PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/iMIO.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 <cstring>
00020 #include <cstdio>
00021 #include <petscda.h>
00022 #include "iceModel.hh"
00023 #include <algorithm>
00024 #include <sstream>
00025 #include <set>
00026 #include "PISMIO.hh"
00027 
00029 
00034 PetscErrorCode  IceModel::writeFiles(const char* default_filename) {
00035   PetscErrorCode ierr;
00036   string filename = default_filename,
00037     config_out;
00038   bool o_set, dump_config;
00039 
00040   grid.profiler->begin(event_output);
00041 
00042   ierr = stampHistoryEnd(); CHKERRQ(ierr);
00043 
00044   ierr = PetscOptionsBegin(grid.com, "", "PISM output options", ""); CHKERRQ(ierr);
00045   {
00046     ierr = PISMOptionsString("-o", "Output file name", filename, o_set); CHKERRQ(ierr);
00047     ierr = PISMOptionsString("-dump_config", "File to write the config to",
00048                              config_out, dump_config); CHKERRQ(ierr);
00049   }
00050   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00051 
00052   if (!ends_with(filename, ".nc")) {
00053     ierr = verbPrintf(2, grid.com,
00054                       "PISM WARNING: output file name does not have the '.nc' suffix!\n");
00055     CHKERRQ(ierr);
00056   }
00057 
00058   ierr = verbPrintf(2, grid.com, "Writing model state to file `%s'\n", filename.c_str()); CHKERRQ(ierr);
00059 
00060 
00061   ierr = dumpToFile(filename.c_str()); CHKERRQ(ierr);
00062 
00063 
00064   // save the config file
00065   if (dump_config) {
00066     ierr = config.write(config_out.c_str()); CHKERRQ(ierr);
00067   }
00068 
00069   grid.profiler->end(event_output);
00070 
00071 #ifdef PISM_PROFILE
00072   bool flag;
00073   ierr = PISMOptionsIsSet("-prof", flag); CHKERRQ(ierr);
00074   string prof_output_name;
00075   if (flag) {
00076     prof_output_name = pism_filename_add_suffix(filename, "-prof", "");
00077 
00078     ierr = verbPrintf(2, grid.com, "Saving profiling data to '%s'...\n",
00079                       prof_output_name.c_str());
00080     CHKERRQ(ierr);
00081 
00082     ierr = grid.profiler->save_report(prof_output_name); CHKERRQ(ierr);
00083   }
00084 #endif
00085 
00086   return 0;
00087 }
00088 
00090 PetscErrorCode IceModel::write_metadata(const char *filename) {
00091   PetscErrorCode ierr;
00092 
00093   ierr = mapping.write(filename); CHKERRQ(ierr);
00094   ierr = global_attributes.write(filename); CHKERRQ(ierr);
00095 
00096   bool override_used;
00097   ierr = PISMOptionsIsSet("-config_override", override_used); CHKERRQ(ierr);
00098   if (override_used) {
00099     overrides.update_from(config);
00100     ierr = overrides.write(filename); CHKERRQ(ierr);
00101   }
00102   
00103   return 0;
00104 }
00105 
00106 
00107 PetscErrorCode IceModel::dumpToFile(const char *filename) {
00108   PetscErrorCode ierr;
00109   PISMIO nc(&grid);
00110 
00111   // Prepare the file
00112   ierr = nc.open_for_writing(filename, false, true); CHKERRQ(ierr);
00113   // append == false, check_dims == true
00114   ierr = nc.append_time(grid.year); CHKERRQ(ierr);
00115   ierr = nc.close(); CHKERRQ(ierr);
00116 
00117   // Write metadata *before* variables:
00118 
00119   ierr = write_metadata(filename); CHKERRQ(ierr);
00120 
00121   ierr = write_model_state(filename);  CHKERRQ(ierr);
00122 
00123   return 0;
00124 }
00125 
00128 PetscErrorCode IceModel::write_variables(const char *filename, set<string> vars,
00129                                          nc_type nctype) {
00130   PetscErrorCode ierr;
00131   IceModelVec *v;
00132 
00133   // Define all the variables:
00134   {
00135     PISMIO nc(&grid);
00136     ierr = nc.open_for_writing(filename, true, false); CHKERRQ(ierr);
00137     // append == true, check_dims == false
00138 
00139     set<string>::iterator i = vars.begin();
00140     while (i != vars.end()) {
00141       v = variables.get(*i);
00142 
00143       if (v != NULL) {
00144         // It has dedicated storage.
00145         if (*i == "mask") {
00146           ierr = v->define(nc, NC_BYTE); CHKERRQ(ierr); // use the default data type
00147         } else {
00148           ierr = v->define(nc, nctype); CHKERRQ(ierr);
00149         }
00150       } else {
00151         // It might be a diagnostic quantity
00152         PISMDiagnostic *diag = diagnostics[*i];
00153 
00154         if (diag != NULL) {
00155           ierr = diag->define(nc); CHKERRQ(ierr);
00156         }
00157       }
00158 
00159       ++i;
00160     }
00161 
00162     if (beddef != NULL) {
00163       ierr = beddef->define_variables(vars, nc, nctype); CHKERRQ(ierr);
00164     }
00165 
00166     if (btu != NULL) {
00167       ierr = btu->define_variables(vars, nc, nctype); CHKERRQ(ierr);
00168     }
00169 
00170     if (basal_yield_stress != NULL) {
00171       ierr = basal_yield_stress->define_variables(vars, nc, nctype); CHKERRQ(ierr);
00172     }
00173 
00174     if (stress_balance != NULL) {
00175       ierr = stress_balance->define_variables(vars, nc, nctype); CHKERRQ(ierr);
00176     } else {
00177       SETERRQ(1,"PISM ERROR: stress_balance == NULL");
00178     }
00179 
00180     if (surface != NULL) {
00181       ierr = surface->define_variables(vars, nc, nctype); CHKERRQ(ierr);
00182     } else {
00183       SETERRQ(1,"PISM ERROR: surface == NULL");
00184     }
00185     if (ocean != NULL) {
00186       ierr = ocean->define_variables(vars, nc, nctype); CHKERRQ(ierr);
00187     } else {
00188       SETERRQ(1,"PISM ERROR: ocean == NULL");
00189     }
00190 
00191     ierr = nc.close(); CHKERRQ(ierr);
00192   }
00193 
00194   // Write all the IceModel variables:
00195   set<string>::iterator i = vars.begin();
00196   while (i != vars.end()) {
00197     v = variables.get(*i);
00198 
00199     if (v == NULL) {
00200       ++i;
00201     } else {
00202       ierr = v->write(filename); CHKERRQ(ierr); // use the default data type
00203 
00204       vars.erase(i++);          // note that it only erases variables that were
00205                                 // found (and saved)
00206     }
00207   }
00208 
00209   // Write bed-deformation-related variables:
00210   if (beddef != NULL) {
00211     ierr = beddef->write_variables(vars, filename); CHKERRQ(ierr);
00212   }
00213 
00214   // Write PISMBedThermalUnit variables:
00215   if (btu != NULL) {
00216     ierr = btu->write_variables(vars, filename); CHKERRQ(ierr);
00217   }
00218 
00219   if (basal_yield_stress != NULL) {
00220     ierr = basal_yield_stress->write_variables(vars, filename); CHKERRQ(ierr);
00221   }
00222 
00223   // Write stress balance-related variables:
00224   if (stress_balance != NULL) {
00225     ierr = stress_balance->write_variables(vars, filename); CHKERRQ(ierr);
00226   } else {
00227     SETERRQ(1,"PISM ERROR: stress_balance == NULL");
00228   }
00229 
00230   // Ask boundary models to write their variables:
00231   if (surface != NULL) {
00232     ierr = surface->write_variables(vars, filename); CHKERRQ(ierr);
00233   } else {
00234     SETERRQ(1,"PISM ERROR: surface == NULL");
00235   }
00236   if (ocean != NULL) {
00237     ierr = ocean->write_variables(vars, filename); CHKERRQ(ierr);
00238   } else {
00239     SETERRQ(1,"PISM ERROR: ocean == NULL");
00240   }
00241 
00242   // All the remaining names in vars must be of diagnostic quantities.
00243   i = vars.begin();
00244   while (i != vars.end()) {
00245     PISMDiagnostic *diag = diagnostics[*i];
00246 
00247     if (diag == NULL)
00248       ++i;
00249     else {
00250       v = NULL;
00251 
00252       ierr = diag->compute(v); CHKERRQ(ierr);
00253 
00254       v->write_in_glaciological_units = true;
00255       ierr = v->write(filename, NC_FLOAT); CHKERRQ(ierr); // diagnostic quantities are always written in float
00256 
00257       delete v;
00258 
00259       vars.erase(i++);
00260     }
00261   }
00262 
00263   // FIXME: we need a way of figuring out if a sub-model did or did not write
00264   // something.
00265 
00266   if (!vars.empty()) {
00267     int threshold = 3;
00268     ierr = verbPrintf(threshold, grid.com,
00269                       "PISM WARNING: the following variables were *not* written by PISM core (IceModel): "); CHKERRQ(ierr);
00270     for (i = vars.begin(); i != vars.end(); ++i) {
00271       ierr = verbPrintf(threshold, grid.com, "%s ", (*i).c_str()); CHKERRQ(ierr);
00272     }
00273     ierr = verbPrintf(threshold, grid.com, "\n"); CHKERRQ(ierr);
00274   }
00275 
00276   return 0;
00277 }
00278 
00279 
00280 PetscErrorCode IceModel::write_model_state(const char* filename) {
00281   PetscErrorCode ierr;
00282 
00283   bool write_temp_pa;
00284   ierr = PISMOptionsIsSet("-temp_pa", write_temp_pa); CHKERRQ(ierr);
00285   if (write_temp_pa || (!config.get_flag("do_cold_ice_methods"))) {
00286     // write temp_pa = pressure-adjusted temp in Celcius
00287     ierr = verbPrintf(4, grid.com,
00288                       "  writing pressure-adjusted ice temperature (deg C) 'temp_pa' ...\n"); CHKERRQ(ierr);
00289     output_vars.insert("temp_pa");
00290   }
00291 
00292   bool write_liqfrac;
00293   ierr = PISMOptionsIsSet("-liqfrac", write_liqfrac); CHKERRQ(ierr);
00294   if (write_liqfrac || (!config.get_flag("do_cold_ice_methods"))) {
00295     ierr = verbPrintf(4, grid.com,
00296                       "  writing liquid water fraction 'liqfrac' ...\n"); CHKERRQ(ierr);
00297     output_vars.insert("liqfrac");
00298   }
00299 
00300   bool userWantsCTS;
00301   ierr = PISMOptionsIsSet("-cts", userWantsCTS); CHKERRQ(ierr);
00302   if (userWantsCTS) {
00303     ierr = verbPrintf(4, grid.com,
00304                       "  writing CTS (= E/Es) scalar field 'cts' ...\n"); CHKERRQ(ierr);
00305     output_vars.insert("cts");
00306   }
00307 
00308   ierr = write_variables(filename, output_vars, NC_DOUBLE);
00309 
00310   return 0;
00311 }
00312 
00313 
00314 
00316 
00321 PetscErrorCode IceModel::initFromFile(const char *filename) {
00322   PetscErrorCode  ierr;
00323   NCTool nc(grid.com, grid.rank);
00324 
00325   ierr = verbPrintf(2, grid.com, "initializing from NetCDF file '%s'...\n",
00326                     filename); CHKERRQ(ierr);
00327 
00328   // options for initializing enthalpy
00329   bool initfromT, initfromTandOm;
00330   string enthalpy_pism_intent;
00331   ierr = PISMOptionsIsSet("-init_from_temp", initfromT); CHKERRQ(ierr);
00332   ierr = PISMOptionsIsSet("-init_from_temp_and_liqfrac", initfromTandOm); CHKERRQ(ierr);
00333   if (initfromT && initfromTandOm) {
00334     PetscPrintf(grid.com,
00335                 "PISM ERROR: both options -init_from_temp and -init_from_temp_and_liqfrac seen; must choose one or none");
00336     PISMEnd();
00337   }
00338 
00339   // if initializing enthalpy from temperature or temperature and liquid water
00340   // fraction, temporarily set pism_intent of Enth3 to "diagnostic" so that
00341   // PISM does not even try to read the "enthalpy" variable
00342   if (initfromT || initfromTandOm) {
00343     enthalpy_pism_intent = Enth3.string_attr("pism_intent");
00344     ierr = Enth3.set_attr("pism_intent", "diagnostic"); CHKERRQ(ierr);
00345   }
00346 
00347 
00348   ierr = nc.open_for_reading(filename); CHKERRQ(ierr);
00349 
00350   // check if the input file has Href; set its pism_intent to "diagnostic" and
00351   // set the field itself to 0 if it is not present
00352   if (config.get_flag("part_grid")) {
00353     bool exists;
00354     ierr = nc.find_variable("Href", NULL, exists); CHKERRQ(ierr);
00355     
00356     if (!exists) {
00357       ierr = verbPrintf(2, grid.com,
00358         "PISM WARNING: Href for PISM-PIK -part_grid not found in %s. Setting it to zero...\n",
00359         filename); CHKERRQ(ierr);
00360 
00361       ierr = vHref.set_attr("pism_intent", "diagnostic"); CHKERRQ(ierr);
00362       ierr = vHref.set(0.0); CHKERRQ(ierr);
00363     }
00364   }
00365 
00366   // Find the index of the last record in the file:
00367   int last_record;
00368   ierr = nc.get_nrecords(last_record); CHKERRQ(ierr); 
00369   last_record -= 1;
00370 
00371   // Read the model state, mapping and climate_steady variables:
00372   set<string> vars = variables.keys();
00373 
00374   set<string>::iterator i = vars.begin();
00375   while (i != vars.end()) {
00376     IceModelVec *var = variables.get(*i++);
00377 
00378     string intent = var->string_attr("pism_intent");
00379     if ((intent == "model_state") || (intent == "mapping") ||
00380         (intent == "climate_steady")) {
00381       ierr = var->read(filename, last_record); CHKERRQ(ierr);
00382     }
00383   }
00384 
00385   if (config.get_flag("do_cold_ice_methods")) {
00386     ierr = verbPrintf(3,grid.com,"  setting enthalpy from temperature...\n");
00387     CHKERRQ(ierr);
00388     ierr = compute_enthalpy_cold(T3, Enth3); CHKERRQ(ierr);
00389   }
00390 
00391   if (config.get_flag("do_age")) {
00392     bool age_exists;
00393     ierr = nc.find_variable("age", NULL, age_exists); CHKERRQ(ierr);
00394 
00395     if (age_exists) {
00396       ierr = tau3.read(filename, last_record); CHKERRQ(ierr);
00397     } else {
00398       ierr = verbPrintf(2,grid.com,
00399                         "PISM WARNING: input file '%s' does not have the 'age' variable.\n"
00400                         "  Setting it to zero...\n",
00401                         filename); CHKERRQ(ierr);
00402       ierr = tau3.set(0.0); CHKERRQ(ierr);
00403     }
00404   }
00405 
00406   if (initfromT || initfromTandOm) {
00407     IceModelVec3 temperature;
00408 
00409     ierr = temperature.create(grid, "temp", false); CHKERRQ(ierr);
00410     ierr = temperature.set_attrs("internal", "ice temperature; temporary storage during initialization",
00411                                  "K", "land_ice_temperature"); CHKERRQ(ierr);
00412     ierr = temperature.set_attr("valid_min", 0.0); CHKERRQ(ierr);
00413     
00414     ierr = temperature.read(filename, last_record); CHKERRQ(ierr);
00415 
00416     if (initfromT) {
00417       ierr = verbPrintf(2, grid.com,
00418                         "  option -init_from_temp seen; computing enthalpy from ice temperature and thickness ...\n");
00419       CHKERRQ(ierr);
00420 
00421       ierr = compute_enthalpy_cold(temperature, Enth3); CHKERRQ(ierr);
00422 
00423     } else {
00424       ierr = verbPrintf(2, grid.com,
00425                         "  option -init_from_temp_and_liqfrac seen; computing enthalpy from ice temperature,"
00426                         " liquid water fraction and thickness ...\n"); CHKERRQ(ierr);
00427 
00428       // use vWork3d as already-allocated space
00429       ierr = vWork3d.set_name("liqfrac"); CHKERRQ(ierr);
00430       ierr = vWork3d.set_attrs("internal", "liqfrac; temporary use during initialization",
00431                                "", ""); CHKERRQ(ierr);
00432       ierr = vWork3d.read(filename, last_record); CHKERRQ(ierr);
00433 
00434       ierr = compute_enthalpy(temperature, vWork3d, Enth3); CHKERRQ(ierr);
00435     }
00436 
00437     // restore the original value of pism_intent (currently: either
00438     // "model_state" or "diagnostic" depending on the "do_cold_ice_methods"
00439     // config parameter).
00440     ierr = Enth3.set_attr("pism_intent", enthalpy_pism_intent); CHKERRQ(ierr);
00441   }
00442 
00443   // re-set Href's pism_intent attribute
00444   if (config.get_flag("part_grid")) {
00445     ierr = vHref.set_attr("pism_intent", "model_state"); CHKERRQ(ierr);
00446   }
00447 
00448   string history;
00449   ierr = nc.get_att_text(NC_GLOBAL, "history", history); CHKERRQ(ierr);
00450   global_attributes.prepend_history(history);
00451 
00452   ierr = nc.close(); CHKERRQ(ierr);
00453 
00454   return 0;
00455 }
00456 
00458 
00471   PetscErrorCode IceModel::regrid(int dimensions) {
00472     PetscErrorCode ierr;
00473     string filename;
00474     bool regrid_vars_set, regrid_file_set;
00475     vector<string> vars_vector;
00476 
00477     if (! (dimensions == 0 ||
00478            dimensions == 2 ||
00479            dimensions == 3))
00480       SETERRQ(1, "dimensions can only be 0, 2 or 3");
00481 
00482     ierr = PetscOptionsBegin(grid.com, PETSC_NULL, "Options controlling regridding",
00483                              PETSC_NULL); CHKERRQ(ierr);
00484     {
00485       ierr = PISMOptionsString("-regrid_file", "Specifies the file to regrid from",
00486                                filename, regrid_file_set); CHKERRQ(ierr);
00487 
00488       ierr = PISMOptionsStringArray("-regrid_vars", "Specifies the list of variables to regrid",
00489                                     "", vars_vector, regrid_vars_set); CHKERRQ(ierr);
00490     }
00491     ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00492 
00493     // Return if no regridding is requested:
00494     if (!regrid_file_set) return 0;
00495 
00496     ierr = verbPrintf(2, grid.com, "regridding from file %s ...\n",filename.c_str()); CHKERRQ(ierr);
00497 
00498     set<string> vars;
00499     vector<string>::iterator j;
00500     for (j = vars_vector.begin(); j != vars_vector.end(); ++j)
00501       vars.insert(*j);
00502 
00503     if (vars.empty()) {
00504       // defaults if user gives no regrid_vars list
00505       vars.insert("litho_temp");
00506 
00507       if (config.get_flag("do_age"))
00508         vars.insert("age");
00509 
00510       if (config.get_flag("do_cold_ice_methods"))
00511         vars.insert("temp");
00512       else
00513         vars.insert("enthalpy");
00514     }
00515 
00516     if (dimensions == 0) {
00517       ierr = regrid_variables(filename, vars, 2); CHKERRQ(ierr); 
00518       ierr = regrid_variables(filename, vars, 3); CHKERRQ(ierr); 
00519     } else {
00520       ierr = regrid_variables(filename, vars, dimensions); CHKERRQ(ierr); 
00521     }
00522 
00523     return 0;
00524   }
00525 
00526 PetscErrorCode IceModel::regrid_variables(string filename, set<string> vars, int ndims) {
00527   PetscErrorCode ierr;
00528 
00529   set<string>::iterator i;
00530   for (i = vars.begin(); i != vars.end(); ++i) {
00531     IceModelVec *v = variables.get(*i);
00532 
00533     if (v == NULL) continue;
00534 
00535     if (v->get_ndims() != ndims) continue;
00536 
00537     string pism_intent = v->string_attr("pism_intent");
00538     if (pism_intent != "model_state") {
00539       ierr = verbPrintf(2, grid.com, "  WARNING: skipping '%s' (only model_state variables can be regridded)...\n",
00540                         (*i).c_str()); CHKERRQ(ierr);
00541       continue;
00542     }
00543 
00544     ierr = v->regrid(filename, true); CHKERRQ(ierr);
00545   }
00546 
00547   return 0;
00548 }
00549 
00550 
00552 PetscErrorCode IceModel::init_snapshots() {
00553   PetscErrorCode ierr;
00554   bool save_times_set, save_file_set, split;
00555   string tmp;
00556   current_snapshot = 0;
00557 
00558   ierr = PetscOptionsBegin(grid.com, "", "Options controlling the snapshot-saving mechanism", ""); CHKERRQ(ierr);
00559   {
00560     ierr = PISMOptionsString("-save_file", "Specifies a snapshot filename",
00561                              snapshots_filename, save_file_set); CHKERRQ(ierr);
00562 
00563     ierr = PISMOptionsString("-save_times", "Gives a list or a MATLAB-style range of times to save snapshots at",
00564                              tmp, save_times_set); CHKERRQ(ierr);
00565 
00566     ierr = PISMOptionsIsSet("-save_split", "Specifies whether to save snapshots to separate files",
00567                             split); CHKERRQ(ierr);
00568 
00569     ierr = set_output_size("-save_size", "Sets the 'size' of a snapshot file.",
00570                            "small", snapshot_vars); CHKERRQ(ierr);
00571   }
00572   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00573 
00574   if (save_file_set ^ save_times_set) {
00575     ierr = PetscPrintf(grid.com,
00576                        "PISM ERROR: you need to specify both -save_file and -save_times to save snapshots.\n");
00577     CHKERRQ(ierr);
00578     PISMEnd();
00579   }
00580 
00581   if (!save_file_set && !save_times_set) {
00582     save_snapshots = false;
00583     return 0;
00584   }
00585 
00586   ierr = parse_times(grid.com, tmp, snapshot_times);
00587   if (ierr != 0) {
00588     ierr = PetscPrintf(grid.com, "PISM ERROR: parsing the -save_times argument failed.\n"); CHKERRQ(ierr);
00589     PISMEnd();
00590   }
00591 
00592   if (snapshot_times.size() == 0) {
00593     PetscPrintf(grid.com, "PISM ERROR: no argument for -save_times option.\n");
00594     PISMEnd();
00595   }
00596 
00597   save_snapshots = true;
00598   snapshots_file_is_ready = false;
00599   split_snapshots = false;
00600 
00601   if (split) {
00602     split_snapshots = true;
00603   } else if (!ends_with(snapshots_filename, ".nc")) {
00604     ierr = verbPrintf(2, grid.com,
00605                       "PISM WARNING: snapshots file name does not have the '.nc' suffix!\n");
00606     CHKERRQ(ierr);
00607   }
00608 
00609   if (split) {
00610     ierr = verbPrintf(2, grid.com, "saving snapshots to '%s+year.nc'; ",
00611                       snapshots_filename.c_str()); CHKERRQ(ierr);
00612   } else {
00613     ierr = verbPrintf(2, grid.com, "saving snapshots to '%s'; ",
00614                       snapshots_filename.c_str()); CHKERRQ(ierr);
00615   }
00616 
00617   ierr = verbPrintf(2, grid.com, "times requested: %s\n", tmp.c_str()); CHKERRQ(ierr);
00618 
00619   return 0;
00620 }
00621 
00623   PetscErrorCode IceModel::write_snapshot() {
00624     PetscErrorCode ierr;
00625     PISMIO nc(&grid);
00626     double saving_after = -1.0e30; // initialize to avoid compiler warning; this
00627     // value is never used, because saving_after
00628     // is only used if save_now == true, and in
00629     // this case saving_after is guaranteed to be
00630     // initialized. See the code below.
00631     char filename[PETSC_MAX_PATH_LEN];
00632 
00633     // determine if the user set the -save_times and -save_file options
00634     if (!save_snapshots)
00635       return 0;
00636 
00637     // do we need to save *now*?
00638     if ( (grid.year >= snapshot_times[current_snapshot]) && (current_snapshot < snapshot_times.size()) ) {
00639       saving_after = snapshot_times[current_snapshot];
00640 
00641       while ((current_snapshot < snapshot_times.size()) &&
00642              (snapshot_times[current_snapshot] <= grid.year))
00643         current_snapshot++;
00644     } else {
00645       // we don't need to save now, so just return
00646       return 0;
00647     }
00648 
00649     grid.profiler->begin(event_snapshots);
00650 
00651     // flush time-series buffers
00652     ierr = flush_timeseries(); CHKERRQ(ierr);
00653 
00654     if (split_snapshots) {
00655       snapshots_file_is_ready = false;  // each snapshot is written to a separate file
00656       snprintf(filename, PETSC_MAX_PATH_LEN, "%s-%06.0f.nc",
00657                snapshots_filename.c_str(), grid.year);
00658     } else {
00659       strncpy(filename, snapshots_filename.c_str(), PETSC_MAX_PATH_LEN);
00660     }
00661 
00662     ierr = verbPrintf(2, grid.com,
00663                       "\nsaving snapshot to %s at %.5f a, for time-step goal %.5f a\n\n",
00664                       filename, grid.year,saving_after);
00665     CHKERRQ(ierr);
00666 
00667     // create line for history in .nc file, including time of write
00668 
00669     string date_str = pism_timestamp();
00670     char tmp[TEMPORARY_STRING_LENGTH];
00671     snprintf(tmp, TEMPORARY_STRING_LENGTH,
00672              "%s: %s snapshot at %10.5f a, for time-step goal %10.5f a\n",
00673              date_str.c_str(), executable_short_name.c_str(), grid.year, saving_after);
00674 
00675     if (!snapshots_file_is_ready) {
00676 
00677       // Prepare the snapshots file:
00678       ierr = nc.open_for_writing(filename, false, true); CHKERRQ(ierr);
00679       // append == false, check_dims == true
00680       ierr = nc.close(); CHKERRQ(ierr);
00681 
00682       ierr = write_metadata(filename); CHKERRQ(ierr);
00683 
00684       snapshots_file_is_ready = true;
00685     }
00686 
00687     ierr = nc.open_for_writing(filename, true, true); CHKERRQ(ierr);
00688     // append == true, check_dims == true
00689     ierr = nc.append_time(grid.year); CHKERRQ(ierr);
00690     ierr = nc.write_history(tmp); CHKERRQ(ierr); // append the history
00691     ierr = nc.close(); CHKERRQ(ierr);
00692 
00693     ierr = write_variables(filename, snapshot_vars, NC_DOUBLE);
00694 
00695     grid.profiler->end(event_snapshots);
00696 
00697     return 0;
00698   }
00699 
00701   PetscErrorCode IceModel::init_backups() {
00702     PetscErrorCode ierr;
00703     bool o_set;
00704 
00705     backup_interval = config.get("backup_interval");
00706 
00707     ierr = PetscOptionsBegin(grid.com, "", "PISM output options", ""); CHKERRQ(ierr);
00708     {
00709       ierr = PISMOptionsString("-o", "Output file name", backup_filename, o_set); CHKERRQ(ierr);
00710       if (!o_set)
00711         backup_filename = executable_short_name + "_backup.nc";
00712       else
00713         backup_filename = pism_filename_add_suffix(backup_filename, "_backup", "");
00714 
00715       ierr = PISMOptionsReal("-backup_interval", "Automatic backup interval, hours",
00716                              backup_interval, o_set); CHKERRQ(ierr);
00717 
00718       ierr = set_output_size("-backup_size", "Sets the 'size' of a backup file.",
00719                              "small", backup_vars); CHKERRQ(ierr);
00720     }
00721     ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00722 
00723     last_backup_time = 0.0;
00724 
00725     return 0;
00726   }
00727 
00729 PetscErrorCode IceModel::write_backup() {
00730   PetscErrorCode ierr;
00731   double wall_clock_hours;
00732   PISMIO nc(&grid);
00733 
00734   if (grid.rank == 0) {
00735     PetscLogDouble current_time;
00736     ierr = PetscGetTime(&current_time); CHKERRQ(ierr);
00737     wall_clock_hours = (current_time - start_time) / 3600.0;
00738   }
00739 
00740   MPI_Bcast(&wall_clock_hours, 1, MPI_DOUBLE, 0, grid.com);
00741 
00742   if (wall_clock_hours - last_backup_time < backup_interval)
00743     return 0;
00744 
00745   grid.profiler->begin(event_backups);
00746 
00747   last_backup_time = wall_clock_hours;
00748 
00749   // create a history string:
00750   string date_str = pism_timestamp();
00751   char tmp[TEMPORARY_STRING_LENGTH];
00752   snprintf(tmp, TEMPORARY_STRING_LENGTH,
00753            "%s automatic backup at %10.5f a, %3.3f hours after the beginning of the run\n",
00754            executable_short_name.c_str(), grid.year, wall_clock_hours);
00755 
00756   ierr = verbPrintf(2, grid.com,
00757                     "  Saving an automatic backup to '%s' (%1.3f hours after the beginning of the run)\n",
00758                     backup_filename.c_str(), wall_clock_hours); CHKERRQ(ierr);
00759 
00760   stampHistory(tmp);
00761 
00762   // write metadata:
00763   ierr = nc.open_for_writing(backup_filename.c_str(), false, true); CHKERRQ(ierr);
00764   // append == false, check_dims == true
00765   ierr = nc.append_time(grid.year); CHKERRQ(ierr);
00766   ierr = nc.close(); CHKERRQ(ierr);
00767 
00768   // Write metadata *before* variables:
00769   ierr = write_metadata(backup_filename.c_str()); CHKERRQ(ierr);
00770 
00771   ierr = write_variables(backup_filename.c_str(), backup_vars, NC_DOUBLE); CHKERRQ(ierr);
00772 
00773   // Also flush time-series:
00774   ierr = flush_timeseries(); CHKERRQ(ierr);
00775 
00776   grid.profiler->end(event_backups);
00777 
00778   return 0;
00779 }
00780 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines