PISM, A Parallel Ice Sheet Model  stable v0.5
src/eismint/iceEISModel.cc
Go to the documentation of this file.
00001 // Copyright (C) 2004-2011 Jed Brown, Ed Bueler and 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 "IceGrid.hh"
00020 #include "iceModel.hh"
00021 #include "iceEISModel.hh"
00022 #include "SIAFD.hh"
00023 #include "SIA_Sliding.hh"
00024 #include "PISMStressBalance.hh"
00025 #include "pism_options.hh"
00026 
00027 IceEISModel::IceEISModel(IceGrid &g, NCConfigVariable &conf, NCConfigVariable &conf_overrides)
00028   : IceModel(g, conf, conf_overrides) {
00029   expername = 'A';
00030 
00031   // the following flag must be here in constructor because IceModel::createVecs()
00032   // uses it
00033   // non-polythermal methods; can be overridden by the command-line option -no_cold:
00034   config.set_flag("do_cold_ice_methods", true);
00035 
00036   // see EISMINT II description; choose no ocean interaction, purely SIA, and E=1
00037   config.set_flag("is_dry_simulation", true);
00038   config.set_flag("use_ssa_velocity", false);
00039 }
00040 
00041 PetscErrorCode IceEISModel::createVecs() {
00042   PetscErrorCode ierr = IceModel::createVecs(); CHKERRQ(ierr);
00043 
00044   // this ensures that these variables are saved to an output file and are read
00045   // back in if -i option is used (they are "model_state", in a sense, since
00046   // PSDummy is used):
00047   ierr = variables.add(artm); CHKERRQ(ierr);
00048   ierr = variables.add(acab); CHKERRQ(ierr);
00049   ierr = artm.set_attr("pism_intent", "model_state"); CHKERRQ(ierr);
00050   ierr = acab.set_attr("pism_intent", "model_state"); CHKERRQ(ierr);
00051 
00052   return 0;
00053 }
00054 
00056 PetscErrorCode IceEISModel::set_grid_defaults() {
00057   grid.Lx = 750e3;
00058   grid.Ly = 750e3;
00059   grid.Lz = 4e3;  // depend on auto-expansion to handle bigger thickness
00060 
00061   PetscErrorCode ierr =  grid.time->init(); CHKERRQ(ierr);
00062 
00063   return 0;
00064 }
00065 
00066 
00068 
00069 PetscErrorCode IceEISModel::set_expername_from_options() {
00070   PetscErrorCode      ierr;
00071 
00072   string eisIIexpername = "A";
00073   char temp = expername;
00074   bool EISIIchosen;
00075   ierr = PISMOptionsString("-eisII", "EISMINT II experiment name",
00076                            eisIIexpername, EISIIchosen);
00077             CHKERRQ(ierr);
00078   if (EISIIchosen == PETSC_TRUE) {
00079     temp = (char)toupper(eisIIexpername.c_str()[0]);
00080     if ((temp >= 'A') && (temp <= 'L')) {
00081       expername = temp;
00082     } else {
00083       ierr = PetscPrintf(grid.com,
00084         "option -eisII must have value A, B, C, D, E, F, G, H, I, J, K, or L\n");
00085         CHKERRQ(ierr);
00086       PISMEnd();
00087     }
00088   }
00089 
00090   char tempstr[TEMPORARY_STRING_LENGTH];
00091   snprintf(tempstr, TEMPORARY_STRING_LENGTH, "%c", temp);
00092 
00093   config.set_string("EISMINT_II_experiment", tempstr);
00094 
00095   return 0;
00096 }
00097 
00098 
00099 PetscErrorCode IceEISModel::setFromOptions() {
00100   PetscErrorCode      ierr;
00101 
00102   ierr = PetscOptionsBegin(grid.com, "", "IceEISModel options", ""); CHKERRQ(ierr);
00103 
00104   ierr = set_expername_from_options(); CHKERRQ(ierr);
00105 
00106   config.set("sia_enhancement_factor", 1.0);
00107   config.set("bed_smoother_range", 0.0);  // none use bed smoothing & bed roughness
00108                                           // parameterization
00109   // basal melt does not change computation of mass continuity or vertical velocity:
00110   config.set_flag("include_bmr_in_continuity", false);
00111 
00112   ierr = verbPrintf(2,grid.com, 
00113     "setting parameters for surface mass balance and temperature in EISMINT II experiment %c ... \n", 
00114     expername); CHKERRQ(ierr);
00115   // EISMINT II specified values for parameters
00116   S_b = convert(1.0e-2 * 1e-3, "1/year", "1/s");    // Grad of accum rate change
00117   S_T = 1.67e-2 * 1e-3;           // K/m  Temp gradient
00118   // these are for A,E,G,H,I,K:
00119   M_max = convert(0.5, "m/year", "m/s");  // Max accumulation
00120   R_el = 450.0e3;           // Distance to equil line (accum=0)
00121   T_min = 238.15;
00122   switch (expername) {
00123     case 'B':  // supposed to start from end of experiment A and:
00124       T_min = 243.15;
00125       break;
00126     case 'C':
00127     case 'J':
00128     case 'L':  // supposed to start from end of experiment A (for C;
00129                //   resp I and K for J and L) and:
00130       M_max = convert(0.25, "m/year", "m/s");
00131       R_el = 425.0e3;
00132       break;
00133     case 'D':  // supposed to start from end of experiment A and:
00134       R_el = 425.0e3;
00135       break;
00136     case 'F':  // start with zero ice and:
00137       T_min = 223.15;
00138       break;
00139   }
00140 
00141   // if user specifies Tmin, Tmax, Mmax, Sb, ST, Rel, then use that (override above)
00142   bool paramSet;
00143   ierr = PISMOptionsReal("-Tmin", "T min, Kelvin",
00144                          T_min, paramSet); CHKERRQ(ierr);
00145   ierr = PISMOptionsReal("-Tmax", "T max, Kelvin",
00146                          T_max, paramSet); CHKERRQ(ierr);
00147 
00148   PetscReal myMmax = convert(M_max, "m/s", "m/year"),
00149     mySb = S_b * secpera / 1e3,
00150     myST = S_T / 1e3,
00151     myRel = R_el / 1e3;
00152   ierr = PISMOptionsReal("-Mmax", "Maximum accumulation, m/year",
00153                          myMmax, paramSet); CHKERRQ(ierr);
00154   if (paramSet)     M_max = myMmax / secpera;
00155 
00156   ierr = PISMOptionsReal("-Sb", "radial gradient of accumulation rate, (m/a)/km",
00157                          mySb, paramSet); CHKERRQ(ierr);
00158   if (paramSet)     S_b = mySb * 1e-3 / secpera;
00159 
00160   ierr = PISMOptionsReal("-ST", "radial gradient of surface temperature, K/km",
00161                          myST, paramSet); CHKERRQ(ierr);
00162   if (paramSet)     S_T = myST * 1e-3;
00163 
00164   ierr = PISMOptionsReal("-Rel", "radial distance to equilibrium line, km",
00165                          myRel, paramSet); CHKERRQ(ierr);
00166   if (paramSet)     R_el = myRel * 1e3;
00167 
00168   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00169 
00170   ierr = IceModel::setFromOptions();  CHKERRQ(ierr);
00171 
00172   return 0;
00173 }
00174 
00176 PetscErrorCode  IceEISModel::allocate_flowlaw() {
00177   PetscErrorCode ierr;
00178 
00179   ierr = IceModel::allocate_flowlaw(); CHKERRQ(ierr);
00180 
00181   // Make bedrock thermal material properties into ice properties.  Note that
00182   // zero thickness bedrock layer is the default, but we want the ice/rock
00183   // interface segment to have geothermal flux applied directly to ice without
00184   // jump in material properties at base.
00185   config.set("bedrock_thermal_density", config.get("ice_density"));
00186   config.set("bedrock_thermal_conductivity", config.get("ice_thermal_conductivity"));
00187   config.set("bedrock_thermal_specific_heat_capacity", config.get("ice_specific_heat_capacity"));
00188 
00189   return 0;
00190 }
00191 
00193 PetscErrorCode IceEISModel::allocate_stressbalance() {
00194   PetscErrorCode ierr;
00195 
00196   if (stress_balance == NULL) {
00197     ShallowStressBalance *my_stress_balance;
00198 
00199     SSB_Modifier *modifier = new SIAFD(grid, *EC, config);
00200 
00201     if (expername == 'G' || expername == 'H') {
00202       my_stress_balance = new SIA_Sliding(grid, *basal, *EC, config);
00203     } else {
00204       my_stress_balance = new SSB_Trivial(grid, *basal, *EC, config);
00205     }
00206   
00207     // ~PISMStressBalance() will de-allocate my_stress_balance and modifier.
00208     stress_balance = new PISMStressBalance(grid, my_stress_balance,
00209                                            modifier, NULL, config);
00210 
00211     // Note that in PISM stress balance computations are diagnostic, i.e. do not
00212     // have a state that changes in time. This means that this call can be here
00213     // and not in model_state_setup() and we don't need to re-initialize after
00214     // the "diagnostic time step".
00215     ierr = stress_balance->init(variables); CHKERRQ(ierr);
00216 
00217     if (config.get_flag("include_bmr_in_continuity")) {
00218       ierr = stress_balance->set_basal_melt_rate(&vbmr); CHKERRQ(ierr);
00219     }
00220   }
00221   
00222   return 0;
00223 }
00224 
00225 PetscErrorCode IceEISModel::init_couplers() {
00226   PetscErrorCode      ierr;
00227 
00228   ierr = IceModel::init_couplers(); CHKERRQ(ierr);
00229 
00230   ierr = verbPrintf(2,grid.com,
00231     "  setting surface mass balance and surface temperature variables from formulas...\n");
00232   CHKERRQ(ierr);
00233 
00234   // now fill in accum and surface temp
00235   ierr = artm.begin_access(); CHKERRQ(ierr);
00236   ierr = acab.begin_access(); CHKERRQ(ierr);
00237 
00238   PetscScalar cx = grid.Lx, cy = grid.Ly;
00239   if (expername == 'E') {  cx += 100.0e3;  cy += 100.0e3;  } // shift center
00240   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00241     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00242       // r is distance from center of grid; if E then center is shifted (above)
00243       const PetscScalar r = sqrt( PetscSqr(-cx + grid.dx*i)
00244                                   + PetscSqr(-cy + grid.dy*j) );
00245       // set accumulation from formula (7) in (Payne et al 2000)
00246       acab(i,j) = PetscMin(M_max, S_b * (R_el-r));
00247       // set surface temperature
00248       artm(i,j) = T_min + S_T * r;  // formula (8) in (Payne et al 2000)
00249     }
00250   }
00251 
00252   ierr = artm.end_access(); CHKERRQ(ierr);
00253   ierr = acab.end_access(); CHKERRQ(ierr);
00254   return 0;
00255 }
00256 
00257 
00258 PetscErrorCode IceEISModel::generateTroughTopography() {
00259   PetscErrorCode  ierr;
00260   // computation based on code by Tony Payne, 6 March 1997:
00261   //    http://homepages.vub.ac.be/~phuybrec/eismint/topog2.f
00262   
00263   const PetscScalar    b0 = 1000.0;  // plateau elevation
00264   const PetscScalar    L = 750.0e3;  // half-width of computational domain
00265   const PetscScalar    w = 200.0e3;  // trough width
00266   const PetscScalar    slope = b0/L;
00267   const PetscScalar    dx61 = (2*L) / 60; // = 25.0e3
00268   ierr = vbed.begin_access(); CHKERRQ(ierr);
00269   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00270     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00271       const PetscScalar nsd = i * grid.dx, ewd = j * grid.dy;
00272       if (    (nsd >= (27 - 1) * dx61) && (nsd <= (35 - 1) * dx61)
00273            && (ewd >= (31 - 1) * dx61) && (ewd <= (61 - 1) * dx61) ) {
00274         vbed(i,j) = 1000.0 - PetscMax(0.0, slope * (ewd - L) * cos(pi * (nsd - L) / w));
00275       } else {
00276         vbed(i,j) = 1000.0;
00277       }
00278     }
00279   }
00280   ierr = vbed.end_access(); CHKERRQ(ierr);
00281 
00282   ierr = verbPrintf(2,grid.com,
00283                "trough bed topography stored by IceEISModel::generateTroughTopography()\n");
00284                CHKERRQ(ierr);
00285   return 0;
00286 }
00287 
00288 
00289 PetscErrorCode IceEISModel::generateMoundTopography() {
00290   PetscErrorCode  ierr;
00291   // computation based on code by Tony Payne, 6 March 1997:
00292   //    http://homepages.vub.ac.be/~phuybrec/eismint/topog2.f
00293   
00294   const PetscScalar    slope = 250.0;
00295   const PetscScalar    w = 150.0e3;  // mound width
00296   ierr = vbed.begin_access(); CHKERRQ(ierr);
00297   for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) {
00298     for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) {
00299       const PetscScalar nsd = i * grid.dx, ewd = j * grid.dy;
00300       vbed(i,j) = PetscAbs(slope * sin(pi * ewd / w) + slope * cos(pi * nsd / w));
00301     }
00302   }
00303   ierr = vbed.end_access(); CHKERRQ(ierr);
00304 
00305   ierr = verbPrintf(2,grid.com,
00306     "mound bed topography stored by IceEISModel::generateTroughTopography()\n");
00307     CHKERRQ(ierr);
00308   return 0;
00309 }
00310 
00311 
00313 PetscErrorCode IceEISModel::set_vars_from_options() {
00314   PetscErrorCode ierr;
00315 
00316   // initialize from EISMINT II formulas
00317   ierr = verbPrintf(2,grid.com, 
00318     "initializing variables from EISMINT II experiment %c formulas ... \n", 
00319     expername); CHKERRQ(ierr);
00320 
00321   ierr = vbed.set(0.0);
00322   if ((expername == 'I') || (expername == 'J')) {
00323     ierr = generateTroughTopography(); CHKERRQ(ierr);
00324   } 
00325   if ((expername == 'K') || (expername == 'L')) {
00326     ierr = generateMoundTopography(); CHKERRQ(ierr);
00327   } 
00328   // communicate b in any case; it will be horizontally-differentiated
00329   ierr = vbed.beginGhostComm(); CHKERRQ(ierr);
00330   ierr = vbed.endGhostComm(); CHKERRQ(ierr);
00331 
00332   ierr = vbwat.set(0.0); CHKERRQ(ierr);
00333   ierr = vbmr.set(0.0); CHKERRQ(ierr);
00334   ierr = vGhf.set(0.042); CHKERRQ(ierr);  // EISMINT II value; J m-2 s-1
00335 
00336   ierr = vuplift.set(0.0); CHKERRQ(ierr);  // no expers have uplift at start
00337 
00338   // if no -i file then starts with zero ice
00339   ierr = vh.set(0.0); CHKERRQ(ierr);
00340   ierr = vH.set(0.0); CHKERRQ(ierr);
00341 
00342   ierr = regrid(2); CHKERRQ(ierr);
00343   
00344   ierr = updateSurfaceElevationAndMask(); CHKERRQ(ierr);
00345 
00346   // this IceModel bootstrap method should do right thing because of variable
00347   //   settings above and init of coupler above
00348   ierr = putTempAtDepth(); CHKERRQ(ierr);
00349 
00350   ierr = regrid(3); CHKERRQ(ierr);
00351 
00352   return 0;
00353 }
00354 
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines