PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/stressbalance/PISMStressBalance_diagnostics.cc

Go to the documentation of this file.
00001 // Copyright (C) 2010, 2011 Constantine Khroulev
00002 //
00003 // This file is part of PISM.
00004 //
00005 // PISM is free software; you can redistribute it and/or modify it under the
00006 // terms of the GNU General Public License as published by the Free Software
00007 // Foundation; either version 2 of the License, or (at your option) any later
00008 // version.
00009 //
00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013 // details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with PISM; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #include "PISMStressBalance_diagnostics.hh"
00020 #include "Mask.hh"
00021 
00022 void PISMStressBalance::get_diagnostics(map<string, PISMDiagnostic*> &dict) {
00023 
00024   dict["bfrict"] = new PSB_bfrict(this, grid, *variables);
00025   dict["bueler_brown_f"] = new PSB_bueler_brown_f(this, grid, *variables);
00026 
00027   dict["cbar"]     = new PSB_cbar(this,     grid, *variables);
00028   dict["cflx"]     = new PSB_cflx(this,     grid, *variables);
00029   dict["cbase"]    = new PSB_cbase(this,    grid, *variables);
00030   dict["csurf"]    = new PSB_csurf(this,    grid, *variables);
00031 
00032   dict["uvel"]     = new PSB_uvel(this, grid, *variables);
00033   dict["vvel"]     = new PSB_vvel(this, grid, *variables);
00034 
00035   dict["velbar"]   = new PSB_velbar(this,   grid, *variables);
00036   dict["velbase"]  = new PSB_velbase(this,  grid, *variables);
00037   dict["velsurf"]  = new PSB_velsurf(this,  grid, *variables);
00038 
00039   dict["wvel"]     = new PSB_wvel(this,     grid, *variables);
00040   dict["wvelbase"] = new PSB_wvelbase(this, grid, *variables);
00041   dict["wvelsurf"] = new PSB_wvelsurf(this, grid, *variables);
00042   dict["wvel_rel"] = new PSB_wvel_rel(this, grid, *variables);
00043   dict["taud_mag"] = new PSB_taud_mag(this, grid, *variables);
00044 
00045 
00046   stress_balance->get_diagnostics(dict);
00047   modifier->get_diagnostics(dict);
00048 }
00049 
00050 PSB_velbar::PSB_velbar(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00051   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00052 
00053   dof = 2;
00054   vars.resize(dof);
00055 
00056   // set metadata:
00057   vars[0].init_2d("ubar", grid);
00058   vars[1].init_2d("vbar", grid);
00059 
00060   set_attrs("vertical mean of horizontal ice velocity in the X direction",
00061             "land_ice_vertical_mean_x_velocity",
00062             "m s-1", "m year-1", 0);
00063   set_attrs("vertical mean of horizontal ice velocity in the Y direction",
00064             "land_ice_vertical_mean_y_velocity",
00065             "m s-1", "m year-1", 1);
00066 }
00067 
00068 PetscErrorCode PSB_velbar::compute(IceModelVec* &output) {
00069   PetscErrorCode ierr;
00070 
00071   IceModelVec3 *u3, *v3, *w3;
00072   IceModelVec2S *thickness;
00073   IceModelVec2V *result;
00074   PetscScalar *u_ij, *v_ij;
00075 
00076   result = new IceModelVec2V;
00077   ierr = result->create(grid, "bar", false); CHKERRQ(ierr);
00078   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00079   ierr = result->set_metadata(vars[1], 1); CHKERRQ(ierr);
00080 
00081   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00082   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00083 
00084   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00085 
00086   ierr = u3->begin_access(); CHKERRQ(ierr);
00087   ierr = v3->begin_access(); CHKERRQ(ierr);
00088   ierr = thickness->begin_access(); CHKERRQ(ierr);
00089   ierr = result->begin_access(); CHKERRQ(ierr);
00090   
00091   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
00092     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
00093       PetscReal u_sum = 0, v_sum = 0,
00094         thk = (*thickness)(i,j);
00095       PetscInt ks = grid.kBelowHeight(thk);
00096 
00097       // an "ice-free" cell:
00098       if (thk < 0.1) {
00099         (*result)(i,j).u = 0;
00100         (*result)(i,j).v = 0;
00101         continue;
00102       }
00103 
00104       // an ice-filled cell:
00105       ierr = u3->getInternalColumn(i, j, &u_ij); CHKERRQ(ierr);
00106       ierr = v3->getInternalColumn(i, j, &v_ij); CHKERRQ(ierr);
00107 
00108       if (thk <= grid.zlevels[1]) {
00109         (*result)(i,j).u = u_ij[0];
00110         (*result)(i,j).v = v_ij[0];
00111         continue;
00112       }
00113       
00114       for (int k = 1; k <= ks; ++k) {
00115         u_sum += (grid.zlevels[k] - grid.zlevels[k-1]) * (u_ij[k] + u_ij[k-1]);
00116         v_sum += (grid.zlevels[k] - grid.zlevels[k-1]) * (v_ij[k] + v_ij[k-1]);
00117       }
00118 
00119       // Finish the trapezoidal rule integration (times 1/2) and turn this
00120       // integral into a vertical average. Note that we ignore the ice between
00121       // zlevels[ks] and the surface, so in order to have a true average we
00122       // divide by zlevels[ks] and not thk.
00123       (*result)(i,j).u = 0.5 * u_sum / grid.zlevels[ks];
00124       (*result)(i,j).v = 0.5 * v_sum / grid.zlevels[ks];
00125     }
00126   }
00127 
00128   ierr = result->end_access(); CHKERRQ(ierr);  
00129   ierr = thickness->end_access(); CHKERRQ(ierr);
00130   ierr = v3->end_access(); CHKERRQ(ierr);
00131   ierr = u3->end_access(); CHKERRQ(ierr);
00132 
00133   output = result;
00134   return 0;
00135 }
00136 
00137 PSB_cbar::PSB_cbar(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00138   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00139 
00140   // set metadata:
00141   vars[0].init_2d("cbar", grid);
00142 
00143   set_attrs("magnitude of vertically-integrated horizontal velocity of ice", "",
00144             "m s-1", "m year-1", 0);
00145   vars[0].set("_FillValue", convert(-0.01, "m/year", "m/second"));
00146   vars[0].set("valid_min", 0.0);
00147 }
00148 
00149 PetscErrorCode PSB_cbar::compute(IceModelVec* &output) {
00150   PetscErrorCode ierr;
00151   IceModelVec *tmp;
00152   IceModelVec2V *velbar_vec;
00153   IceModelVec2S *thickness, *result;
00154 
00155   // get the thickness
00156   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00157   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00158 
00159   result = new IceModelVec2S;
00160   ierr = result->create(grid, "cbar", false);
00161   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr); 
00162 
00163   // compute vertically-averaged horizontal velocity:
00164   PSB_velbar velbar(model, grid, variables);
00165   ierr = velbar.compute(tmp); CHKERRQ(ierr);
00166 
00167   velbar_vec = dynamic_cast<IceModelVec2V*>(tmp);
00168   if (velbar_vec == NULL) SETERRQ(1, "dynamic cast failure");
00169 
00170   // compute its magnitude:
00171   ierr = velbar_vec->magnitude(*result); CHKERRQ(ierr);
00172 
00173   // mask out ice-free areas:
00174   ierr = result->mask_by(*thickness, convert(-0.01, "m/year", "m/second")); CHKERRQ(ierr);
00175 
00176   delete tmp;
00177   output = result;
00178   return 0;
00179 }
00180 
00181 PSB_cflx::PSB_cflx(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00182   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00183 
00184   // set metadata:
00185   vars[0].init_2d("cflx", grid);
00186 
00187   set_attrs("magnitude of vertically-integrated horizontal flux of ice", "",
00188             "m2 s-1", "m2 year-1", 0);
00189   vars[0].set("_FillValue", convert(-0.01, "m2/year", "m2/second"));
00190   vars[0].set("valid_min", 0.0);
00191 }
00192 
00193 PetscErrorCode PSB_cflx::compute(IceModelVec* &output) {
00194   PetscErrorCode ierr;
00195   IceModelVec2S *thickness, *result;
00196   IceModelVec *tmp;
00197 
00198   // get the thickness
00199   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00200   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00201 
00202   // Compute the vertically-average horizontal ice velocity:
00203   PSB_cbar cbar(model, grid, variables);
00204   ierr = cbar.compute(tmp); CHKERRQ(ierr);
00205   // NB: the call above allocates memory
00206 
00207   result = dynamic_cast<IceModelVec2S*>(tmp);
00208   if (result == NULL) SETERRQ(1, "dynamic_cast failure");
00209 
00210   ierr = thickness->begin_access(); CHKERRQ(ierr);
00211   ierr = result->begin_access(); CHKERRQ(ierr);
00212   
00213   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i)
00214     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j)
00215       (*result)(i,j) *= (*thickness)(i,j);
00216 
00217   ierr = result->end_access(); CHKERRQ(ierr);
00218   ierr = thickness->end_access(); CHKERRQ(ierr);
00219 
00220   ierr = result->mask_by(*thickness, convert(-0.01, "m2/year", "m2/second")); CHKERRQ(ierr);
00221 
00222   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00223 
00224   output = result;
00225   return 0;
00226 }
00227 
00228 PSB_cbase::PSB_cbase(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00229  : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00230 
00231   // set metadata:
00232   vars[0].init_2d("cbase", grid);
00233 
00234   set_attrs("magnitude of horizontal velocity of ice at base of ice", "",
00235             "m s-1", "m year-1", 0);
00236   vars[0].set("_FillValue", convert(-0.01, "m/year", "m/second"));
00237   vars[0].set("valid_min", 0.0);
00238 }
00239 
00240 PetscErrorCode PSB_cbase::compute(IceModelVec* &output) {
00241   PetscErrorCode ierr;
00242   PetscScalar fill_value = convert(-0.01, "m/year", "m/second");
00243   IceModelVec3 *u3, *v3, *w3;
00244   IceModelVec2S tmp, *result, *thickness;
00245 
00246   ierr = tmp.create(grid, "tmp", false); CHKERRQ(ierr);
00247 
00248   result = new IceModelVec2S;
00249   ierr = result->create(grid, "cbase", false); CHKERRQ(ierr);
00250   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00251 
00252   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr); 
00253 
00254   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00255   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00256 
00257   ierr = u3->getHorSlice(*result, 0.0); CHKERRQ(ierr); // result = u_{z=0}
00258   ierr = v3->getHorSlice(tmp, 0.0); CHKERRQ(ierr);    // tmp = v_{z=0}
00259 
00260   ierr = result->set_to_magnitude(*result, tmp); CHKERRQ(ierr);
00261 
00262   ierr = result->mask_by(*thickness, fill_value); CHKERRQ(ierr); // mask out ice-free areas
00263 
00264   output = result;
00265   return 0;
00266 }
00267 
00268 PSB_csurf::PSB_csurf(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00269   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00270   PetscReal fill_value = convert(-0.01, "m/year", "m/second");
00271   // set metadata:
00272   vars[0].init_2d("csurf", grid);
00273   
00274   set_attrs("magnitude of horizontal velocity of ice at ice surface", "",
00275             "m s-1", "m year-1", 0);
00276   vars[0].set("_FillValue", fill_value);
00277   vars[0].set("valid_min",  0.0);
00278 }
00279 
00280 PetscErrorCode PSB_csurf::compute(IceModelVec* &output) {
00281   PetscErrorCode ierr;
00282   PetscReal fill_value = convert(-0.01, "m/year", "m/second");
00283 
00284   IceModelVec3 *u3, *v3, *w3;
00285   IceModelVec2S tmp, *result, *thickness;
00286 
00287   ierr = tmp.create(grid, "tmp", false); CHKERRQ(ierr);
00288 
00289   result = new IceModelVec2S;
00290   ierr = result->create(grid, "csurf", false); CHKERRQ(ierr);
00291   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00292 
00293   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr); 
00294 
00295   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00296   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00297 
00298   ierr = u3->getSurfaceValues(*result, *thickness); CHKERRQ(ierr);
00299   ierr = v3->getSurfaceValues(tmp, *thickness); CHKERRQ(ierr);
00300 
00301   ierr = result->set_to_magnitude(*result, tmp); CHKERRQ(ierr);
00302 
00303   ierr = result->mask_by(*thickness, fill_value); CHKERRQ(ierr); // mask out ice-free areas
00304 
00305   output = result;
00306   return 0;
00307 }
00308 
00309 
00310 PSB_velsurf::PSB_velsurf(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00311   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00312   
00313   // set metadata:
00314   dof = 2;
00315   vars.resize(dof);
00316   
00317   vars[0].init_2d("uvelsurf", grid);
00318   vars[1].init_2d("vvelsurf", grid);
00319   
00320   set_attrs("x-component of the horizontal velocity of ice at ice surface", "",
00321             "m s-1", "m year-1", 0);
00322   set_attrs("y-component of the horizontal velocity of ice at ice surface", "",
00323             "m s-1", "m year-1", 1);
00324 
00325   vars[0].set("valid_min", convert(-1e6, "m/year", "m/second"));
00326   vars[0].set("valid_max", convert(1e6, "m/year", "m/second"));
00327 
00328   vars[1].set("valid_min", convert(-1e6, "m/year", "m/second"));
00329   vars[1].set("valid_max", convert(1e6, "m/year", "m/second"));
00330 }
00331 
00332 PetscErrorCode PSB_velsurf::compute(IceModelVec* &output) {
00333   PetscErrorCode ierr;
00334   IceModelVec2V *result;
00335   IceModelVec3 *u3, *v3, *w3;
00336   IceModelVec2S *thickness, tmp;
00337 
00338   result = new IceModelVec2V;
00339   ierr = result->create(grid, "surf", false); CHKERRQ(ierr);
00340   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00341   ierr = result->set_metadata(vars[1], 1); CHKERRQ(ierr);
00342 
00343   ierr = tmp.create(grid, "tmp", false); CHKERRQ(ierr);
00344 
00345   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00346 
00347   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00348   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00349 
00350   ierr = u3->getSurfaceValues(tmp, *thickness); CHKERRQ(ierr);
00351   ierr = result->set_component(0, tmp); CHKERRQ(ierr); 
00352 
00353   ierr = v3->getSurfaceValues(tmp, *thickness); CHKERRQ(ierr);
00354   ierr = result->set_component(1, tmp); CHKERRQ(ierr); 
00355 
00356   output = result;
00357   return 0;
00358 }
00359 
00360 PSB_wvel::PSB_wvel(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00361   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00362   
00363   // set metadata:
00364   vars[0].init_3d("wvel", grid, g.zlevels);
00365   
00366   set_attrs("vertical velocity of ice, relative to geoid", "",
00367             "m s-1", "m year-1", 0);
00368   vars[0].set("valid_min", convert(-1e6, "m/year", "m/second"));
00369   vars[0].set("valid_max", convert(1e6, "m/year", "m/second"));
00370 }
00371 
00372 PetscErrorCode PSB_wvel::compute(IceModelVec* &output) {
00373   PetscErrorCode ierr;
00374   IceModelVec3 *result, *u3, *v3, *w3;
00375   IceModelVec2S *bed, *uplift;
00376   PetscScalar *u, *v, *w, *res;
00377 
00378   result = new IceModelVec3;
00379   ierr = result->create(grid, "wvel", false); CHKERRQ(ierr);
00380   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00381 
00382   bed = dynamic_cast<IceModelVec2S*>(variables.get("bedrock_altitude"));
00383   if (bed == NULL) SETERRQ(1, "bedrock_altitude is not available");
00384 
00385   uplift = dynamic_cast<IceModelVec2S*>(variables.get("tendency_of_bedrock_altitude"));
00386   if (uplift == NULL) SETERRQ(1, "tendency_of_bedrock_altitude is not available");
00387 
00388   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00389 
00390   ierr = bed->begin_access(); CHKERRQ(ierr);
00391   ierr = u3->begin_access(); CHKERRQ(ierr);
00392   ierr = v3->begin_access(); CHKERRQ(ierr);
00393   ierr = w3->begin_access(); CHKERRQ(ierr);
00394   ierr = uplift->begin_access(); CHKERRQ(ierr); 
00395   ierr = result->begin_access(); CHKERRQ(ierr);
00396 
00397   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00398     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00399       ierr = u3->getInternalColumn(i, j, &u); CHKERRQ(ierr);
00400       ierr = v3->getInternalColumn(i, j, &v); CHKERRQ(ierr);
00401       ierr = w3->getInternalColumn(i, j, &w); CHKERRQ(ierr);
00402       ierr = result->getInternalColumn(i, j, &res); CHKERRQ(ierr);
00403 
00404       for (PetscInt k = 0; k < grid.Mz; ++k)
00405         res[k] = w[k] + (*uplift)(i,j) + u[k] * bed->diff_x_p(i,j) + v[k] * bed->diff_y_p(i,j);
00406     }
00407   }
00408 
00409   ierr = result->end_access(); CHKERRQ(ierr);
00410   ierr = uplift->end_access(); CHKERRQ(ierr);
00411   ierr = w3->end_access(); CHKERRQ(ierr);
00412   ierr = v3->end_access(); CHKERRQ(ierr);
00413   ierr = u3->end_access(); CHKERRQ(ierr);
00414   ierr = bed->end_access(); CHKERRQ(ierr); 
00415 
00416   output = result;
00417   return 0;
00418 }
00419 
00420 PSB_wvelsurf::PSB_wvelsurf(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00421   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00422   
00423   // set metadata:
00424   vars[0].init_2d("wvelsurf", grid);
00425   
00426   set_attrs("vertical velocity of ice at ice surface, relative to the geoid", "",
00427             "m s-1", "m year-1", 0);
00428   vars[0].set("valid_min", convert(-1e6, "m/year", "m/second"));
00429   vars[0].set("valid_max", convert(1e6, "m/year", "m/second"));
00430 }
00431 
00432 PetscErrorCode PSB_wvelsurf::compute(IceModelVec* &output) {
00433   PetscErrorCode ierr;
00434   IceModelVec *tmp;
00435   IceModelVec3 *w3;
00436   IceModelVec2S *result, *thickness;
00437 
00438   result = new IceModelVec2S;
00439   ierr = result->create(grid, "wvelsurf", false); CHKERRQ(ierr);
00440   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00441 
00442   PSB_wvel wvel(model, grid, variables);
00443 
00444   ierr = wvel.compute(tmp); CHKERRQ(ierr);
00445 
00446   w3 = dynamic_cast<IceModelVec3*>(tmp);
00447   if (tmp == NULL) SETERRQ(1, "dynamic_cast failure");
00448 
00449   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00450   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00451 
00452   ierr = w3->getSurfaceValues(*result, *thickness); CHKERRQ(ierr);
00453 
00454   delete tmp;
00455   output = result;
00456   return 0;
00457 }
00458 
00459 PSB_wvelbase::PSB_wvelbase(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00460   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00461   
00462   // set metadata:
00463   vars[0].init_2d("wvelbase", grid);
00464   
00465   set_attrs("vertical velocity of ice at the base of ice, relative to the geoid", "",
00466             "m s-1", "m year-1", 0);
00467   vars[0].set("valid_min", convert(-1e6, "m/year", "m/second"));
00468   vars[0].set("valid_max", convert(1e6, "m/year", "m/second"));
00469 }
00470 
00471 PetscErrorCode PSB_wvelbase::compute(IceModelVec* &output) {
00472   PetscErrorCode ierr;
00473   IceModelVec *tmp;
00474   IceModelVec3 *w3;
00475   IceModelVec2S *result;
00476 
00477   result = new IceModelVec2S;
00478   ierr = result->create(grid, "wvelbase", false); CHKERRQ(ierr);
00479   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00480 
00481   PSB_wvel wvel(model, grid, variables);
00482 
00483   ierr = wvel.compute(tmp); CHKERRQ(ierr);
00484 
00485   w3 = dynamic_cast<IceModelVec3*>(tmp);
00486   if (tmp == NULL) SETERRQ(1, "dynamic_cast failure");
00487 
00488   ierr = w3->getHorSlice(*result, 0.0); CHKERRQ(ierr);
00489 
00490   delete tmp;
00491   output = result;
00492   return 0;
00493 }
00494 
00495 PSB_velbase::PSB_velbase(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00496   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00497     
00498   // set metadata:
00499   dof = 2;
00500   vars.resize(dof);
00501   
00502   vars[0].init_2d("uvelbase", grid);
00503   vars[1].init_2d("vvelbase", grid);
00504   
00505   set_attrs("x-component of the horizontal velocity of ice at the base of ice", "",
00506             "m s-1", "m year-1", 0);
00507   set_attrs("y-component of the horizontal velocity of ice at the base of ice", "",
00508             "m s-1", "m year-1", 1);
00509 
00510   vars[0].set("valid_min", convert(-1e6, "m/year", "m/second"));
00511   vars[0].set("valid_max", convert(1e6, "m/year", "m/second"));
00512 
00513   vars[1].set("valid_min", convert(-1e6, "m/year", "m/second"));
00514   vars[1].set("valid_max", convert(1e6, "m/year", "m/second"));
00515 }
00516 
00517 PetscErrorCode PSB_velbase::compute(IceModelVec* &output) {
00518   PetscErrorCode ierr;
00519   IceModelVec2V *result;
00520   IceModelVec3 *u3, *v3, *w3;
00521   IceModelVec2S tmp;            // will be de-allocated automatically
00522 
00523   result = new IceModelVec2V;
00524   ierr = result->create(grid, "base", false); CHKERRQ(ierr);
00525   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00526   ierr = result->set_metadata(vars[1], 1); CHKERRQ(ierr);
00527 
00528   ierr = tmp.create(grid, "tmp", false); CHKERRQ(ierr);
00529 
00530   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00531 
00532   ierr = u3->getHorSlice(tmp, 0.0); CHKERRQ(ierr);
00533   ierr = result->set_component(0, tmp); CHKERRQ(ierr); 
00534 
00535   ierr = v3->getHorSlice(tmp, 0.0); CHKERRQ(ierr);
00536   ierr = result->set_component(1, tmp); CHKERRQ(ierr); 
00537 
00538   output = result;
00539   return 0;
00540 }
00541 
00542 PSB_bueler_brown_f::PSB_bueler_brown_f(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00543   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00544   
00545   // set metadata:
00546   vars[0].init_2d("bueler_brown_f", grid);
00547   set_attrs("f(|v|) in Bueler and Brown (2009), equation 22", "",
00548             "", "", 0);
00549   vars[0].set("valid_min", 0);
00550   vars[0].set("valid_max", 1);
00551   vars[0].set("_FillValue", -0.01);
00552 }
00553 
00555 static PetscScalar bueler_brown_f(PetscScalar v_squared) {
00556   const PetscScalar inC_fofv = 1.0e-4 * PetscSqr(secpera),
00557     outC_fofv = 2.0 / pi;
00558   
00559   return 1.0 - outC_fofv * atan(inC_fofv * v_squared);
00560 }
00561 
00562 PetscErrorCode PSB_bueler_brown_f::compute(IceModelVec* &output) {
00563   PetscErrorCode ierr;
00564   IceModelVec2V *vel_ssa;
00565   IceModelVec2S *thickness;
00566   PetscReal fill_value = -0.01;
00567 
00568   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00569   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00570 
00571   IceModelVec2S *result = new IceModelVec2S;
00572   ierr = result->create(grid, "bueler_brown_f", false); CHKERRQ(ierr);
00573   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00574 
00575   ierr = model->get_advective_2d_velocity(vel_ssa); CHKERRQ(ierr);
00576 
00577   ierr = vel_ssa->begin_access(); CHKERRQ(ierr);
00578   ierr = result->begin_access(); CHKERRQ(ierr);
00579 
00580   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i)
00581     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j)
00582       (*result)(i,j) = bueler_brown_f((*vel_ssa)(i,j).magnitude_squared());
00583 
00584   ierr = result->end_access(); CHKERRQ(ierr);
00585   ierr = vel_ssa->end_access(); CHKERRQ(ierr);
00586 
00587   ierr = result->mask_by(*thickness, fill_value); CHKERRQ(ierr);
00588   
00589   output = result;
00590   return 0;
00591 }
00592 
00593 PSB_bfrict::PSB_bfrict(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00594   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00595   
00596   // set metadata:
00597   vars[0].init_2d("bfrict", grid);
00598   
00599   set_attrs("basal frictional heating", "",
00600             "W m-2", "W m-2", 0);
00601 }
00602 
00603 PetscErrorCode PSB_bfrict::compute(IceModelVec* &output) {
00604   PetscErrorCode ierr;
00605   
00606   IceModelVec2S *result = new IceModelVec2S;
00607   ierr = result->create(grid, "bfrict", false); CHKERRQ(ierr);
00608   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00609 
00610   IceModelVec2S *bfrict;
00611   ierr = model->get_basal_frictional_heating(bfrict); CHKERRQ(ierr);  
00612 
00613   ierr = bfrict->copy_to(*result); CHKERRQ(ierr);
00614 
00615   output = result;
00616   return 0;
00617 }
00618 
00619 
00620 PSB_uvel::PSB_uvel(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00621   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00622   
00623   // set metadata:
00624   vars[0].init_3d("uvel", grid, g.zlevels);
00625   
00626   set_attrs("horizontal velocity of ice in the X direction", "land_ice_x_velocity",
00627             "m s-1", "m year-1", 0);
00628 }
00629 
00630 PetscErrorCode PSB_uvel::compute(IceModelVec* &output) {
00631   PetscErrorCode ierr;
00632   
00633   IceModelVec3 *result = new IceModelVec3;
00634   ierr = result->create(grid, "uvel", false); CHKERRQ(ierr);
00635   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00636 
00637   IceModelVec2S *thickness;
00638   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00639   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00640 
00641   IceModelVec3 *u3, *v3, *w3;
00642   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00643 
00644   ierr = u3->begin_access(); CHKERRQ(ierr);
00645   ierr = result->begin_access(); CHKERRQ(ierr);
00646   ierr = thickness->begin_access(); CHKERRQ(ierr);
00647 
00648   PetscScalar *u_ij, *u_out_ij;
00649   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
00650     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
00651       int ks = grid.kBelowHeight((*thickness)(i,j));
00652 
00653       ierr = u3->getInternalColumn(i,j,&u_ij); CHKERRQ(ierr);
00654       ierr = result->getInternalColumn(i,j,&u_out_ij); CHKERRQ(ierr);
00655 
00656       // in the ice:
00657       for (int k = 0; k <= ks ; k++) {
00658         u_out_ij[k] = u_ij[k];
00659       }
00660       // above the ice:
00661       for (int k = ks+1; k < grid.Mz ; k++) {
00662         u_out_ij[k] = 0.0;
00663       }
00664     }
00665   }
00666 
00667   ierr = thickness->end_access(); CHKERRQ(ierr);  
00668   ierr = result->end_access(); CHKERRQ(ierr);
00669   ierr = u3->end_access(); CHKERRQ(ierr);
00670   
00671   output = result;
00672   return 0;
00673 }
00674 
00675 PSB_vvel::PSB_vvel(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00676   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00677   
00678   // set metadata:
00679   vars[0].init_3d("vvel", grid, g.zlevels);
00680   
00681   set_attrs("horizontal velocity of ice in the Y direction", "land_ice_y_velocity",
00682             "m s-1", "m year-1", 0);
00683 }
00684 
00685 PetscErrorCode PSB_vvel::compute(IceModelVec* &output) {
00686   PetscErrorCode ierr;
00687   
00688   IceModelVec3 *result = new IceModelVec3;
00689   ierr = result->create(grid, "vvel", false); CHKERRQ(ierr);
00690   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00691 
00692   IceModelVec2S *thickness;
00693   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00694   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00695 
00696   IceModelVec3 *u3, *v3, *w3;
00697   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00698 
00699   ierr = v3->begin_access(); CHKERRQ(ierr);
00700   ierr = result->begin_access(); CHKERRQ(ierr);
00701   ierr = thickness->begin_access(); CHKERRQ(ierr);
00702 
00703   PetscScalar *v_ij, *v_out_ij;
00704   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
00705     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
00706       int ks = grid.kBelowHeight((*thickness)(i,j));
00707 
00708       ierr = v3->getInternalColumn(i,j,&v_ij); CHKERRQ(ierr);
00709       ierr = result->getInternalColumn(i,j,&v_out_ij); CHKERRQ(ierr);
00710 
00711       // in the ice:
00712       for (int k = 0; k <= ks ; k++) {
00713         v_out_ij[k] = v_ij[k];
00714       }
00715       // above the ice:
00716       for (int k = ks+1; k < grid.Mz ; k++) {
00717         v_out_ij[k] = 0.0;
00718       }
00719     }
00720   }
00721 
00722   ierr = thickness->end_access(); CHKERRQ(ierr);  
00723   ierr = result->end_access(); CHKERRQ(ierr);
00724   ierr = v3->end_access(); CHKERRQ(ierr);
00725   
00726   output = result;
00727   return 0;
00728 }
00729 
00730 PSB_wvel_rel::PSB_wvel_rel(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00731   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00732   
00733   // set metadata:
00734   vars[0].init_3d("wvel_rel", grid, g.zlevels);
00735   
00736   set_attrs("vertical velocity of ice, relative to base of ice directly below", "",
00737             "m s-1", "m year-1", 0);
00738 }
00739 
00740 PetscErrorCode PSB_wvel_rel::compute(IceModelVec* &output) {
00741   PetscErrorCode ierr;
00742   
00743   IceModelVec3 *result = new IceModelVec3;
00744   ierr = result->create(grid, "wvel_rel", false); CHKERRQ(ierr);
00745   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00746 
00747   IceModelVec2S *thickness;
00748   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00749   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00750 
00751   IceModelVec3 *u3, *v3, *w3;
00752   ierr = model->get_3d_velocity(u3, v3, w3); CHKERRQ(ierr);
00753 
00754   ierr = w3->begin_access(); CHKERRQ(ierr);
00755   ierr = result->begin_access(); CHKERRQ(ierr);
00756   ierr = thickness->begin_access(); CHKERRQ(ierr);
00757 
00758   PetscScalar *w_ij, *w_out_ij;
00759   for (PetscInt   i = grid.xs; i < grid.xs+grid.xm; ++i) {
00760     for (PetscInt j = grid.ys; j < grid.ys+grid.ym; ++j) {
00761       int ks = grid.kBelowHeight((*thickness)(i,j));
00762 
00763       ierr = w3->getInternalColumn(i,j,&w_ij); CHKERRQ(ierr);
00764       ierr = result->getInternalColumn(i,j,&w_out_ij); CHKERRQ(ierr);
00765 
00766       // in the ice:
00767       for (int k = 0; k <= ks ; k++) {
00768         w_out_ij[k] = w_ij[k];
00769       }
00770       // above the ice:
00771       for (int k = ks+1; k < grid.Mz ; k++) {
00772         w_out_ij[k] = 0.0;
00773       }
00774     }
00775   }
00776 
00777   ierr = thickness->end_access(); CHKERRQ(ierr);  
00778   ierr = result->end_access(); CHKERRQ(ierr);
00779   ierr = w3->end_access(); CHKERRQ(ierr);
00780   
00781   output = result;
00782   return 0;
00783 }
00784 
00785 PSB_taud_mag::PSB_taud_mag(PISMStressBalance *m, IceGrid &g, PISMVars &my_vars)
00786   : PISMDiag<PISMStressBalance>(m, g, my_vars) {
00787   
00788   // set metadata:
00789   vars[0].init_2d("taud_mag", grid);
00790   
00791   set_attrs("magnitude of the driving shear stress at the base of ice", "",
00792             "Pa", "Pa", 0);
00793 }
00794 
00795 PetscErrorCode PSB_taud_mag::compute(IceModelVec* &output) {
00796   PetscErrorCode ierr;
00797 
00798   // Allocate memory:
00799   IceModelVec2S *result = new IceModelVec2S;
00800   ierr = result->create(grid, "taud_mag", false); CHKERRQ(ierr);
00801   ierr = result->set_metadata(vars[0], 0); CHKERRQ(ierr);
00802   result->write_in_glaciological_units = true;
00803 
00804   IceModelVec2S *thickness, *surface, *bed;
00805   IceModelVec2Int *mask;
00806 
00807   thickness = dynamic_cast<IceModelVec2S*>(variables.get("land_ice_thickness"));
00808   if (thickness == NULL) SETERRQ(1, "land_ice_thickness is not available");
00809 
00810   surface = dynamic_cast<IceModelVec2S*>(variables.get("surface_altitude"));
00811   if (surface == NULL) SETERRQ(1, "surface_altitude is not available");
00812 
00813   bed = dynamic_cast<IceModelVec2S*>(variables.get("bedrock_altitude"));
00814   if (bed == NULL) SETERRQ(1, "bedrock_altitude is not available");
00815 
00816   mask = dynamic_cast<IceModelVec2Int*>(variables.get("mask"));
00817   if (mask == NULL) SETERRQ(1, "mask is not available");
00818 
00819   IceModelVec2S &thk = *thickness; // to improve readability (below)
00820 
00821   const PetscScalar n       = model->config.get("Glen_exponent"), // frequently n = 3
00822                     etapow  = (2.0 * n + 2.0)/n,  // = 8/3 if n = 3
00823                     invpow  = 1.0 / etapow,  // = 3/8
00824                     dinvpow = (- n - 2.0) / (2.0 * n + 2.0); // = -5/8
00825   const PetscScalar minThickEtaTransform = 5.0; // m
00826   const PetscScalar dx=grid.dx, dy=grid.dy;
00827 
00828   PetscReal standard_gravity = model->config.get("standard_gravity"),
00829     ice_density = model->config.get("ice_density");
00830   bool use_eta = (model->config.get_string("surface_gradient_method") == "eta");
00831 
00832   MaskQuery M(*mask);
00833 
00834   ierr =   surface->begin_access();    CHKERRQ(ierr);
00835   ierr =       bed->begin_access();  CHKERRQ(ierr);
00836   ierr =      mask->begin_access();  CHKERRQ(ierr);
00837   ierr =        thk.begin_access();  CHKERRQ(ierr);
00838 
00839   ierr = result->begin_access(); CHKERRQ(ierr);
00840 
00841   PetscReal result_ij_u, result_ij_v;
00842   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00843     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00844       const PetscScalar pressure = ice_density * standard_gravity * thk(i,j);
00845       if (pressure <= 0.0) {
00846         result_ij_u = 0.0;
00847         result_ij_v = 0.0;
00848       } else {
00849         PetscScalar h_x = 0.0, h_y = 0.0;
00850         // FIXME: we need to handle grid periodicity correctly.
00851         if (M.grounded(i,j) && (use_eta == true)) {
00852                 // in grounded case, differentiate eta = H^{8/3} by chain rule
00853           if (thk(i,j) > 0.0) {
00854             const PetscScalar myH = (thk(i,j) < minThickEtaTransform ?
00855                                      minThickEtaTransform : thk(i,j));
00856             const PetscScalar eta = pow(myH, etapow), factor = invpow * pow(eta, dinvpow);
00857             h_x = factor * (pow(thk(i+1,j),etapow) - pow(thk(i-1,j),etapow)) / (2*dx);
00858             h_y = factor * (pow(thk(i,j+1),etapow) - pow(thk(i,j-1),etapow)) / (2*dy);
00859           }
00860           // now add bed slope to get actual h_x,h_y
00861           // FIXME: there is no reason to assume user's bed is periodized
00862           h_x += bed->diff_x(i,j);
00863           h_y += bed->diff_y(i,j);
00864         } else {  // floating or eta transformation is not used
00865             h_x = surface->diff_x(i,j);
00866             h_y = surface->diff_y(i,j);
00867         }
00868 
00869         result_ij_u = - pressure * h_x;
00870         result_ij_v = - pressure * h_y;
00871       }
00872 
00873       (*result)(i,j) = sqrt(PetscSqr(result_ij_u) + PetscSqr(result_ij_v));
00874     }
00875   }
00876 
00877   ierr =        thk.end_access(); CHKERRQ(ierr);
00878   ierr =       bed->end_access(); CHKERRQ(ierr);
00879   ierr =   surface->end_access(); CHKERRQ(ierr);
00880   ierr =      mask->end_access(); CHKERRQ(ierr);
00881   ierr =     result->end_access(); CHKERRQ(ierr);
00882   
00883   output = result;
00884   return 0;
00885 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines