PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/ismip/iceMISMIPModel.cc

Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines