|
PISM, A Parallel Ice Sheet Model
stable v0.5
|
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
1.7.5.1