|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
00001 // Copyright (C) 2008-2011 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 <cstring> 00020 #include <petscda.h> 00021 #include "pism_const.hh" 00022 #include "grid.hh" 00023 #include "iceModel.hh" 00024 #include "iceMISMIPModel.hh" 00025 #include "SSA.hh" 00026 #include "Mask.hh" 00027 00028 PetscErrorCode MISMIPBasalResistanceLaw::printInfo(int verbthresh, MPI_Comm com) { 00029 PetscErrorCode ierr; 00030 if (m_MISMIP == 1.0) { 00031 ierr = verbPrintf(verbthresh, com, 00032 "Using MISMIP sliding w tau_b = - C u, C=%5.4e.\n", C_MISMIP); CHKERRQ(ierr); 00033 } else { 00034 ierr = verbPrintf(verbthresh, com, 00035 "Using MISMIP sliding w tau_b = - C (|u|^2 + eps^2)^{(m-1)/2} u,\n" 00036 " m=%5.4f, C=%5.4e, and eps = %5.4f m/a.\n", 00037 m_MISMIP, C_MISMIP, regularize_MISMIP * secpera); CHKERRQ(ierr); 00038 } 00039 return 0; 00040 } 00041 00042 PetscScalar MISMIPBasalResistanceLaw::drag(PetscScalar /*tauc*/, 00043 PetscScalar vx, PetscScalar vy) { 00044 PetscScalar myC = C_MISMIP; 00045 if (m_MISMIP == 1.0) { 00046 return myC; 00047 } else { 00048 const PetscScalar magsliding = PetscSqr(vx) + PetscSqr(vy) 00049 + PetscSqr(regularize_MISMIP); 00050 return myC * pow(magsliding, (m_MISMIP - 1.0) / 2.0); 00051 } 00052 } 00053 00054 IceMISMIPModel::IceMISMIPModel(IceGrid &g, NCConfigVariable &conf, NCConfigVariable &conf_overrides) : 00055 IceModel(g, conf, conf_overrides) { 00056 00057 // following flag must be here in constructor because IceModel::createVecs() 00058 // uses it 00059 00060 // non-polythermal methods; can be overridden by the command-line option -no_cold: 00061 config.set_flag("do_cold_ice_methods", true); 00062 00063 config.set("default_till_phi", 0); 00064 00065 // some are the defaults, while some are merely in a valid range; 00066 // see IceMISMIPModel::setFromOptions() for decent values 00067 modelnum = 1; 00068 exper = 1; 00069 sliding = 'a'; 00070 gridmode = 1; 00071 stepindex = 1; 00072 initialthickness = 10.0; // m 00073 runtimeyears = 3.0e4; // a 00074 initials = "ABC"; 00075 tryCalving = false; 00076 writeExtras = false; 00077 m_MISMIP = 1.0/3.0; // power 00078 C_MISMIP = 7.624e6; // Pa m^(−1/3) s^(1/3) 00079 regularize_MISMIP = 0.01 / secpera; // 0.01 m/a 00080 dHdtnorm_atol = 1.0e-1; // m/a; FIXME: 1000 times bigger than MISMIP spec 1.0e-4 00081 dxgdt_atol = 100.0; // m/a FIXME: 1000 times bigger than MISMIP spec 0.1 00082 rstats.xg = -1.0; // deliberately invalid 00083 tviewfile = PETSC_NULL; 00084 } 00085 00086 IceMISMIPModel::~IceMISMIPModel() { 00087 // this destructor gets called even if user does *not* choose -mismip 00088 if (tviewfile != PETSC_NULL) 00089 PetscViewerDestroy(tviewfile); 00090 } 00091 00092 PetscErrorCode IceMISMIPModel::set_grid_defaults() { 00093 grid.My = 3; 00094 return 0; 00095 } 00096 00097 00098 PetscErrorCode IceMISMIPModel::set_grid_from_options() { 00099 PetscErrorCode ierr; 00100 00101 // let the base class read -Mx, -My, -Mz, -Mbz, -Lx, -Ly, -Lz, z_spacing and -zb_spacing: 00102 ierr = IceModel::set_grid_from_options(); CHKERRQ(ierr); 00103 ierr = ignore_option(grid.com, "-Lx"); CHKERRQ(ierr); 00104 ierr = ignore_option(grid.com, "-Ly"); CHKERRQ(ierr); 00105 ierr = ignore_option(grid.com, "-Lz"); CHKERRQ(ierr); 00106 00107 const PetscScalar L = 1800.0e3; // Horizontal half-width of grid 00108 00109 if ((modelnum == 2) && (sliding == 'b')) { 00110 grid.Lz = 7000.0; 00111 } else { 00112 grid.Lz = 6000.0; 00113 } 00114 00115 ierr = grid.compute_vertical_levels(); CHKERRQ(ierr); 00116 00117 // effect of double rescale here is to compute grid.dy so we can get square 00118 // cells (in horizontal). 00119 grid.Lx = L; 00120 grid.Ly = 1000.0; 00121 grid.periodicity = Y_PERIODIC; 00122 ierr = grid.compute_horizontal_spacing(); CHKERRQ(ierr); 00123 const PetscScalar Ly_desired = (grid.dx * grid.My) / 2.0; 00124 grid.Ly = Ly_desired; 00125 ierr = grid.compute_horizontal_spacing(); CHKERRQ(ierr); 00126 00127 return 0; 00128 } 00129 00130 00131 PetscErrorCode IceMISMIPModel::setFromOptions() { 00132 PetscErrorCode ierr; 00133 00134 // from Table 5 00135 const PetscScalar timeexper3a[14] = {0.0, // zero position not used 00136 3.0e4, 1.5e4, 1.5e4, 00137 1.5e4, 1.5e4, 3.0e4, 00138 3.0e4, 1.5e4, 1.5e4, 00139 3.0e4, 3.0e4, 3.0e4, 00140 1.5e4}; 00141 // from Table 6 00142 const PetscScalar timeexper3b[16] = {0.0, // zero position not used 00143 3.0e4, 1.5e4, 1.5e4, 00144 1.5e4, 1.5e4, 1.5e4, 00145 1.5e4, 3.0e4, 1.5e4, 00146 1.5e4, 1.5e4, 1.5e4, 00147 1.5e4, 3.0e4, 1.5e4}; // 15th VALUE LABELED AS 16 IN Table 6 !? 00148 00149 // read major option -mismip [1a|1b|2a|2b|3a|3b] 00150 char Ee[PETSC_MAX_PATH_LEN]; 00151 strcpy(Ee,""); 00152 ierr = PetscOptionsGetString(PETSC_NULL, "-mismip", Ee, PETSC_MAX_PATH_LEN, PETSC_NULL); 00153 CHKERRQ(ierr); 00154 if (strlen(Ee) != 2) { 00155 ierr = PetscPrintf(grid.com, 00156 "IceMISMIPModel ERROR: '-mismip' must be followed by two char argument;\n" 00157 " i.e. '-mismip Xx' where Xx=1a,1b,2a,2b,3a,3b\n"); CHKERRQ(ierr); 00158 PISMEnd(); 00159 } else { 00160 if ((Ee[0] < '1') || (Ee[0] > '3')) { 00161 ierr = PetscPrintf(grid.com, 00162 "IceMISMIPModel ERROR: first character of string 'Xx' in" 00163 " '-mismip Xx' must be 1, 2, or 3\n"); CHKERRQ(ierr); 00164 PISMEnd(); 00165 } 00166 exper = (int) Ee[0] - (int) '0'; 00167 if ((Ee[1] == 'a') || (Ee[1] == 'b')) { 00168 sliding = Ee[1]; 00169 } else { 00170 ierr = PetscPrintf(grid.com, 00171 "IceMISMIPModel ERROR: second character of string 'Xx' in" 00172 " '-mismip Xx' must be a or b\n"); CHKERRQ(ierr); 00173 PISMEnd(); 00174 } 00175 } 00176 00177 // OTHER OPTIONS: 00178 // read option -extras [OFF] 00179 ierr = PISMOptionsIsSet("-extras", writeExtras); CHKERRQ(ierr); 00180 00181 // read option -initials [ABC] 00182 bool flag; 00183 ierr = PISMOptionsString("-initials", "User's initials, for MISMIP reporting", 00184 initials, flag); CHKERRQ(ierr); 00185 if (initials.size() != 3) { 00186 ierr = verbPrintf(1,grid.com,"IceMISMIPModel WARNING: Initials string" 00187 " should usually be three chars long."); CHKERRQ(ierr); 00188 } 00189 00190 // read option -initialthk [10.0] 00191 ierr = PetscOptionsGetScalar(PETSC_NULL, "-initialthk", &initialthickness, PETSC_NULL); 00192 CHKERRQ(ierr); 00193 00194 // read option -model [1] 00195 ierr = PetscOptionsGetInt(PETSC_NULL, "-model", &modelnum, PETSC_NULL); CHKERRQ(ierr); 00196 if ((modelnum < 1) || (modelnum > 2)) { 00197 PetscPrintf(grid.com, 00198 "IceMISMIPModel ERROR: modelnum must be 1 or 2; '-model 1' or '-model 2'\n"); 00199 CHKERRQ(ierr); 00200 PISMEnd(); 00201 } 00202 00203 // read option -steady_atol [1.0e-4] 00204 ierr = PetscOptionsGetScalar(PETSC_NULL, "-steady_atol", &dHdtnorm_atol, PETSC_NULL); 00205 CHKERRQ(ierr); 00206 00207 // read option -step [1] 00208 ierr = PetscOptionsGetInt(PETSC_NULL, "-step", &stepindex, PETSC_NULL); CHKERRQ(ierr); 00209 if (stepindex < 1) { 00210 ierr = PetscPrintf(grid.com, 00211 "IceMISMIPModel ERROR: run index N in '-run N' must be at least 1\n"); 00212 CHKERRQ(ierr); 00213 PISMEnd(); 00214 } 00215 00216 if ((exper == 1) || (exper == 2)) { 00217 if (stepindex > 9) { 00218 ierr = PetscPrintf(grid.com, 00219 "IceMISMIPModel ERROR: run index N in '-run N' must be" 00220 " <= 9 in experiments 1 or 2\n"); 00221 CHKERRQ(ierr); 00222 PISMEnd(); 00223 } 00224 runtimeyears = 3.0e4; 00225 } else if (exper == 3) { 00226 if (sliding == 'a') { 00227 if (stepindex > 13) { 00228 ierr = PetscPrintf(grid.com, 00229 "IceMISMIPModel ERROR: run index N in '-run N' must be" 00230 " <= 13 in experiment 3a\n"); 00231 CHKERRQ(ierr); 00232 PISMEnd(); 00233 } 00234 runtimeyears = timeexper3a[stepindex]; 00235 } else if (sliding == 'b') { 00236 if (stepindex > 15) { 00237 ierr = PetscPrintf(grid.com, 00238 "IceMISMIPModel ERROR: run index N in '-run N' must be" 00239 " <= 15 in experiment 3b\n"); 00240 CHKERRQ(ierr); 00241 PISMEnd(); 00242 } 00243 runtimeyears = timeexper3b[stepindex]; 00244 } else { 00245 SETERRQ(99, "how did I get here?"); 00246 } 00247 } else { 00248 SETERRQ(99, "how did I get here?"); 00249 } 00250 00251 // read option -try_calving [OFF] 00252 ierr = PISMOptionsIsSet("-try_calving", tryCalving); CHKERRQ(ierr); 00253 00254 config.set_flag("do_energy", false); 00255 config.set_flag("use_ssa_when_grounded", true); 00256 config.set_flag("is_dry_simulation", false); 00257 config.set_flag("include_bmr_in_continuity", false); 00258 config.set_flag("ocean_kill", true); 00259 config.set_flag("use_ssa_velocity", true); 00260 config.set_flag("compute_surf_grad_inward_ssa", false); 00261 00262 config.set_string("surface_gradient_method", "eta"); // -gradient mahaffy or haseloff show surface 00263 // wiggles just upstream of grounding line 00264 00265 ierr = IceModel::setFromOptions(); CHKERRQ(ierr); 00266 00267 // determine gridmode from Mx 00268 if (grid.Mx == 151) 00269 gridmode = 1; 00270 else if (grid.Mx == 1501) 00271 gridmode = 2; 00272 else 00273 gridmode = 3; 00274 00275 // models 1 vs 2 00276 if (modelnum == 1) { 00277 config.set_flag("do_sia", false); 00278 } else if (modelnum == 2) { 00279 config.set_flag("do_sia", true); 00280 } else { 00281 SETERRQ(98, "how did I get here?"); 00282 } 00283 00284 // see Table 3 00285 if (sliding == 'a') { 00286 m_MISMIP = 1.0/3.0; 00287 C_MISMIP = 7.624e6; 00288 } else if (sliding == 'b') { 00289 m_MISMIP = 1.0; 00290 C_MISMIP = 7.2082e10; 00291 } else { 00292 SETERRQ(99, "how did I get here?"); 00293 } 00294 regularize_MISMIP = 0.01 / secpera; 00295 00296 return 0; 00297 } 00298 00299 PetscErrorCode IceMISMIPModel::set_time_from_options() { 00300 PetscErrorCode ierr; 00301 00302 ierr = IceModel::set_time_from_options(); CHKERRQ(ierr); 00303 00304 // use MISMIP runtimeyears UNLESS USER SPECIFIES A RUN LENGTH 00305 // use -y option, if given, to overwrite runtimeyears 00306 bool ySet, ysSet, yeSet; 00307 ierr = PISMOptionsIsSet("-y", ySet); CHKERRQ(ierr); 00308 ierr = PISMOptionsIsSet("-ys", ysSet); CHKERRQ(ierr); 00309 ierr = PISMOptionsIsSet("-ye", yeSet); CHKERRQ(ierr); 00310 if ( ySet || ( ysSet && yeSet ) ) { 00311 ierr = verbPrintf(2,grid.com, 00312 "IceMISMIPModel: ignoring MISMIP-specified run length and using value\n" 00313 " from user option -y (or -ys and -ye)\n"); CHKERRQ(ierr); 00314 } else { 00315 ierr = verbPrintf(2,grid.com, 00316 "IceMISMIPModel: setting max run length to %5.2f years (from MISMIP specs)\n", 00317 runtimeyears); CHKERRQ(ierr); 00318 if (ysSet == PETSC_FALSE) { 00319 grid.year = 0.0; 00320 grid.start_year = 0.0; 00321 } 00322 grid.end_year = grid.start_year + runtimeyears; 00323 } 00324 00325 return 0; 00326 } 00327 00328 PetscErrorCode IceMISMIPModel::allocate_flowlaw() { 00329 PetscErrorCode ierr; 00330 00331 iceFactory.setType(ICE_CUSTOM); // ICE_CUSTOM has easy setting of ice density, hardness, etc. 00332 00333 ierr = IceModel::allocate_flowlaw(); CHKERRQ(ierr); 00334 00335 // from Table 4 00336 const PetscScalar Aexper1or2[10] = {0.0, // zero position not used 00337 4.6416e-24, 2.1544e-24, 1.0e-24, 00338 4.6416e-25, 2.1544e-25, 1.0e-25, 00339 4.6416e-26, 2.1544e-26, 1.0e-26}; 00340 00341 // from Table 5 00342 const PetscScalar Aexper3a[14] = {0.0, // zero position not used 00343 3.0e-25, 2.5e-25, 2.0e-25, 00344 1.5e-25, 1.0e-25, 5.0e-26, 00345 2.5e-26, 5.0e-26, 1.0e-25, 00346 1.5e-25, 2.0e-25, 2.5e-25, 00347 3.0e-25}; 00348 00349 // from Table 6 00350 const PetscScalar Aexper3b[16] = {0.0, // zero position not used 00351 1.6e-24, 1.4e-24, 1.2e-24, 00352 1.0e-24, 8.0e-25, 6.0e-25, 00353 4.0e-25, 2.0e-25, 4.0e-25, 00354 6.0e-25, 8.0e-25, 1.0e-24, 00355 1.2e-24, 1.4e-24, 1.6e-24}; // 15th VALUE LABELED AS 16 IN Table 6 !? 00356 00357 CustomGlenIce *cgi = dynamic_cast<CustomGlenIce*>(ice); 00358 if (cgi) { 00359 // following values are from MISMIP spec: 00360 cgi->setDensity(900.0); 00361 cgi->setExponent(3); 00362 00363 // exper and stepindex range checking was done in setFromOptions 00364 if ((exper == 1) || (exper == 2)) { 00365 cgi->setSoftness(Aexper1or2[stepindex]); 00366 } else if (exper == 3) { 00367 if (sliding == 'a') { 00368 cgi->setSoftness(Aexper3a[stepindex]); 00369 } else if (sliding == 'b') { 00370 cgi->setSoftness(Aexper3b[stepindex]); 00371 } else { 00372 SETERRQ(99, "how did I get here?"); 00373 } 00374 } else { 00375 SETERRQ(99, "how did I get here?"); 00376 } 00377 00378 // if needed, get B_MISMIP by cgi->hardnessParameter(273.15) 00379 } 00380 00381 // ierr = ice->printInfo(1);CHKERRQ(ierr); // DEBUG 00382 00383 ierr = ice->setFromOptions();CHKERRQ(ierr); 00384 if (!cgi) { 00385 ierr = verbPrintf(2,grid.com, 00386 "WARNING: Not using CustomGlenIce so cannot set hardness defaults\n" 00387 " (Perhaps you chose something else with -ice_type xxx)\n" 00388 " Details on your chosen ice follow\n"); CHKERRQ(ierr); 00389 // ierr = ice->printInfo(2);CHKERRQ(ierr); 00390 } 00391 00392 return 0; 00393 } 00394 00395 00396 PetscErrorCode IceMISMIPModel::allocate_basal_resistance_law() { 00397 if (basal != NULL) return 0; 00398 basal = new MISMIPBasalResistanceLaw(m_MISMIP, C_MISMIP, regularize_MISMIP); 00399 return 0; 00400 } 00401 00402 00403 PetscErrorCode IceMISMIPModel::allocate_stressbalance() { 00404 PetscErrorCode ierr; 00405 00406 ierr = IceModel::allocate_stressbalance(); CHKERRQ(ierr); 00407 00408 SSA *ssa = dynamic_cast<SSA*>(stress_balance->get_stressbalance()); 00409 if (ssa == NULL) { SETERRQ(1, "ssa == NULL"); } 00410 00411 const PetscReal 00412 MIN_THICKNESS = 5.0, // meters 00413 DEFAULT_CONSTANT_HARDNESS_FOR_SSA = 1.9e8, // Pa s^{1/3}; see p. 49 of MacAyeal et al 1996 00414 DEFAULT_TYPICAL_STRAIN_RATE = (100.0 / secpera) / (100.0 * 1.0e3), // typical strain rate is 100 m/yr per 00415 DEFAULT_nuH = MIN_THICKNESS * DEFAULT_CONSTANT_HARDNESS_FOR_SSA 00416 / (2.0 * pow(DEFAULT_TYPICAL_STRAIN_RATE,2./3.)); // Pa s m 00417 // COMPARE: 30.0 * 1e6 * secpera = 9.45e14 is Ritz et al (2001) value of 00418 // 30 MPa yr for \bar\nu 00419 ssa->strength_extension->set_min_thickness(MIN_THICKNESS); // m 00420 ssa->strength_extension->set_notional_strength(DEFAULT_nuH); 00421 00422 return 0; 00423 } 00424 00425 00426 PetscErrorCode IceMISMIPModel::initFromFile(const char *fname) { 00427 PetscErrorCode ierr; 00428 00429 ierr = IceModel::initFromFile(fname); CHKERRQ(ierr); 00430 00431 ierr = verbPrintf(2,grid.com, 00432 "starting MISMIP experiment from file %s:\n" 00433 " model %d, experiment %d%c, grid mode %d, step %d", 00434 fname,modelnum,exper,sliding,gridmode,stepindex); CHKERRQ(ierr); 00435 CustomGlenIce *cgi = dynamic_cast<CustomGlenIce*>(ice); 00436 if (cgi) { 00437 ierr = verbPrintf(2,grid.com, " (A=%5.4e)\n",cgi->softnessParameter_from_temp(273.15)); CHKERRQ(ierr); 00438 } else { 00439 ierr = verbPrintf(2,grid.com," (WARNING: SOFTNESS A UNKNOWN!)\n"); CHKERRQ(ierr); 00440 } 00441 return 0; 00442 } 00443 00444 00445 PetscErrorCode IceMISMIPModel::createVecs() { 00446 PetscErrorCode ierr; 00447 ierr = IceModel::createVecs(); CHKERRQ(ierr); 00448 00449 ierr = artm.set_attr("pism_intent", "model_state"); CHKERRQ(ierr); 00450 ierr = acab.set_attr("pism_intent", "model_state"); CHKERRQ(ierr); 00451 return 0; 00452 } 00453 00454 PetscErrorCode IceMISMIPModel::set_vars_from_options() { 00455 PetscErrorCode ierr; 00456 00457 ierr = verbPrintf(2,grid.com, 00458 "initializing MISMIP model %d, experiment %d%c, grid mode %d, step %d", 00459 modelnum,exper,sliding,gridmode,stepindex); CHKERRQ(ierr); 00460 CustomGlenIce *cgi = dynamic_cast<CustomGlenIce*>(ice); 00461 if (cgi) { 00462 ierr = verbPrintf(2,grid.com, " (A=%5.4e)\n",cgi->softnessParameter_from_temp(273.15)); CHKERRQ(ierr); 00463 } else { 00464 ierr = verbPrintf(2,grid.com," (WARNING: SOFTNESS A UNKNOWN!)\n"); CHKERRQ(ierr); 00465 } 00466 00467 // all of these relate to models which need to be turned off ... 00468 ierr = vHmelt.set(0.0); CHKERRQ(ierr); 00469 // none use Goldsby-Kohlstedt or do age calc 00470 00471 ierr = vuplift.set(0.0); CHKERRQ(ierr); // no bed deformation 00472 ierr = T3.set(ice->melting_point_temp); CHKERRQ(ierr); 00473 00474 ierr = vH.set(initialthickness); CHKERRQ(ierr); 00475 00476 ierr = vbmr.set(0.0); CHKERRQ(ierr); 00477 ierr = vGhf.set(0.0); CHKERRQ(ierr); 00478 00479 ierr = artm.set(ice->melting_point_temp); CHKERRQ(ierr); 00480 ierr = acab.set(0.3/secpera); CHKERRQ(ierr); 00481 00482 ierr = setBed(); CHKERRQ(ierr); 00483 00484 ierr = compute_enthalpy_cold(T3, Enth3); CHKERRQ(ierr); 00485 00486 ierr = regrid(0); CHKERRQ(ierr); 00487 00488 return 0; 00489 } 00490 00491 00492 PetscErrorCode IceMISMIPModel::init_couplers() { 00493 PetscErrorCode ierr; 00494 00495 config.set("ocean_sub_shelf_heat_flux_into_ice",0.0); // NO sub ice shelf melting 00496 00497 ierr = IceModel::init_couplers(); CHKERRQ(ierr); 00498 00499 if (ocean != PETSC_NULL) { 00500 POConstant *co = dynamic_cast<POConstant*>(ocean); 00501 if (co == NULL) 00502 SETERRQ(1, "PISM ERROR: co == NULL in IceMISMIPModel ... ocean model is not a POConstant!\n"); 00503 } else { 00504 SETERRQ(2,"PISM ERROR: ocean == PETSC_NULL"); 00505 } 00506 00507 return 0; 00508 } 00509 00510 00511 PetscErrorCode IceMISMIPModel::misc_setup() { 00512 PetscErrorCode ierr; 00513 00514 ierr = IceModel::misc_setup(); CHKERRQ(ierr); 00515 00516 // create prefix (e.g.) "EBU1_2b_M1_A3" for output files with names (e.g.) 00517 // EBU1_2b_M1_A3.nc, EBU1_2b_M1_A3_t, EBU1_2b_M1_A3_ss, and EBU1_2b_M1_A3_f 00518 snprintf(mprefix, sizeof(mprefix), "%s%d_%d%c_M%d_A%d", 00519 initials.c_str(), modelnum, exper, sliding, gridmode, stepindex); 00520 00521 // if user says "-o foo.nc" 00522 PetscTruth oused; 00523 char oname[PETSC_MAX_PATH_LEN]; 00524 ierr = PetscOptionsGetString(PETSC_NULL, "-o", oname, PETSC_MAX_PATH_LEN, &oused); 00525 CHKERRQ(ierr); 00526 if (oused == PETSC_FALSE) { 00527 strcpy(oname,mprefix); 00528 strcat(oname,".nc"); 00529 // act like user set the output name 00530 ierr = PetscOptionsSetValue("-o",oname); CHKERRQ(ierr); 00531 } 00532 00533 ierr = verbPrintf(2,grid.com, 00534 "IceMISMIPModel: MISMIP options read. Will save file\n" 00535 " %s_t during run, %s.nc at end of run,\n" 00536 " and files %s_ss, %s_f at end of run if\n" 00537 " steady state achieved.\n", 00538 mprefix,oname,mprefix,mprefix); CHKERRQ(ierr); 00539 00540 // create ABC1_..._t file for every 50 year results 00541 strcpy(tfilename,mprefix); 00542 strcat(tfilename,"_t"); 00543 ierr = PetscViewerASCIIOpen(grid.com, tfilename, &tviewfile); CHKERRQ(ierr); 00544 #if PETSC_VERSION_MAJOR >= 3 00545 ierr = PetscViewerSetFormat(tviewfile, PETSC_VIEWER_DEFAULT); CHKERRQ(ierr); 00546 #else 00547 ierr = PetscViewerSetFormat(tviewfile, PETSC_VIEWER_ASCII_DEFAULT); CHKERRQ(ierr); 00548 #endif 00549 00550 return 0; 00551 } 00552 00553 00554 PetscErrorCode IceMISMIPModel::setBed() { 00555 PetscErrorCode ierr; 00556 00557 ierr = vbed.begin_access(); CHKERRQ(ierr); 00558 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00559 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00560 00561 const PetscScalar ifrom0 = 00562 static_cast<PetscScalar>(i)-static_cast<PetscScalar>(grid.Mx - 1)/2.0; 00563 const PetscScalar x = grid.dx * ifrom0; 00564 const PetscScalar xs = PetscAbs(x) / 750.0e3; // scaled and symmetrical x coord 00565 00566 if ((exper == 1) || (exper == 2)) { 00567 vbed(i,j) = 720.0 - 778.5 * xs; 00568 } else if (exper == 3) { 00569 const PetscScalar xs2 = xs * xs, 00570 xs4 = xs2 * xs2, 00571 xs6 = xs4 * xs2; 00572 vbed(i,j) = 729.0 - 2184.0 * xs2 + 1031.72 * xs4 - 151.72 * xs6; 00573 } else { 00574 SETERRQ(99,"how did I get here?"); 00575 } 00576 00577 } 00578 } 00579 ierr = vbed.end_access(); CHKERRQ(ierr); 00580 00581 // communicate b because it will be horizontally differentiated 00582 ierr = vbed.beginGhostComm(); CHKERRQ(ierr); 00583 ierr = vbed.endGhostComm(); CHKERRQ(ierr); 00584 return 0; 00585 } 00586 00587 00588 PetscErrorCode IceMISMIPModel::init_ocean_kill() { 00589 PetscErrorCode ierr; 00590 00591 const PetscScalar calving_front = 1600.0e3; 00592 00593 ierr = ocean_kill_mask.begin_access(); CHKERRQ(ierr); 00594 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00595 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00596 00597 const PetscScalar ifrom0 = 00598 static_cast<PetscScalar>(i)-static_cast<PetscScalar>(grid.Mx - 1)/2.0; 00599 const PetscScalar x = grid.dx * ifrom0; 00600 if (PetscAbs(x) >= calving_front) { 00601 ocean_kill_mask(i,j) = 1; 00602 } else { 00603 ocean_kill_mask(i,j) = 0; 00604 } 00605 00606 } 00607 } 00608 ierr = ocean_kill_mask.end_access(); CHKERRQ(ierr); 00609 00610 // communicate it 00611 ierr = ocean_kill_mask.beginGhostComm(); CHKERRQ(ierr); 00612 ierr = ocean_kill_mask.endGhostComm(); CHKERRQ(ierr); 00613 return 0; 00614 } 00615 00616 00617 PetscErrorCode IceMISMIPModel::calving() { 00618 // allows the calving front to retreat and advance, with attempt to 00619 // maintain thickness at calving front in range [100m,200m] 00620 // front will not advance beyond calving_front=1600km above 00621 PetscErrorCode ierr; 00622 00623 ierr = verbPrintf(2,grid.com,"\nIceMISMIPModel: ad hoc calving ...\n"); CHKERRQ(ierr); 00624 00625 const PetscScalar calving_thk_min = 100.0, calving_thk_max = 200.0; // meters 00626 00627 ierr = vMask.begin_access(); CHKERRQ(ierr); 00628 ierr = vH.begin_access(); CHKERRQ(ierr); 00629 00630 MaskQuery mask(vMask); 00631 00632 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00633 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00634 if (mask.ocean(i,j)) { 00635 if (vH(i,j) < calving_thk_min) { 00636 vH(i,j) = 0.0; 00637 } else if ( (vH(i,j) == 0.0) && 00638 ((vH(i-1,j) > calving_thk_max) || (vH(i+1,j) > calving_thk_max)) ) { 00639 vH(i,j) = (calving_thk_min + calving_thk_max) / 2.0; 00640 } 00641 } 00642 } 00643 } 00644 ierr = vMask.end_access(); CHKERRQ(ierr); 00645 ierr = vH.end_access(); CHKERRQ(ierr); 00646 00647 // communicate 00648 ierr = vH.beginGhostComm(); CHKERRQ(ierr); 00649 ierr = vH.endGhostComm(); CHKERRQ(ierr); 00650 00651 ierr = updateSurfaceElevationAndMask(); CHKERRQ(ierr); // update h and mask 00652 return 0; 00653 } 00654 00655 00656 PetscErrorCode IceMISMIPModel::additionalAtStartTimestep() { 00657 // this is called at start of each pass through time-stepping loop IceModel::run() 00658 const PetscScalar tonext50 = (50.0 - fmod(grid.year, 50.0)) * secpera; 00659 if (maxdt_temporary < 0.0) { // it has not been set 00660 maxdt_temporary = tonext50; 00661 } else { 00662 maxdt_temporary = PetscMin(maxdt_temporary, tonext50); 00663 } 00664 return 0; 00665 } 00666 00667 00668 PetscErrorCode IceMISMIPModel::additionalAtEndTimestep() { 00669 // this is called at the end of each pass through time-stepping loop IceModel::run() 00670 PetscErrorCode ierr; 00671 00672 // apply an ad hoc calving criterion only under user option -try_calving 00673 if (tryCalving == PETSC_TRUE) { 00674 ierr = calving(); CHKERRQ(ierr); 00675 } 00676 return 0; 00677 } 00678 00679 00680 PetscErrorCode IceMISMIPModel::writeMISMIPFinalFiles() { 00681 PetscErrorCode ierr; 00682 00683 // report on why we stopped, both stdout and stamp in output NetCDF file 00684 char str[TEMPORARY_STRING_LENGTH]; 00685 if (rstats.dHdtnorm * secpera < dHdtnorm_atol) { 00686 snprintf(str, sizeof(str), 00687 "MISMIP steady state thickness criterion (max|dHdt| < %.2e m/yr) satisfied.\n", 00688 dHdtnorm_atol); 00689 ierr = verbPrintf(2,grid.com, "\nIceMISMIPModel: %s", str); CHKERRQ(ierr); 00690 stampHistory(str); 00691 } 00692 if (PetscAbs(mstats.dxgdt) * secpera < dxgdt_atol) { 00693 snprintf(str, sizeof(str), 00694 "MISMIP steady state grounding line movement criterion (|dxgdt| < %.2e m/yr) satisfied.\n", 00695 dxgdt_atol); 00696 ierr = verbPrintf(2,grid.com, "\nIceMISMIPModel: %s", str); CHKERRQ(ierr); 00697 stampHistory(str); 00698 } 00699 if ( (rstats.dHdtnorm * secpera >= dHdtnorm_atol) 00700 || (PetscAbs(mstats.dxgdt) * secpera >= dxgdt_atol) ) { 00701 snprintf(str, sizeof(str), 00702 "WARNING: one of the MISMIP steady state criteria NOT achieved.\n"); 00703 ierr = verbPrintf(2,grid.com, "\nIceMISMIPModel: %s", str); CHKERRQ(ierr); 00704 stampHistory(str); 00705 } 00706 00707 snprintf(str, sizeof(str), 00708 "Stopping. Completed timestep year=%.3f. Writing MISMIP files.\n", 00709 grid.year); 00710 ierr = verbPrintf(2,grid.com, "\nIceMISMIPModel: %s", str); CHKERRQ(ierr); 00711 stampHistory(str); 00712 00713 // get stats in preparation for writing final files 00714 ierr = getRoutineStats(); CHKERRQ(ierr); 00715 ierr = getMISMIPStats(); CHKERRQ(ierr); 00716 // write ASCII file ABC1_1b_M1_A1_ss and ABC1_1b_M1_A1_f; 00717 char ssfilename[PETSC_MAX_PATH_LEN], ffilename[PETSC_MAX_PATH_LEN]; 00718 strcpy(ssfilename,mprefix); 00719 strcat(ssfilename,"_ss"); 00720 strcpy(ffilename,mprefix); 00721 strcat(ffilename,"_f"); 00722 ierr = verbPrintf(2, grid.com, 00723 "IceMISMIPModel: writing files %s and %s", 00724 ssfilename, ffilename); CHKERRQ(ierr); 00725 ierr = writeMISMIPasciiFile('s',ssfilename); CHKERRQ(ierr); 00726 ierr = writeMISMIPasciiFile('f',ffilename); CHKERRQ(ierr); 00727 // optionally write ABC1_1b_M1_A1_ss 00728 if (writeExtras == PETSC_TRUE) { 00729 char efilename[PETSC_MAX_PATH_LEN]; 00730 strcpy(efilename,mprefix); 00731 strcat(efilename,"_extras"); 00732 ierr = verbPrintf(2, grid.com, " and %s", efilename); CHKERRQ(ierr); 00733 ierr = writeMISMIPasciiFile('e',efilename); CHKERRQ(ierr); 00734 } 00735 ierr = verbPrintf(2, grid.com, "\n"); CHKERRQ(ierr); 00736 return 0; 00737 } 00738 00739 00740 PetscErrorCode IceMISMIPModel::writeMISMIPasciiFile(const char mismiptype, char* filename) { 00741 PetscErrorCode ierr; 00742 PetscViewer view; 00743 ierr = PetscViewerASCIIOpen(grid.com, filename, &view); CHKERRQ(ierr); 00744 #if PETSC_VERSION_MAJOR >= 3 00745 ierr = PetscViewerSetFormat(view, PETSC_VIEWER_DEFAULT); CHKERRQ(ierr); 00746 #else 00747 ierr = PetscViewerSetFormat(view, PETSC_VIEWER_ASCII_DEFAULT); CHKERRQ(ierr); 00748 #endif 00749 // just get all Vecs which might be needed 00750 ierr = vH.begin_access(); CHKERRQ(ierr); 00751 ierr = vh.begin_access(); CHKERRQ(ierr); 00752 ierr = vbed.begin_access(); CHKERRQ(ierr); 00753 if (mismiptype == 'f') { 00754 ierr = PetscViewerASCIIPrintf(view,"%10.4f %10.2f\n", rstats.xg / 1000.0, grid.year); 00755 CHKERRQ(ierr); 00756 } else { 00757 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00758 const PetscScalar 00759 ifrom0 = static_cast<PetscScalar>(i) 00760 - static_cast<PetscScalar>(grid.Mx - 1)/2.0, 00761 x = grid.dx * ifrom0; 00762 if (x >= 0) { 00763 if (mismiptype == 's') { 00764 ierr = PetscViewerASCIISynchronizedPrintf(view, 00765 "%10.2f %10.4f\n", 00766 x / 1000.0, vH(i,grid.ys)); CHKERRQ(ierr); 00767 } else { // mismiptype == 'e' 00768 ierr = PetscViewerASCIISynchronizedPrintf(view, 00769 "%10.4f %10.4f\n", 00770 vh(i,grid.ys), vbed(i,grid.ys)); CHKERRQ(ierr); 00771 } 00772 } else { // write empty string to make sure all processors write; 00773 // perhaps it is a bug in PETSc that this seems to be necessary? 00774 ierr = PetscViewerASCIISynchronizedPrintf(view,""); CHKERRQ(ierr); 00775 } 00776 } 00777 } 00778 ierr = vH.end_access(); CHKERRQ(ierr); 00779 ierr = vbed.end_access(); CHKERRQ(ierr); 00780 ierr = vh.end_access(); CHKERRQ(ierr); 00781 ierr = PetscViewerFlush(view); CHKERRQ(ierr); 00782 ierr = PetscViewerDestroy(view); CHKERRQ(ierr); 00783 return 0; 00784 } 00785 00786 00787 PetscErrorCode IceMISMIPModel::getMISMIPStats() { 00788 // run this only after getRoutineStats() is called 00789 PetscErrorCode ierr; 00790 IceModelVec2S q = vWork2d[0]; // give it a shorter name 00791 00792 IceModelVec *tmp; 00793 { 00794 ierr = diagnostics["velbar"]->compute(tmp); CHKERRQ(ierr); 00795 IceModelVec2V *vel_bar = dynamic_cast<IceModelVec2V*>(tmp); 00796 ierr = vel_bar->get_component(0, q); CHKERRQ(ierr); 00797 } 00798 delete tmp; 00799 00800 ierr = q.multiply_by(vH); CHKERRQ(ierr); 00801 // q is signed flux in x direction, in units of m^2/s 00802 00803 ierr = vH.begin_access(); CHKERRQ(ierr); 00804 ierr = vbed.begin_access(); CHKERRQ(ierr); 00805 ierr = q.begin_access(); CHKERRQ(ierr); 00806 00807 mstats.x1 = rstats.xg; 00808 mstats.x2 = rstats.xg - grid.dx; 00809 mstats.x3 = rstats.xg + grid.dx; 00810 00811 PetscScalar myh2 = 0.0, myh3 = 0.0, myb1 = -1e6, myb2 = -1e6, myb3 = -1e6, 00812 myq1 = -1e20, myq2 = -1e20, myq3 = -1e20; 00813 const int ig = (int)floor(rstats.ig + 0.1); 00814 00815 mstats.h1 = rstats.hxg; // already computed 00816 if ( (ig >= grid.xs) && (ig < grid.xs + grid.xm) && 00817 (0 >= grid.ys) && (0 < grid.ys + grid.ym) ) { // if (ig,0) is in ownership 00818 myb1 = vbed(ig,0); 00819 myq1 = q(ig,0); 00820 } 00821 ierr = PetscGlobalMax(&myb1, &mstats.b1, grid.com); CHKERRQ(ierr); 00822 ierr = PetscGlobalMax(&myq1, &mstats.q1, grid.com); CHKERRQ(ierr); 00823 00824 if ( (ig-1 >= grid.xs) && (ig-1 < grid.xs + grid.xm) && 00825 (0 >= grid.ys) && (0 < grid.ys + grid.ym) ) { // if (ig-1,0) is in ownership 00826 myh2 = vH(ig-1,0); 00827 myb2 = vbed(ig-1,0); 00828 myq2 = q(ig-1,0); 00829 } 00830 ierr = PetscGlobalMax(&myh2, &mstats.h2, grid.com); CHKERRQ(ierr); 00831 ierr = PetscGlobalMax(&myb2, &mstats.b2, grid.com); CHKERRQ(ierr); 00832 ierr = PetscGlobalMax(&myq2, &mstats.q2, grid.com); CHKERRQ(ierr); 00833 00834 if ( (ig+1 >= grid.xs) && (ig+1 < grid.xs + grid.xm) && 00835 (0 >= grid.ys) && (0 < grid.ys + grid.ym) ) { // if (ig+1,0) is in ownership 00836 myh3 = vH(ig+1,0); 00837 myb3 = vbed(ig+1,0); 00838 myq3 = q(ig+1,0); 00839 } 00840 ierr = PetscGlobalMax(&myh3, &mstats.h3, grid.com); CHKERRQ(ierr); 00841 ierr = PetscGlobalMax(&myb3, &mstats.b3, grid.com); CHKERRQ(ierr); 00842 ierr = PetscGlobalMax(&myq3, &mstats.q3, grid.com); CHKERRQ(ierr); 00843 00844 ierr = vH.end_access(); CHKERRQ(ierr); 00845 ierr = vbed.end_access(); CHKERRQ(ierr); 00846 ierr = q.end_access(); CHKERRQ(ierr); 00847 00848 // perform MISMIP diagnostic computation here, to estimate dxg/dt: 00849 // d xg a - dq/dx 00850 // ---- = ----------------------------- 00851 // dt dh/dx - (rhow/rhoi) (db/dx) 00852 double ocean_rho = config.get("sea_water_density"); 00853 const PetscScalar dqdx = (mstats.q1 - mstats.q2) / (mstats.x1 - mstats.x2), 00854 dhdx = (mstats.h1 - mstats.h2) / (mstats.x1 - mstats.x2), 00855 dbdx = (mstats.b1 - mstats.b2) / (mstats.x1 - mstats.x2); 00856 mstats.dxgdt = ((0.3/secpera) - dqdx) / (dhdx - (ocean_rho/ice->rho) * dbdx); 00857 return 0; 00858 } 00859 00860 00861 PetscErrorCode IceMISMIPModel::getRoutineStats() { 00862 PetscErrorCode ierr; 00863 00864 // these are in MKS; sans "g" are local to the processor; with "g" are global 00865 // across all processors; we only evaluate for x > 0 00866 PetscScalar maxubar = 0.0, avubargrounded = 0.0, avubarfloating = 0.0, ig = 0.0, 00867 Ngrounded = 0.0, Nfloating = 0.0; 00868 PetscScalar gavubargrounded, gavubarfloating, gig; 00869 00870 IceModelVec *tmp; 00871 ierr = diagnostics["velbar"]->compute(tmp); CHKERRQ(ierr); 00872 00873 IceModelVec2V *vel_bar = dynamic_cast<IceModelVec2V*>(tmp); 00874 00875 MaskQuery mask(vMask); 00876 00877 ierr = vMask.begin_access(); CHKERRQ(ierr); 00878 ierr = vH.begin_access(); CHKERRQ(ierr); 00879 ierr = vel_bar->begin_access(); CHKERRQ(ierr); 00880 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00881 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00882 00883 const PetscScalar ifrom0 = 00884 static_cast<PetscScalar>(i)-static_cast<PetscScalar>(grid.Mx - 1)/2.0; 00885 00886 // grounding line xg is largest x so that mask(i,j) != FLOATING 00887 // and mask(i+1,j) == FLOATING 00888 if ( (ifrom0 > 0.0) && (vH(i,j) > 0.0) 00889 && mask.grounded(i,j) 00890 && mask.ocean(i+1,j) ) { 00891 ig = PetscMax(ig,static_cast<PetscScalar>(i)); 00892 } 00893 00894 if ((ifrom0 > 0) && (vH(i,j) > 0.0)) { 00895 if ((*vel_bar)(i,j).u > maxubar) maxubar = (*vel_bar)(i,j).u; 00896 if (mask.grounded(i,j)) { 00897 Ngrounded += 1.0; 00898 avubargrounded += (*vel_bar)(i,j).u; 00899 } else { 00900 Nfloating += 1.0; 00901 avubarfloating += (*vel_bar)(i,j).u; 00902 } 00903 } 00904 00905 } 00906 } 00907 ierr = vMask.end_access(); CHKERRQ(ierr); 00908 ierr = vel_bar->end_access(); CHKERRQ(ierr); 00909 00910 delete vel_bar; 00911 00912 ierr = PetscGlobalMax(&ig, &gig, grid.com); CHKERRQ(ierr); 00913 rstats.ig = gig; 00914 00915 const PetscScalar gigfrom0 = 00916 gig - static_cast<PetscScalar>(grid.Mx - 1)/2.0; 00917 rstats.xg = gigfrom0 * grid.dx; 00918 00919 PetscScalar myhxg = 0.0; 00920 if ( (gig >= grid.xs) && (gig < grid.xs + grid.xm) && 00921 (0 >= grid.ys) && (0 < grid.ys + grid.ym) ) { // if (gig,0) is in ownership 00922 myhxg = vH(static_cast<int>(gig),0); // i.e. hxg = vH(gig,0) 00923 } else { 00924 myhxg = 0.0; 00925 } 00926 ierr = PetscGlobalMax(&myhxg, &rstats.hxg, grid.com); CHKERRQ(ierr); 00927 00928 ierr = vH.end_access(); CHKERRQ(ierr); 00929 00930 ierr = PetscGlobalMax(&maxubar, &rstats.maxubar, grid.com); CHKERRQ(ierr); 00931 00932 ierr = PetscGlobalSum(&Ngrounded, &rstats.Ngrounded, grid.com); CHKERRQ(ierr); 00933 ierr = PetscGlobalSum(&avubargrounded, &gavubargrounded, grid.com); CHKERRQ(ierr); 00934 if (rstats.Ngrounded > 0) gavubargrounded = gavubargrounded / rstats.Ngrounded; 00935 else gavubargrounded = 0.0; // degenerate case 00936 rstats.avubarG = gavubargrounded; 00937 00938 ierr = PetscGlobalSum(&Nfloating, &rstats.Nfloating, grid.com); CHKERRQ(ierr); 00939 ierr = PetscGlobalSum(&avubarfloating, &gavubarfloating, grid.com); CHKERRQ(ierr); 00940 if (rstats.Nfloating > 0) gavubarfloating = gavubarfloating / rstats.Nfloating; 00941 else gavubarfloating = 0.0; // degenerate case 00942 rstats.avubarF = gavubarfloating; 00943 00944 PetscScalar infnormdHdt = 0.0; 00945 ierr = vH.begin_access(); CHKERRQ(ierr); 00946 ierr = vdHdt.begin_access(); CHKERRQ(ierr); 00947 for (PetscInt i=grid.xs; i<grid.xs+grid.xm; ++i) { 00948 for (PetscInt j=grid.ys; j<grid.ys+grid.ym; ++j) { 00949 if (vH(i,j) > 0.0) { 00950 infnormdHdt = PetscMax(infnormdHdt, vdHdt(i,j)); 00951 } 00952 } 00953 } 00954 ierr = vH.end_access(); CHKERRQ(ierr); 00955 ierr = vdHdt.end_access(); CHKERRQ(ierr); 00956 ierr = PetscGlobalMax(&infnormdHdt, &rstats.dHdtnorm, grid.com); CHKERRQ(ierr); 00957 return 0; 00958 } 00959 00960 00961 PetscErrorCode IceMISMIPModel::summaryPrintLine( 00962 PetscTruth printPrototype, bool /*tempAndAge*/, 00963 PetscScalar year, PetscScalar /*dt*/, 00964 PetscScalar volume, PetscScalar /*area_kmsquare*/, 00965 PetscScalar /*meltfrac*/, PetscScalar H0, PetscScalar /*T0*/) { 00966 00967 /* 00968 Because this model resolves the shelf and only uses the floatation criterion 00969 to move the grounding line, we must give 17 numbers. These numbers will go into 00970 a reportable ascii file ABC1_1a_M1_A1_t. 00971 00972 The reported numbers are 00973 00974 t x_g Volume h(0,t) h(x_g,t) 00975 x_1 h(x_1,t) b(x_1) q(x_1,t) // last grounded point (i.e. x_1 = x_g) 00976 x_2 h(x_2,t) b(x_2) q(x_2,t) // x_2 = x_1 - dx 00977 x_3 h(x_3,t) b(x_3) q(x_3,t) // x_3 = x_1 + dx 00978 00979 The number of reported digits is 00980 00981 8 chars (includes ".") for t [years] 00982 7 chars for x_* [km] 00983 8 chars for Volume [10^6 km^3] 00984 7 chars for h(*,t) [m] 00985 7 chars for b(*,t) [m] 00986 7 chars for q(*,t) [m^2/year] 00987 00988 The format written to ABC1_1a_M1_A1_t has 137 columns, like this: 00989 00990 ######## ####### ######## ####### ####### ####### ####### ####### ####### ####### ####### ####### ####### ####### ####### ####### ####### 00991 00992 At verbosity 3 or higher, an additional stdout format fits in an 80 column line: 00993 00994 M ######## ####### ######## ####### ####### 00995 ####### ####### ####### ####### ####### ####### ####### ####### 00996 ####### ####### ####### ####### 00997 00998 A line 00999 [ d(xg)/dt = ####### m/yr by MISMIP computation ] 01000 is written to stdout. This grounding line motion rate 01001 is computed as in MISMIP description, and finite differences. 01002 */ 01003 01004 PetscErrorCode ierr; 01005 if (printPrototype == PETSC_TRUE) { 01006 ierr = verbPrintf(2,grid.com, 01007 "P YEAR: ivol h0 xg hxg maxubar avubarG avubarF dHdtnorm Ngnd Nflt\n"); 01008 ierr = verbPrintf(2,grid.com, 01009 "U years 10^6_km^3 m km m m/a m/a m/a m/a 1 1\n"); 01010 } else { 01011 ierr = getRoutineStats(); CHKERRQ(ierr); 01012 ierr = verbPrintf(2,grid.com, 01013 "S %12.5f: %8.5f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %8.2e %5d %5d\n", 01014 year, volume/(1.0e6*1.0e9), 01015 H0, rstats.xg / 1000.0, rstats.hxg, rstats.maxubar * secpera, 01016 rstats.avubarG * secpera, rstats.avubarF * secpera, 01017 rstats.dHdtnorm * secpera, int(rstats.Ngrounded), int(rstats.Nfloating)); CHKERRQ(ierr); 01018 if (fabs(fmod(year, 50.0)) < 1.0e-6) { 01019 // write another line to ASCII file ABC1_1b_M1_A1_t; also write to stdout 01020 // (given some verbosity level); note modest code redundancy 01021 ierr = verbPrintf(2, grid.com, 01022 "[IceMISMIPModel: adding t=%10.3f line to file %s;\n", 01023 year,tfilename); CHKERRQ(ierr); 01024 ierr = getMISMIPStats(); CHKERRQ(ierr); 01025 ierr = verbPrintf(3,grid.com,"M "); 01026 ierr = verbPrintf(3,grid.com, 01027 "%8.2f %7.2f %8.5f %7.2f %7.2f ", 01028 year, rstats.xg / 1000.0, volume/(1.0e6*1.0e9), H0, rstats.hxg); CHKERRQ(ierr); 01029 ierr = PetscViewerASCIIPrintf(tviewfile, 01030 "%8.2f %7.2f %8.5f %7.2f %7.2f ", 01031 year, rstats.xg / 1000.0, volume/(1.0e6*1.0e9), H0, rstats.hxg); CHKERRQ(ierr); 01032 ierr = verbPrintf(3,grid.com,"\n "); 01033 ierr = verbPrintf(3,grid.com, 01034 "%7.2f %7.2f %7.2f %7.0f %7.2f %7.2f %7.2f %7.0f ", 01035 mstats.x1 / 1000.0, mstats.h1, mstats.b1, mstats.q1 * secpera, 01036 mstats.x2 / 1000.0, mstats.h2, mstats.b2, mstats.q2 * secpera); CHKERRQ(ierr); 01037 ierr = PetscViewerASCIIPrintf(tviewfile, 01038 "%7.2f %7.2f %7.2f %7.0f %7.2f %7.2f %7.2f %7.0f ", 01039 mstats.x1 / 1000.0, mstats.h1, mstats.b1, mstats.q1 * secpera, 01040 mstats.x2 / 1000.0, mstats.h2, mstats.b2, mstats.q2 * secpera); CHKERRQ(ierr); 01041 ierr = verbPrintf(3,grid.com,"\n "); 01042 ierr = verbPrintf(3,grid.com, 01043 "%7.2f %7.2f %7.2f %7.0f\n", 01044 mstats.x3 / 1000.0, mstats.h3, mstats.b3, mstats.q3 * secpera); CHKERRQ(ierr); 01045 ierr = PetscViewerASCIIPrintf(tviewfile, 01046 "%7.2f %7.2f %7.2f %7.0f\n", 01047 mstats.x3 / 1000.0, mstats.h3, mstats.b3, mstats.q3 * secpera); CHKERRQ(ierr); 01048 ierr = verbPrintf(2,grid.com, 01049 " d(xg)/dt = %10.2f m/yr by MISMIP computation ]\n", 01050 mstats.dxgdt * secpera); CHKERRQ(ierr); 01051 01052 // now check if MISMIP steady state criteria are achieved: 01053 if ((rstats.dHdtnorm * secpera < dHdtnorm_atol) && (PetscAbs(mstats.dxgdt) * secpera < dxgdt_atol)) { 01054 // set the IceModel goal of end_year to the current year; 01055 // causes immediate stop 01056 grid.end_year = grid.year; 01057 } 01058 } 01059 } 01060 return 0; 01061 } 01062
1.7.3