|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
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 }
1.7.3