PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/iceModel.cc

Go to the documentation of this file.
00001 // Copyright (C) 2004-2011 Jed Brown, Ed Bueler and Constantine Khroulev
00002 //
00003 // This file is part of PISM.
00004 //
00005 // PISM is free software; you can redistribute it and/or modify it under the
00006 // terms of the GNU General Public License as published by the Free Software
00007 // Foundation; either version 2 of the License, or (at your option) any later
00008 // version.
00009 //
00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013 // details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with PISM; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #include <cmath>
00020 #include <cstring>
00021 #include <petscda.h>
00022 
00023 #include "iceModel.hh"
00024 #include "pism_signal.h"
00025 
00026 IceModel::IceModel(IceGrid &g, NCConfigVariable &conf, NCConfigVariable &conf_overrides)
00027   : grid(g), config(conf), overrides(conf_overrides), iceFactory(grid.com,NULL, conf), ice(NULL) {
00028   PetscErrorCode ierr;
00029 
00030   if (utIsInit() == 0) {
00031     if (utInit(NULL) != 0) {
00032       PetscPrintf(grid.com, "PISM ERROR: UDUNITS initialization failed.\n");
00033       PISMEnd();
00034     }
00035   }
00036 
00037   mapping.init("mapping", grid.com, grid.rank);
00038   global_attributes.init("global_attributes", grid.com, grid.rank);
00039 
00040   pism_signal = 0;
00041   signal(SIGTERM, pism_signal_handler);
00042   signal(SIGUSR1, pism_signal_handler);
00043   signal(SIGUSR2, pism_signal_handler);
00044 
00045   basal_yield_stress = NULL;
00046   basal = NULL;
00047 
00048   stress_balance = NULL;
00049 
00050   surface = NULL;
00051   ocean   = NULL;
00052   beddef  = NULL;
00053 
00054   EC = NULL;
00055   btu = NULL;
00056 
00057   ierr = setDefaults();  // lots of parameters and flags set here, including by reading from a config file
00058   if (ierr != 0) {
00059     verbPrintf(1,grid.com, "Error setting defaults.\n");
00060     PISMEnd();
00061   }
00062 
00063   // Do not save snapshots by default:
00064   save_snapshots = false;
00065   // Do not save time-series by default:
00066   save_ts = false;
00067   save_extra = false;
00068 
00069   reset_counters();
00070 
00071   allowAboveMelting = PETSC_FALSE;  // only IceCompModel ever sets it to true
00072 
00073   // Default ice type:
00074   iceFactory.setType(ICE_PB);
00075 }
00076 
00077 void IceModel::reset_counters() {
00078   CFLmaxdt = CFLmaxdt2D = 0.0;
00079   CFLviolcount = 0;
00080   dt_years_TempAge = 0.0;
00081   dt_from_diffus = dt_from_cfl = 0.0;
00082   dvoldt = gdHdtav = 0;
00083   gDmax = dvoldt = gdHdtav = 0;
00084   gmaxu = gmaxv = gmaxw = -1;
00085   maxdt_temporary = dt = dt_force = 0.0;
00086   skipCountDown = 0;
00087   total_basal_ice_flux = 0;
00088   total_sub_shelf_ice_flux = 0;
00089   total_surface_ice_flux = 0;
00090 }
00091 
00092 
00093 IceModel::~IceModel() {
00094 
00095   deallocate_internal_objects();
00096 
00097   // write (and deallocate) time-series
00098   vector<DiagnosticTimeseries*>::iterator i = timeseries.begin();
00099   while(i != timeseries.end()) delete (*i++);
00100 
00101   // de-allocate diagnostics
00102   map<string,PISMDiagnostic*>::iterator j = diagnostics.begin();
00103   while (j != diagnostics.end()) delete (j++)->second;
00104 
00105   // de-allocate viewers
00106   map<string,PetscViewer>::iterator k = viewers.begin();
00107   while (k != viewers.end()) {
00108     if ((*k).second != PETSC_NULL) {
00109       PetscViewerDestroy((*k).second);
00110       ++k;
00111     }
00112   }
00113 
00114   delete stress_balance;
00115 
00116   delete ocean;
00117   delete surface;
00118   delete beddef;
00119 
00120   delete basal;
00121   delete EC;
00122   delete btu;
00123   delete ice;
00124 
00125   utTerm(); // Clean up after UDUNITS
00126 }
00127 
00128 
00130 
00138 PetscErrorCode IceModel::createVecs() {
00139   PetscErrorCode ierr;
00140   PetscInt WIDE_STENCIL = grid.max_stencil_width;
00141 
00142   ierr = verbPrintf(3, grid.com,
00143                     "Allocating memory...\n"); CHKERRQ(ierr);
00144 
00145   // The following code creates (and documents -- to some extent) the
00146   // variables. The main (and only) principle here is using standard names from
00147   // the CF conventions; see
00148   // http://cf-pcmdi.llnl.gov/documents/cf-standard-names
00149 
00150   ierr = Enth3.create(grid, "enthalpy", true, WIDE_STENCIL); CHKERRQ(ierr);
00151   // POSSIBLE standard name = land_ice_enthalpy
00152   ierr = Enth3.set_attrs(
00153      "model_state",
00154      "ice enthalpy (includes sensible heat, latent heat, pressure)",
00155      "J kg-1", ""); CHKERRQ(ierr);
00156   ierr = variables.add(Enth3); CHKERRQ(ierr);
00157 
00158   if (config.get_flag("do_cold_ice_methods")) {
00159     // ice temperature
00160     ierr = T3.create(grid, "temp", true); CHKERRQ(ierr);
00161     ierr = T3.set_attrs("model_state", "ice temperature", "K", "land_ice_temperature"); CHKERRQ(ierr);
00162     ierr = T3.set_attr("valid_min", 0.0); CHKERRQ(ierr);
00163     ierr = variables.add(T3); CHKERRQ(ierr);
00164 
00165     ierr = Enth3.set_attr("pism_intent", "diagnostic"); CHKERRQ(ierr); 
00166   }
00167 
00168   // age of ice but only if age will be computed
00169   if (config.get_flag("do_age")) {
00170     ierr = tau3.create(grid, "age", true, WIDE_STENCIL); CHKERRQ(ierr);
00171     // PROPOSED standard_name = land_ice_age
00172     ierr = tau3.set_attrs("model_state", "age of ice",
00173                           "s", ""); CHKERRQ(ierr);
00174     ierr = tau3.set_glaciological_units("years");
00175     tau3.write_in_glaciological_units = true;
00176     ierr = tau3.set_attr("valid_min", 0.0); CHKERRQ(ierr);
00177     ierr = variables.add(tau3); CHKERRQ(ierr);
00178   }
00179 
00180   // ice upper surface elevation
00181   ierr = vh.create(grid, "usurf", true, WIDE_STENCIL); CHKERRQ(ierr);
00182   ierr = vh.set_attrs("diagnostic", "ice upper surface elevation",
00183                       "m", "surface_altitude"); CHKERRQ(ierr);
00184   ierr = variables.add(vh); CHKERRQ(ierr);
00185 
00186   // land ice thickness
00187   ierr = vH.create(grid, "thk", true, WIDE_STENCIL); CHKERRQ(ierr);
00188   ierr = vH.set_attrs("model_state", "land ice thickness",
00189                       "m", "land_ice_thickness"); CHKERRQ(ierr);
00190   ierr = vH.set_attr("valid_min", 0.0); CHKERRQ(ierr);
00191   ierr = variables.add(vH); CHKERRQ(ierr);
00192 
00193   // bedrock surface elevation
00194   ierr = vbed.create(grid, "topg", true, WIDE_STENCIL); CHKERRQ(ierr);
00195   ierr = vbed.set_attrs("model_state", "bedrock surface elevation",
00196                         "m", "bedrock_altitude"); CHKERRQ(ierr);
00197   ierr = variables.add(vbed); CHKERRQ(ierr);
00198 
00199   if (config.get_flag("ocean_kill")) {
00200     ierr = ocean_kill_mask.create(grid, "ocean_kill_mask", false); CHKERRQ(ierr);
00201     ierr = ocean_kill_mask.set_attrs("internal",
00202                                      "mask specifying fixed calving front locations",
00203                                      "", ""); CHKERRQ(ierr);
00204     ocean_kill_mask.time_independent = true;
00205     ierr = variables.add(ocean_kill_mask); CHKERRQ(ierr);
00206 
00207   }
00208 
00209   // grounded_dragging_floating integer mask
00210   ierr = vMask.create(grid, "mask", true, WIDE_STENCIL); CHKERRQ(ierr);
00211   ierr = vMask.set_attrs("diagnostic", "grounded_dragging_floating integer mask",
00212                          "", ""); CHKERRQ(ierr);
00213   vector<double> mask_values(4);
00214   mask_values[0] = MASK_ICE_FREE_BEDROCK;
00215   mask_values[1] = MASK_GROUNDED;
00216   mask_values[2] = MASK_FLOATING;
00217   mask_values[3] = MASK_ICE_FREE_OCEAN;
00218   ierr = vMask.set_attr("flag_values", mask_values); CHKERRQ(ierr);
00219   ierr = vMask.set_attr("flag_meanings",
00220                         "ice_free_bedrock grounded_ice floating_ice ice_free_ocean"); CHKERRQ(ierr);
00221   vMask.output_data_type = NC_BYTE;
00222   ierr = variables.add(vMask); CHKERRQ(ierr);
00223 
00224   // iceberg identifying integer mask
00225   if (config.get_flag("kill_icebergs")) {
00226     ierr = vIcebergMask.create(grid, "IcebergMask", true, WIDE_STENCIL); CHKERRQ(ierr);
00227     ierr = vIcebergMask.set_attrs("internal", 
00228                                   "iceberg-identifying integer mask",
00229                                   "", ""); CHKERRQ(ierr);
00230     vector<double> icebergmask_values(5);
00231     icebergmask_values[0] = ICEBERGMASK_NO_ICEBERG;
00232     icebergmask_values[1] = ICEBERGMASK_NOT_SET;
00233     icebergmask_values[2] = ICEBERGMASK_ICEBERG_CAND;
00234     icebergmask_values[3] = ICEBERGMASK_STOP_OCEAN;
00235     icebergmask_values[4] = ICEBERGMASK_STOP_ATTACHED;
00236     //more values to identify lakes?
00237 
00238     ierr = vIcebergMask.set_attr("flag_values", icebergmask_values); CHKERRQ(ierr);
00239     ierr = vIcebergMask.set_attr("flag_meanings",
00240       "no_iceberg not_set iceberg_candidate ocean_boundary grounded_boudary"); CHKERRQ(ierr);
00241     vIcebergMask.output_data_type = NC_BYTE;
00242     ierr = variables.add(vIcebergMask); CHKERRQ(ierr);
00243   }
00244 
00245   // upward geothermal flux at bedrock surface
00246   ierr = vGhf.create(grid, "bheatflx", true, WIDE_STENCIL); CHKERRQ(ierr); // never differentiated
00247   // PROPOSED standard_name = lithosphere_upward_heat_flux
00248   ierr = vGhf.set_attrs("climate_steady", "upward geothermal flux at bedrock surface",
00249                         "W m-2", ""); CHKERRQ(ierr);
00250   ierr = vGhf.set_glaciological_units("mW m-2");
00251   vGhf.write_in_glaciological_units = true;
00252   vGhf.time_independent = true;
00253   ierr = variables.add(vGhf); CHKERRQ(ierr);
00254 
00255   // temperature seen by top of bedrock thermal layer
00256   ierr = bedtoptemp.create(grid, "bedtoptemp", false); CHKERRQ(ierr); // never differentiated
00257   ierr = bedtoptemp.set_attrs("internal",
00258                         "temperature of top of bedrock thermal layer",
00259                         "K", ""); CHKERRQ(ierr);
00260   ierr = bedtoptemp.set_glaciological_units("K");
00261   ierr = variables.add(bedtoptemp); CHKERRQ(ierr);
00262 
00263   // effective thickness of subglacial melt water
00264   ierr = vHmelt.create(grid, "bwat", true, WIDE_STENCIL); CHKERRQ(ierr);
00265   ierr = vHmelt.set_attrs("model_state", "effective thickness of subglacial melt water",
00266                           "m", ""); CHKERRQ(ierr);
00267   // NB! Effective thickness of subglacial melt water *does* vary from 0 to hmelt_max meters only.
00268   ierr = vHmelt.set_attr("valid_min", 0.0); CHKERRQ(ierr);
00269   ierr = vHmelt.set_attr("valid_max", config.get("hmelt_max")); CHKERRQ(ierr);
00270   ierr = variables.add(vHmelt); CHKERRQ(ierr);
00271 
00272   // rate of change of ice thickness
00273   ierr = vdHdt.create(grid, "dHdt", true, WIDE_STENCIL); CHKERRQ(ierr);
00274   ierr = vdHdt.set_attrs("diagnostic", "rate of change of ice thickness",
00275                          "m s-1", "tendency_of_land_ice_thickness"); CHKERRQ(ierr);
00276   ierr = vdHdt.set_glaciological_units("m year-1");
00277   vdHdt.write_in_glaciological_units = true;
00278   const PetscScalar  huge_dHdt = 1.0e6;      // million m a-1 is out-of-range
00279   ierr = vdHdt.set_attr("valid_min", convert(-huge_dHdt, "m/year", "m/s")); CHKERRQ(ierr);
00280   ierr = vdHdt.set_attr("valid_max", convert( huge_dHdt, "m/year", "m/s")); CHKERRQ(ierr);
00281   ierr = variables.add(vdHdt); CHKERRQ(ierr);
00282 
00283   if (config.get_flag("use_ssa_velocity")) {
00284     // yield stress for basal till (plastic or pseudo-plastic model)
00285     ierr = vtauc.create(grid, "tauc", true, WIDE_STENCIL); CHKERRQ(ierr);
00286     // PROPOSED standard_name = land_ice_basal_material_yield_stress
00287     ierr = vtauc.set_attrs("diagnostic", 
00288                            "yield stress for basal till (plastic or pseudo-plastic model)",
00289                            "Pa", ""); CHKERRQ(ierr);
00290     ierr = variables.add(vtauc); CHKERRQ(ierr);
00291   }
00292 
00293   // bedrock uplift rate
00294   ierr = vuplift.create(grid, "dbdt", true, WIDE_STENCIL); CHKERRQ(ierr);
00295   ierr = vuplift.set_attrs("model_state", "bedrock uplift rate",
00296                            "m s-1", "tendency_of_bedrock_altitude"); CHKERRQ(ierr);
00297   ierr = vuplift.set_glaciological_units("m year-1");
00298   vuplift.write_in_glaciological_units = true;
00299   ierr = variables.add(vuplift); CHKERRQ(ierr);
00300 
00301   // basal melt rate
00302   ierr = vbmr.create(grid, "bmelt", true, WIDE_STENCIL); CHKERRQ(ierr);
00303   // ghosted to allow the "redundant" computation of tauc
00304   ierr = vbmr.set_attrs("model_state",
00305                         "ice basal melt rate in ice thickness per time",
00306                         "m s-1", "land_ice_basal_melt_rate"); CHKERRQ(ierr);
00307   ierr = vbmr.set_glaciological_units("m year-1"); CHKERRQ(ierr);
00308   vbmr.write_in_glaciological_units = true;
00309   vbmr.set_attr("comment", "positive basal melt rate corresponds to ice loss");
00310   ierr = variables.add(vbmr); CHKERRQ(ierr);
00311 
00312   // longitude
00313   ierr = vLongitude.create(grid, "lon", true); CHKERRQ(ierr);
00314   ierr = vLongitude.set_attrs("mapping", "longitude", "degree_east", "longitude"); CHKERRQ(ierr);
00315   vLongitude.time_independent = true;
00316   ierr = vLongitude.set_attr("coordinates", ""); CHKERRQ(ierr);
00317   ierr = vLongitude.set_attr("grid_mapping", ""); CHKERRQ(ierr);
00318   ierr = vLongitude.set_attr("valid_min", -180.0); CHKERRQ(ierr);
00319   ierr = vLongitude.set_attr("valid_max",  180.0); CHKERRQ(ierr);
00320   ierr = variables.add(vLongitude); CHKERRQ(ierr);
00321 
00322   // latitude
00323   ierr = vLatitude.create(grid, "lat", true); CHKERRQ(ierr); // has ghosts so that we can compute cell areas
00324   ierr = vLatitude.set_attrs("mapping", "latitude", "degree_north", "latitude"); CHKERRQ(ierr);
00325   vLatitude.time_independent = true;
00326   ierr = vLatitude.set_attr("coordinates", ""); CHKERRQ(ierr);
00327   ierr = vLatitude.set_attr("grid_mapping", ""); CHKERRQ(ierr);
00328   ierr = vLatitude.set_attr("valid_min", -90.0); CHKERRQ(ierr);
00329   ierr = vLatitude.set_attr("valid_max",  90.0); CHKERRQ(ierr);
00330   ierr = variables.add(vLatitude); CHKERRQ(ierr);
00331 
00332   if (config.get_flag("part_grid") == true) {
00333     // Href
00334     ierr = vHref.create(grid, "Href", true); CHKERRQ(ierr);
00335     ierr = vHref.set_attrs("model_state", "temporary ice thickness at calving front boundary",
00336                            "m", ""); CHKERRQ(ierr);
00337     ierr = variables.add(vHref); CHKERRQ(ierr);
00338 
00339         if (config.get_flag("part_redist") == true){
00340       // Hav
00341       ierr = vHresidual.create(grid, "Hresidual", true); CHKERRQ(ierr);
00342       ierr = vHresidual.set_attrs("diagnostic", "residual ice thickness in recently filled boundary grid cell",
00343                           "m", ""); CHKERRQ(ierr);
00344       ierr = variables.add(vHresidual); CHKERRQ(ierr);
00345         }
00346   }
00347 
00348   if (config.get_flag("do_eigen_calving") == true) {
00349     ierr = vPrinStrain1.create(grid, "edot_1", true); CHKERRQ(ierr);
00350     ierr = vPrinStrain1.set_attrs("internal", 
00351                                   "major principal component of horizontal strain-rate",
00352                                   "1/s", ""); CHKERRQ(ierr);
00353     ierr = variables.add(vPrinStrain1); CHKERRQ(ierr);
00354     ierr = vPrinStrain2.create(grid, "edot_2", true); CHKERRQ(ierr);
00355     ierr = vPrinStrain2.set_attrs("internal",
00356                                   "minor principal component of horizontal strain-rate",
00357                                   "1/s", ""); CHKERRQ(ierr);
00358     ierr = variables.add(vPrinStrain2); CHKERRQ(ierr);
00359   }
00360 
00361   if (config.get_flag("dirichlet_bc") == true) {
00362     // bc_locations
00363           ierr = vBCMask.create(grid, "bcflag", true, WIDE_STENCIL); CHKERRQ(ierr);
00364       ierr = vBCMask.set_attrs("model_state", "Dirichlet boundary mask",
00365                          "", ""); CHKERRQ(ierr);
00366       vector<double> bc_mask_values(2);
00367       bc_mask_values[0] = 0;
00368       bc_mask_values[1] = 1;
00369       ierr = vBCMask.set_attr("flag_values", bc_mask_values); CHKERRQ(ierr);
00370       ierr = vBCMask.set_attr("flag_meanings", "no_data bc_condition"); CHKERRQ(ierr);
00371       vBCMask.output_data_type = NC_BYTE;
00372       ierr = variables.add(vBCMask); CHKERRQ(ierr);
00373 
00374 
00375      // vel_bc
00376      ierr = vBCvel.create(grid, "bar", true, WIDE_STENCIL); CHKERRQ(ierr); // ubar and vbar
00377      ierr = vBCvel.set_attrs("model_state",
00378                               "X-component of the SSA velocity boundary conditions",
00379                               "m s-1", "", 0); CHKERRQ(ierr);
00380      ierr = vBCvel.set_attrs("model_state",
00381                               "Y-component of the SSA velocity boundary conditions",
00382                               "m s-1", "", 1); CHKERRQ(ierr);
00383      ierr = vBCvel.set_glaciological_units("m year-1"); CHKERRQ(ierr);
00384      ierr = vBCvel.set_attr("valid_min", convert(-1e6, "m/year", "m/second"), 0); CHKERRQ(ierr);
00385      ierr = vBCvel.set_attr("valid_max",  convert(1e6, "m/year", "m/second"), 0); CHKERRQ(ierr);
00386      ierr = vBCvel.set_attr("valid_min", convert(-1e6, "m/year", "m/second"), 1); CHKERRQ(ierr);
00387      ierr = vBCvel.set_attr("valid_max",  convert(1e6, "m/year", "m/second"), 1); CHKERRQ(ierr);
00388      ierr = vBCvel.set_attr("_FillValue", convert(2e6, "m/year", "m/second"), 0); CHKERRQ(ierr);
00389      ierr = vBCvel.set_attr("_FillValue", convert(2e6, "m/year", "m/second"), 1); CHKERRQ(ierr);
00390      //just for diagnostics...
00391      ierr = variables.add(vBCvel); CHKERRQ(ierr);
00392 
00393   }
00394 
00395 
00396   // cell areas
00397   ierr = cell_area.create(grid, "cell_area", false); CHKERRQ(ierr);
00398   ierr = cell_area.set_attrs("diagnostic", "cell areas", "m2", ""); CHKERRQ(ierr);
00399   ierr = cell_area.set_attr("comment",
00400                             "values are equal to dx*dy "
00401                             "if latitude and longitude fields are not available; "
00402                             "otherwise WGS84 ellipsoid is used"); CHKERRQ(ierr); 
00403   cell_area.time_independent = true;
00404   ierr = cell_area.set_glaciological_units("km2"); CHKERRQ(ierr);
00405   cell_area.write_in_glaciological_units = true;
00406   ierr = variables.add(cell_area); CHKERRQ(ierr);
00407 
00408   // fields owned by IceModel but filled by PISMSurfaceModel *surface:
00409   // mean annual net ice equivalent surface mass balance rate
00410   ierr = acab.create(grid, "acab", false); CHKERRQ(ierr);
00411   ierr = acab.set_attrs(
00412             "climate_from_PISMSurfaceModel",  // FIXME: can we do better?
00413             "ice-equivalent surface mass balance (accumulation/ablation) rate",
00414             "m s-1",  // m *ice-equivalent* per second
00415             "land_ice_surface_specific_mass_balance");  // CF standard_name
00416             CHKERRQ(ierr);
00417   ierr = acab.set_glaciological_units("m year-1"); CHKERRQ(ierr);
00418   acab.write_in_glaciological_units = true;
00419   acab.set_attr("comment", "positive values correspond to ice gain");
00420   ierr = variables.add(acab); CHKERRQ(ierr);
00421 
00422   // annual mean air temperature at "ice surface", at level below all firn
00423   //   processes (e.g. "10 m" or ice temperatures)
00424   ierr = artm.create(grid, "artm", false); CHKERRQ(ierr);
00425   ierr = artm.set_attrs(
00426             "climate_from_PISMSurfaceModel",  // FIXME: can we do better?
00427             "annual average ice surface temperature, below firn processes",
00428             "K", 
00429             "");  // PROPOSED CF standard_name = land_ice_surface_temperature_below_firn
00430   CHKERRQ(ierr);
00431   ierr = variables.add(artm); CHKERRQ(ierr);
00432 
00433   ierr = liqfrac_surface.create(grid, "liqfrac_surface", false); CHKERRQ(ierr);
00434   ierr = liqfrac_surface.set_attrs("climate_from_PISMSurfaceModel",
00435                                    "liquid water fraction at the top surface of the ice",
00436                                    "1", ""); CHKERRQ(ierr);
00437   // ierr = variables.add(liqfrac_surface); CHKERRQ(ierr);
00438 
00439   // ice mass balance rate at the base of the ice shelf; sign convention for
00440   //   vshelfbasemass matches standard sign convention for basal melt rate of
00441   //   grounded ice
00442   ierr = shelfbmassflux.create(grid, "shelfbmassflux", false); CHKERRQ(ierr); // no ghosts; NO HOR. DIFF.!
00443   ierr = shelfbmassflux.set_attrs(
00444            "climate_state", "ice mass flux from ice shelf base (positive flux is loss from ice shelf)",
00445            "m s-1", ""); CHKERRQ(ierr); 
00446   // PROPOSED standard name = ice_shelf_basal_specific_mass_balance
00447   // rescales from m/s to m/a when writing to NetCDF and std out:
00448   shelfbmassflux.write_in_glaciological_units = true;
00449   ierr = shelfbmassflux.set_glaciological_units("m year-1"); CHKERRQ(ierr);
00450   // do not add; boundary models are in charge here
00451   //ierr = variables.add(shelfbmassflux); CHKERRQ(ierr);
00452 
00453   // ice boundary tempature at the base of the ice shelf
00454   ierr = shelfbtemp.create(grid, "shelfbtemp", false); CHKERRQ(ierr); // no ghosts; NO HOR. DIFF.!
00455   ierr = shelfbtemp.set_attrs(
00456            "climate_state", "absolute temperature at ice shelf base",
00457            "K", ""); CHKERRQ(ierr);
00458   // PROPOSED standard name = ice_shelf_basal_temperature
00459   // do not add; boundary models are in charge here
00460   // ierr = variables.add(shelfbtemp); CHKERRQ(ierr);
00461 
00462   return 0;
00463 }
00464 
00465 
00467 
00470 PetscErrorCode IceModel::deallocate_internal_objects() {
00471   return 0;
00472 }
00473 
00474 PetscErrorCode IceModel::setExecName(const char *my_executable_short_name) {
00475   executable_short_name = my_executable_short_name;
00476   return 0;
00477 }
00478 
00480 
00483 PetscErrorCode IceModel::step(bool do_mass_continuity,
00484                               bool do_energy,
00485                               bool do_age,
00486                               bool do_skip,
00487                               bool use_ssa_when_grounded) {
00488   PetscErrorCode ierr;
00489 
00490   grid.profiler->begin(event_step);
00491 
00493   ierr = additionalAtStartTimestep(); CHKERRQ(ierr);  // might set dt_force,maxdt_temporary
00494 
00496   double apcc_dt;
00497   ierr = surface->max_timestep(grid.year, apcc_dt); CHKERRQ(ierr);
00498   apcc_dt *= secpera;
00499   if (apcc_dt > 0.0) {
00500     if (maxdt_temporary > 0)
00501       maxdt_temporary = PetscMin(apcc_dt, maxdt_temporary);
00502     else
00503       maxdt_temporary = apcc_dt;
00504   }
00505 
00506   double opcc_dt;
00507   ierr = ocean->max_timestep(grid.year, opcc_dt); CHKERRQ(ierr);
00508   opcc_dt *= secpera;
00509   if (opcc_dt > 0.0) {
00510     if (maxdt_temporary > 0)
00511       maxdt_temporary = PetscMin(opcc_dt, maxdt_temporary);
00512     else
00513       maxdt_temporary = opcc_dt;
00514   }
00515 
00518   double extras_dt;
00519   ierr = extras_max_timestep(grid.year, extras_dt); CHKERRQ(ierr);
00520   extras_dt *= secpera;
00521   if (extras_dt > 0.0) {
00522     if (maxdt_temporary > 0)
00523       maxdt_temporary = PetscMin(extras_dt, maxdt_temporary);
00524     else
00525       maxdt_temporary = extras_dt;
00526   }
00527 
00528   grid.profiler->begin(event_beddef);
00529 
00532   if (beddef) {
00533     bool bed_changed;
00534     ierr = bed_def_step(bed_changed); CHKERRQ(ierr);
00535     if (bed_changed) {
00536       stdout_flags += "b";
00537     } else stdout_flags += "$";
00538   } else stdout_flags += " ";
00539   
00540   grid.profiler->end(event_beddef);
00541 
00543   if (use_ssa_when_grounded) {
00544     if (basal_yield_stress) {
00545       ierr = basal_yield_stress->update(grid.year, dt / secpera); CHKERRQ(ierr);
00546       ierr = basal_yield_stress->basal_material_yield_stress(vtauc); CHKERRQ(ierr);
00547     }
00548     stdout_flags += "y";
00549   } else stdout_flags += "$";
00550 
00554 
00555   // always do SIA velocity calculation (unless -no_sia is given); only update
00556   // SSA and only update velocities at depth if suggested by temp and age
00557   // stability criterion; note *lots* of communication is avoided by skipping
00558   // SSA (and temp/age)
00559 
00560   bool updateAtDepth = (skipCountDown == 0);
00561   
00562   grid.profiler->begin(event_velocity);
00563 
00564   ierr = stress_balance->update(updateAtDepth == false); CHKERRQ(ierr); 
00565 
00566   grid.profiler->end(event_velocity);
00567 
00568   string sb_stdout;
00569   ierr = stress_balance->stdout_report(sb_stdout); CHKERRQ(ierr);
00570 
00571   stdout_flags += sb_stdout;
00572 
00573   stdout_flags += (updateAtDepth ? "v" : "V");
00574    
00575   // communication here for global max; sets CFLmaxdt2D
00576   ierr = computeMax2DSlidingSpeed(); CHKERRQ(ierr);   
00577 
00578   if (updateAtDepth) {
00579     // communication here for global max; sets CFLmaxdt
00580     ierr = computeMax3DVelocities(); CHKERRQ(ierr); 
00581   }
00582 
00585   ierr = determineTimeStep(do_energy); CHKERRQ(ierr);
00586 
00588   ierr = surface->update(grid.year, dt / secpera); CHKERRQ(ierr);
00589   ierr = ocean->update(grid.year,   dt / secpera); CHKERRQ(ierr);
00590 
00591 
00592   dt_years_TempAge += dt / secpera;
00593   // IceModel::dt,dtTempAge,grid.year are now set correctly according to
00594   //    mass-continuity-eqn-diffusivity criteria, horizontal CFL criteria, and
00595   //    other criteria from derived class additionalAtStartTimestep(), and from
00596   //    "-skip" mechanism
00597 
00598   grid.profiler->begin(event_age);
00599   
00601   if (do_age) {
00602     ierr = ageStep(); CHKERRQ(ierr);
00603     stdout_flags += "a";
00604   } else {
00605     stdout_flags += "$";
00606   }
00607 
00608   grid.profiler->end(event_age);
00609   
00610   
00611   grid.profiler->begin(event_energy);
00612 
00616   if (updateAtDepth && do_energy) { // do the temperature step
00617     ierr = energyStep(); CHKERRQ(ierr);
00618     stdout_flags += "E";
00619   } else {
00620     stdout_flags += "$";
00621   }
00622   
00623   grid.profiler->end(event_energy);
00624 
00628   ierr = ice_mass_bookkeeping(); CHKERRQ(ierr);
00629 
00630   grid.profiler->begin(event_mass);
00631 
00634   if (do_mass_continuity) {
00635     ierr = massContExplicitStep(); CHKERRQ(ierr); // update H
00636     ierr = updateSurfaceElevationAndMask(); CHKERRQ(ierr); // update h and mask
00637 
00638     // Note that there are three adaptive time-stepping criteria. Two of them
00639     // (using max. diffusion and 2D CFL) are limiting the mass-continuity
00640     // time-step and the third (3D CFL) limits the energy and age time-steps.
00641 
00642     // The mass-continuity time-step is usually smaller, and the skipping
00643     // mechanism lets us do several mass-continuity steps for each energy step.
00644 
00645     // When -no_mass is set, mass-continuity-related time-step restrictions are
00646     // disabled, making "skipping" unnecessary.
00647 
00648     // This is why the following two lines appear here and are executed only
00649     // if do_mass_continuity == true.
00650     if (do_skip == PETSC_TRUE && skipCountDown > 0)
00651       skipCountDown--;
00652     stdout_flags += "h";
00653   } else {
00654     stdout_flags += "$";
00655     // if do_mass_continuity is false, then ice thickness does not change and
00656     // dH/dt = 0:
00657     ierr = vdHdt.set(0.0); CHKERRQ(ierr);
00658   }
00659   
00660   grid.profiler->end(event_mass);
00661 
00663   ierr = additionalAtEndTimestep(); CHKERRQ(ierr);
00664 
00665   grid.year += dt / secpera;  // adopt the new time
00666   if (updateAtDepth && do_energy) { // FIXME: must be same condition as "do the temperature step"
00667     t_years_TempAge = grid.year;
00668     dt_years_TempAge = 0.0;
00669   }
00670 
00671   // end the flag line
00672   char tempstr[5];  snprintf(tempstr,5," %c", adaptReasonFlag);
00673   stdout_flags += tempstr;
00674 
00675 #ifdef PISM_DEBUG
00676   ierr = variables.check_for_nan(); CHKERRQ(ierr);
00677 #endif
00678 
00679   grid.profiler->end(event_step);
00680 
00681   return 0;
00682 }
00683 
00684 
00686 
00689 PetscErrorCode IceModel::run() {
00690   PetscErrorCode  ierr;
00691 
00692   bool do_mass_conserve = config.get_flag("do_mass_conserve"),
00693     do_energy = config.get_flag("do_energy"),
00694     do_age = config.get_flag("do_age"),
00695     do_skip = config.get_flag("do_skip"),
00696     use_ssa_when_grounded = config.get_flag("use_ssa_when_grounded");
00697   int stepcount = (config.get_flag("count_time_steps")) ? 0 : -1;
00698 
00699   // do a one-step diagnostic run:
00700   ierr = verbPrintf(2,grid.com,
00701       "doing preliminary step to fill diagnostic quantities ...\n"); CHKERRQ(ierr);
00702 
00703   // set verbosity to 1 to suppress reporting
00704   PetscInt tmp_verbosity = getVerbosityLevel(); 
00705   ierr = setVerbosityLevel(1); CHKERRQ(ierr);
00706 
00707   dt_force = -1.0;
00708   maxdt_temporary = -1.0;
00709   skipCountDown = 0;
00710   dt_years_TempAge = 0.0;
00711   dt = 0.0;
00712   PetscReal end_year = grid.end_year;
00713   
00714   // FIXME:  In the case of derived class diagnostic time series this fixed
00715   //         step-length can be problematic.  The fix may have to be in the derived class.
00716   //         The problem is that unless the derived class fully reinitializes its
00717   //         time series then there can be a request for an interpolation on [A,B]
00718   //         where A>B.  See IcePSTexModel.
00719   //grid.end_year = grid.start_year + 1; // all what matters is that it is
00720   //                                   // greater than start_year
00721   grid.end_year = grid.start_year + 0.01; // all what matters is that it is
00722                                        // greater than start_year
00723 
00724   
00725   ierr = step(do_mass_conserve, do_energy, do_age,
00726               do_skip, use_ssa_when_grounded); CHKERRQ(ierr);
00727 
00728   // print verbose messages according to user-set verbosity
00729   if (tmp_verbosity > 2) {
00730     ierr = PetscPrintf(grid.com,
00731       " done; reached time %.4f a\n", grid.year); CHKERRQ(ierr);
00732     ierr = PetscPrintf(grid.com,
00733       "  re-setting model state as initialized ...\n"); CHKERRQ(ierr);
00734   }
00735 
00736   // re-initialize the model:
00737   global_attributes.set_string("history", "");
00738   grid.year = grid.start_year;
00739   t_years_TempAge = grid.year;
00740   grid.end_year = end_year;
00741   ierr = model_state_setup(); CHKERRQ(ierr);
00742 
00743   // restore verbosity:
00744   ierr = setVerbosityLevel(tmp_verbosity); CHKERRQ(ierr);
00745 
00746   // Write snapshots and time-series at the beginning of the run.
00747   ierr = write_snapshot(); CHKERRQ(ierr);
00748   ierr = write_timeseries(); CHKERRQ(ierr);
00749   ierr = write_extras(); CHKERRQ(ierr);
00750 
00751   ierr = verbPrintf(2,grid.com, "running forward ...\n"); CHKERRQ(ierr);
00752 
00753   stdout_flags.erase(); // clear it out
00754   ierr = summaryPrintLine(PETSC_TRUE,do_energy, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); CHKERRQ(ierr);
00755   adaptReasonFlag = '$'; // no reason for no timestep
00756   reset_counters();
00757   ierr = summary(do_energy); CHKERRQ(ierr);  // report starting state
00758 
00759   // main loop for time evolution
00760   for (PetscScalar year = grid.start_year; year < grid.end_year; year += dt/secpera) {
00761     
00762     stdout_flags.erase();  // clear it out
00763     dt_force = -1.0;
00764     maxdt_temporary = -1.0;
00765 
00766     ierr = step(do_mass_conserve, do_energy, do_age,
00767                 do_skip, use_ssa_when_grounded); CHKERRQ(ierr);
00768     
00769     // report a summary for major steps or the last one
00770     bool updateAtDepth = (skipCountDown == 0);
00771     bool tempAgeStep = ( updateAtDepth && ((do_energy) || (do_age)) );
00772 
00773     const bool show_step = tempAgeStep || (adaptReasonFlag == 'e');
00774     ierr = summary(show_step); CHKERRQ(ierr);
00775 
00776     // writing these fields here ensures that we do it after the last time-step
00777     ierr = write_snapshot(); CHKERRQ(ierr);
00778     ierr = write_timeseries(); CHKERRQ(ierr);
00779     ierr = write_extras(); CHKERRQ(ierr);
00780     ierr = write_backup(); CHKERRQ(ierr);
00781 
00782     ierr = update_viewers(); CHKERRQ(ierr);
00783 
00784     if (stepcount >= 0) stepcount++;
00785     if (endOfTimeStepHook() != 0) break;
00786   } // end of the time-stepping loop
00787 
00788   bool flag;
00789   PetscInt pause_time = 0;
00790   ierr = PISMOptionsInt("-pause", "Pause after the run, seconds",
00791                         pause_time, flag); CHKERRQ(ierr);
00792   if (pause_time > 0) {
00793     ierr = verbPrintf(2,grid.com,"pausing for %d secs ...\n",pause_time); CHKERRQ(ierr);
00794     ierr = PetscSleep(pause_time); CHKERRQ(ierr);
00795   }
00796 
00797   if (stepcount >= 0) {
00798     ierr = verbPrintf(1,grid.com,
00799               "count_time_steps:  run() took %d steps\naverage dt = %.6f years\n",
00800               stepcount,(grid.end_year-grid.start_year)/(double)stepcount); CHKERRQ(ierr);
00801   }
00802 
00803   return 0;
00804 }
00805 
00807 
00811 PetscErrorCode IceModel::init() {
00812   PetscErrorCode ierr;
00813 
00814   ierr = PetscOptionsBegin(grid.com, "", "PISM options", ""); CHKERRQ(ierr);
00815 
00816   // Build PISM with -DPISM_WAIT_FOR_GDB=1 and run with -wait_for_gdb to
00817   // make it wait for a connection.
00818 #ifdef PISM_WAIT_FOR_GDB
00819   bool wait_for_gdb = false;
00820   ierr = PISMOptionsIsSet("-wait_for_gdb", wait_for_gdb); CHKERRQ(ierr);
00821   if (wait_for_gdb) {
00822     ierr = pism_wait_for_gdb(grid.com, 0); CHKERRQ(ierr);
00823   }
00824 #endif
00825 
00826 
00828   ierr = grid_setup(); CHKERRQ(ierr);
00829 
00831   ierr = setFromOptions(); CHKERRQ(ierr);
00832 
00834   ierr = createVecs(); CHKERRQ(ierr);
00835 
00837   ierr = allocate_submodels(); CHKERRQ(ierr);
00838 
00840   ierr = init_couplers(); CHKERRQ(ierr);
00841 
00843   ierr = allocate_internal_objects(); CHKERRQ(ierr);
00844 
00848   ierr = model_state_setup(); CHKERRQ(ierr);
00849 
00851   ierr = grid.report_parameters(); CHKERRQ(ierr);
00852 
00856   ierr = misc_setup();
00857 
00858   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00859 
00863 
00864   ierr = MPI_Barrier(grid.com); CHKERRQ(ierr);
00865   ierr = PetscGetTime(&start_time); CHKERRQ(ierr);
00866 
00867   return 0; 
00868 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines