PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/iMtimeseries.cc

Go to the documentation of this file.
00001 // Copyright (C) 2009-2011 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 "iceModel.hh"
00020 #include <sstream>
00021 #include <algorithm>
00022 #include "PISMIO.hh"
00023 
00025 PetscErrorCode IceModel::init_timeseries() {
00026   PetscErrorCode ierr;
00027   bool ts_file_set, ts_times_set, ts_vars_set;
00028   string times, vars;
00029   bool append;
00030 
00031   ierr = PetscOptionsBegin(grid.com, "", "Options controlling scalar diagnostic time-series", ""); CHKERRQ(ierr);
00032   {
00033     ierr = PISMOptionsString("-ts_file", "Specifies the time-series output file name",
00034                              ts_filename, ts_file_set); CHKERRQ(ierr);
00035 
00036     ierr = PISMOptionsString("-ts_times", "Specifies a MATLAB-style range or a list of requested times",
00037                              times, ts_times_set); CHKERRQ(ierr);
00038 
00039     ierr = PISMOptionsString("-ts_vars", "Specifies a comma-separated list of veriables to save",
00040                              vars, ts_vars_set); CHKERRQ(ierr);
00041 
00042     // default behavior is to move the file aside if it exists already; option allows appending
00043     ierr = PISMOptionsIsSet("-ts_append", append); CHKERRQ(ierr);
00044   }
00045   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00046 
00047 
00048   if (ts_file_set ^ ts_times_set) {
00049     ierr = PetscPrintf(grid.com,
00050       "PISM ERROR: you need to specity both -ts_file and -ts_times to save"
00051       "diagnostic time-series.\n");
00052     CHKERRQ(ierr);
00053     PISMEnd();
00054   }
00055 
00056   // If neither -ts_filename nor -ts_times is set, we're done.
00057   if (!ts_file_set && !ts_times_set) {
00058     save_ts = false;
00059     return 0;
00060   }
00061   
00062   save_ts = true;
00063 
00064   ierr = parse_times(grid.com, times, ts_times);
00065   if (ierr != 0) {
00066     ierr = PetscPrintf(grid.com, "PISM ERROR: parsing the -ts_times argument failed.\n"); CHKERRQ(ierr);
00067     PISMEnd();
00068   }
00069 
00070   if (ts_times.size() == 0) {
00071     PetscPrintf(grid.com, "PISM ERROR: no argument for -ts_times option.\n");
00072     PISMEnd();
00073   }
00074 
00075   ierr = verbPrintf(2, grid.com, "saving scalar time-series to '%s'; ",
00076                     ts_filename.c_str()); CHKERRQ(ierr);
00077 
00078   ierr = verbPrintf(2, grid.com, "times requested: %s\n", times.c_str()); CHKERRQ(ierr);
00079 
00080   current_ts = 0;
00081 
00082 
00083   string var_name;
00084   if (ts_vars_set) {
00085     ierr = verbPrintf(2, grid.com, "variables requested: %s\n", vars.c_str()); CHKERRQ(ierr);
00086     istringstream arg(vars);
00087 
00088     while (getline(arg, var_name, ','))
00089       ts_vars.insert(var_name);
00090 
00091   } else {
00092     var_name = config.get_string("ts_default_variables");
00093     istringstream arg(var_name);
00094   
00095     while (getline(arg, var_name, ' ')) {
00096       if (!var_name.empty()) // this ignores multiple spaces separating variable names
00097         ts_vars.insert(var_name);
00098     }
00099   }
00100 
00101 
00102   PISMIO nc(&grid);
00103   ierr = nc.open_for_writing(ts_filename.c_str(), (append==PETSC_TRUE), false); CHKERRQ(ierr);
00104   ierr = nc.close(); CHKERRQ(ierr);
00105 
00106   ierr = create_timeseries(); CHKERRQ(ierr);
00107   
00108   return 0;
00109 }
00110 
00113 PetscErrorCode IceModel::create_timeseries() {
00114 
00115   string time_units = "years since " + config.get_string("reference_date");
00116   
00117   if (find(ts_vars.begin(), ts_vars.end(), "ivol") != ts_vars.end()) {
00118     DiagnosticTimeseries *ivol = new DiagnosticTimeseries(&grid, "ivol", "t");
00119 
00120     ivol->set_units("m3", "");
00121     ivol->set_dimension_units(time_units, "");
00122     ivol->output_filename = ts_filename;
00123 
00124     ivol->set_attr("long_name", "total ice volume");
00125     ivol->set_attr("valid_min", 0.0);
00126 
00127     timeseries.push_back(ivol);
00128   }
00129 
00130   if (find(ts_vars.begin(), ts_vars.end(), "ivoltemp") != ts_vars.end()) {
00131     DiagnosticTimeseries *ivoltemp = new DiagnosticTimeseries(&grid, "ivoltemp", "t");
00132 
00133     ivoltemp->set_units("m3", "");
00134     ivoltemp->set_dimension_units(time_units, "");
00135     ivoltemp->output_filename = ts_filename;
00136 
00137     ivoltemp->set_attr("long_name", "temperate ice volume");
00138     ivoltemp->set_attr("valid_min", 0.0);
00139 
00140     timeseries.push_back(ivoltemp);
00141   }
00142 
00143   if (find(ts_vars.begin(), ts_vars.end(), "ivoltempf") != ts_vars.end()) {
00144     DiagnosticTimeseries *ivoltempf = new DiagnosticTimeseries(&grid, "ivoltempf", "t");
00145 
00146     ivoltempf->set_units("1", "");
00147     ivoltempf->set_dimension_units(time_units, "");
00148     ivoltempf->output_filename = ts_filename;
00149 
00150     ivoltempf->set_attr("long_name", "temperate ice volume fraction");
00151     ivoltempf->set_attr("valid_min", 0.0);
00152 
00153     timeseries.push_back(ivoltempf);
00154   }
00155 
00156   if (find(ts_vars.begin(), ts_vars.end(), "ivolcold") != ts_vars.end()) {
00157     DiagnosticTimeseries *ivolcold = new DiagnosticTimeseries(&grid, "ivolcold", "t");
00158 
00159     ivolcold->set_units("m3", "");
00160     ivolcold->set_dimension_units(time_units, "");
00161     ivolcold->output_filename = ts_filename;
00162 
00163     ivolcold->set_attr("long_name", "cold ice volume");
00164     ivolcold->set_attr("valid_min", 0.0);
00165 
00166     timeseries.push_back(ivolcold);
00167   }
00168 
00169   if (find(ts_vars.begin(), ts_vars.end(), "ivolcoldf") != ts_vars.end()) {
00170     DiagnosticTimeseries *ivolcoldf = new DiagnosticTimeseries(&grid, "ivolcoldf", "t");
00171 
00172     ivolcoldf->set_units("1", "");
00173     ivolcoldf->set_dimension_units(time_units, "");
00174     ivolcoldf->output_filename = ts_filename;
00175 
00176     ivolcoldf->set_attr("long_name", "cold ice volume fraction");
00177     ivolcoldf->set_attr("valid_min", 0.0);
00178 
00179     timeseries.push_back(ivolcoldf);
00180   }
00181 
00182   if (find(ts_vars.begin(), ts_vars.end(), "ienthalpy") != ts_vars.end()) {
00183     DiagnosticTimeseries *ienthalpy = new DiagnosticTimeseries(&grid, "ienthalpy", "t");
00184 
00185     ienthalpy->set_units("J", "");
00186     ienthalpy->set_dimension_units(time_units, "");
00187     ienthalpy->output_filename = ts_filename;
00188 
00189     ienthalpy->set_attr("long_name", "total ice enthalpy");
00190     ienthalpy->set_attr("valid_min", 0.0);
00191 
00192     timeseries.push_back(ienthalpy);
00193   }
00194 
00195   if (find(ts_vars.begin(), ts_vars.end(), "imass") != ts_vars.end()) {
00196     DiagnosticTimeseries *imass = new DiagnosticTimeseries(&grid, "imass", "t");
00197 
00198     imass->set_units("kg", "");
00199     imass->set_dimension_units(time_units, "");
00200     imass->output_filename = ts_filename;
00201 
00202     imass->set_attr("long_name", "total ice mass");
00203     imass->set_attr("valid_min", 0.0);
00204 
00205     timeseries.push_back(imass);
00206   }
00207 
00208   if (find(ts_vars.begin(), ts_vars.end(), "iarea") != ts_vars.end()) {
00209     DiagnosticTimeseries *iarea = new DiagnosticTimeseries(&grid, "iarea", "t");
00210 
00211     iarea->set_units("m2", "");
00212     iarea->set_dimension_units(time_units, "");
00213     iarea->output_filename = ts_filename;
00214 
00215     iarea->set_attr("long_name", "ice area");
00216     iarea->set_attr("valid_min", 0.0);
00217 
00218     timeseries.push_back(iarea);
00219   }
00220 
00221   if (find(ts_vars.begin(), ts_vars.end(), "iareatemp") != ts_vars.end()) {
00222     DiagnosticTimeseries *iareatemp = new DiagnosticTimeseries(&grid, "iareatemp", "t");
00223 
00224     iareatemp->set_units("m2", "");
00225     iareatemp->set_dimension_units(time_units, "");
00226     iareatemp->output_filename = ts_filename;
00227 
00228     iareatemp->set_attr("long_name", "ice area temperate");
00229     iareatemp->set_attr("valid_min", 0.0);
00230 
00231     timeseries.push_back(iareatemp);
00232   }
00233 
00234   if (find(ts_vars.begin(), ts_vars.end(), "iareatempf") != ts_vars.end()) {
00235     DiagnosticTimeseries *iareatempf = new DiagnosticTimeseries(&grid, "iareatempf", "t");
00236 
00237     iareatempf->set_units("1", "");
00238     iareatempf->set_dimension_units(time_units, "");
00239     iareatempf->output_filename = ts_filename;
00240 
00241     iareatempf->set_attr("long_name", "ice area temperate fraction");
00242     iareatempf->set_attr("valid_min", 0.0);
00243 
00244     timeseries.push_back(iareatempf);
00245   }
00246 
00247   if (find(ts_vars.begin(), ts_vars.end(), "iareacold") != ts_vars.end()) {
00248     DiagnosticTimeseries *iareacold = new DiagnosticTimeseries(&grid, "iareacold", "t");
00249 
00250     iareacold->set_units("m2", "");
00251     iareacold->set_dimension_units(time_units, "");
00252     iareacold->output_filename = ts_filename;
00253 
00254     iareacold->set_attr("long_name", "ice area cold");
00255     iareacold->set_attr("valid_min", 0.0);
00256 
00257     timeseries.push_back(iareacold);
00258   }
00259 
00260   if (find(ts_vars.begin(), ts_vars.end(), "iareacoldf") != ts_vars.end()) {
00261     DiagnosticTimeseries *iareacoldf = new DiagnosticTimeseries(&grid, "iareacoldf", "t");
00262 
00263     iareacoldf->set_units("1", "");
00264     iareacoldf->set_dimension_units(time_units, "");
00265     iareacoldf->output_filename = ts_filename;
00266 
00267     iareacoldf->set_attr("long_name", "ice area cold fraction");
00268     iareacoldf->set_attr("valid_min", 0.0);
00269 
00270     timeseries.push_back(iareacoldf);
00271   }
00272 
00273   if (find(ts_vars.begin(), ts_vars.end(), "iareag") != ts_vars.end()) {
00274     DiagnosticTimeseries *iareag = new DiagnosticTimeseries(&grid, "iareag", "t");
00275 
00276     iareag->set_units("m2", "");
00277     iareag->set_dimension_units(time_units, "");
00278     iareag->output_filename = ts_filename;
00279 
00280     iareag->set_attr("long_name", "grounded ice area");
00281     iareag->set_attr("valid_min", 0.0);
00282 
00283     timeseries.push_back(iareag);
00284   }
00285 
00286   if (find(ts_vars.begin(), ts_vars.end(), "iareaf") != ts_vars.end()) {
00287     DiagnosticTimeseries *iareaf = new DiagnosticTimeseries(&grid, "iareaf", "t");
00288 
00289     iareaf->set_units("m2", "");
00290     iareaf->set_dimension_units(time_units, "");
00291     iareaf->output_filename = ts_filename;
00292 
00293     iareaf->set_attr("long_name", "floating ice area");
00294     iareaf->set_attr("valid_min", 0.0);
00295 
00296     timeseries.push_back(iareaf);
00297   }
00298 
00299   if (find(ts_vars.begin(), ts_vars.end(), "dt") != ts_vars.end()) {
00300     DiagnosticTimeseries *delta_t = new DiagnosticTimeseries(&grid, "dt", "t");
00301 
00302     delta_t->set_units("s", "years");
00303     delta_t->set_dimension_units(time_units, "");
00304     delta_t->output_filename = ts_filename;
00305 
00306     delta_t->set_attr("long_name", "mass continuity time-step");
00307     delta_t->set_attr("valid_min", 0.0);
00308 
00309     timeseries.push_back(delta_t);
00310   }
00311 
00312   // The following are in  config.get("ts_bad_set")  list.
00313 
00314   if (find(ts_vars.begin(), ts_vars.end(), "divoldt") != ts_vars.end()) {
00315     DiagnosticTimeseries *divoldt = new DiagnosticTimeseries(&grid, "divoldt", "t");
00316 
00317     divoldt->set_units("m3 s-1", "");
00318     divoldt->set_dimension_units(time_units, "");
00319     divoldt->output_filename = ts_filename;
00320 
00321     divoldt->set_attr("long_name", "total ice volume rate of change");
00322 
00323     timeseries.push_back(divoldt);
00324   }
00325 
00326   if (find(ts_vars.begin(), ts_vars.end(), "dimassdt") != ts_vars.end()) {
00327     DiagnosticTimeseries *dimassdt = new DiagnosticTimeseries(&grid, "dimassdt", "t");
00328 
00329     dimassdt->set_units("kg s-1", "");
00330     dimassdt->set_dimension_units(time_units, "");
00331     dimassdt->output_filename = ts_filename;
00332 
00333     dimassdt->set_attr("long_name", "total ice mass rate of change");
00334 
00335     timeseries.push_back(dimassdt);
00336   }
00337 
00338   if (find(ts_vars.begin(), ts_vars.end(), "surface_ice_flux") != ts_vars.end()) {
00339     DiagnosticTimeseries *tsif = new DiagnosticTimeseries(&grid, "surface_ice_flux", "t");
00340 
00341     tsif->set_units("kg s-1", "");
00342     tsif->set_dimension_units(time_units, "");
00343     tsif->output_filename = ts_filename;
00344 
00345     tsif->set_attr("long_name", "total over ice domain of top surface ice mass flux");
00346     tsif->set_attr("comment", "positive means ice gain");
00347 
00348     timeseries.push_back(tsif);
00349   }
00350 
00351   if (find(ts_vars.begin(), ts_vars.end(), "basal_ice_flux") != ts_vars.end()) {
00352     DiagnosticTimeseries *tbif = new DiagnosticTimeseries(&grid, "basal_ice_flux", "t");
00353 
00354     tbif->set_units("kg s-1", "");
00355     tbif->set_dimension_units(time_units, "");
00356     tbif->output_filename = ts_filename;
00357 
00358     tbif->set_attr("long_name", "total over ice domain of basal surface ice mass flux");
00359     tbif->set_attr("comment", "positive means ice gain");
00360 
00361     timeseries.push_back(tbif);
00362   }
00363 
00364   if (find(ts_vars.begin(), ts_vars.end(), "sub_shelf_ice_flux") != ts_vars.end()) {
00365     DiagnosticTimeseries *tssif = new DiagnosticTimeseries(&grid, "sub_shelf_ice_flux", "t");
00366 
00367     tssif->set_units("kg s-1", "");
00368     tssif->set_dimension_units(time_units, "");
00369     tssif->output_filename = ts_filename;
00370 
00371     tssif->set_attr("long_name", "total over ice domain of sub-ice-shelf ice mass flux");
00372     tssif->set_attr("comment", "positive means ice gain");
00373 
00374     timeseries.push_back(tssif);
00375   }
00376 
00377   if (find(ts_vars.begin(), ts_vars.end(), "nonneg_rule_flux") != ts_vars.end()) {
00378     DiagnosticTimeseries *ts = new DiagnosticTimeseries(&grid, "nonneg_rule_flux", "t");
00379 
00380     ts->set_units("kg s-1", "");
00381     ts->set_dimension_units(time_units, "");
00382     ts->output_filename = ts_filename;
00383 
00384     ts->set_attr("long_name", "total over ice domain of ice mass gain by application of non-negative thickness rule");
00385     ts->set_attr("comment", "positive means ice gain");
00386 
00387     timeseries.push_back(ts);
00388   }
00389 
00390   if (find(ts_vars.begin(), ts_vars.end(), "ocean_kill_flux") != ts_vars.end()) {
00391     DiagnosticTimeseries *ts = new DiagnosticTimeseries(&grid, "ocean_kill_flux", "t");
00392 
00393     ts->set_units("kg s-1", "");
00394     ts->set_dimension_units(time_units, "");
00395     ts->output_filename = ts_filename;
00396 
00397     ts->set_attr("long_name", "total over ice domain of ice mass gain by calving by application of -ocean_kill mechanism");
00398     ts->set_attr("comment", "positive means ice gain");
00399 
00400     timeseries.push_back(ts);
00401   }
00402 
00403   if (find(ts_vars.begin(), ts_vars.end(), "float_kill_flux") != ts_vars.end()) {
00404     DiagnosticTimeseries *ts = new DiagnosticTimeseries(&grid, "float_kill_flux", "t");
00405 
00406     ts->set_units("kg s-1", "");
00407     ts->set_dimension_units(time_units, "");
00408     ts->output_filename = ts_filename;
00409 
00410     ts->set_attr("long_name", "total over ice domain of ice mass gain by calving by application of -float_kill mechanism");
00411     ts->set_attr("comment", "positive means ice gain");
00412 
00413     timeseries.push_back(ts);
00414   }
00415 
00416   // as noted above, the variables listed in the bad_set may require a user to 
00417   // very carefully interpret; thus the need to add a warning
00418   string warning = config.get_string("ts_bad_set_warning"),
00419          tmp;
00420   istringstream arg(config.get_string("ts_bad_set_variables")); // string becomes stream
00421   set<string> bad_vars;
00422   while (getline(arg, tmp, ' ')) {
00423     if (!tmp.empty()) // this ignores multiple spaces separating variable names
00424       bad_vars.insert(tmp);
00425   }
00426   for (size_t i = 0; i < timeseries.size(); i++) {
00427     if (set_contains(bad_vars,timeseries[i]->short_name)) {
00428       timeseries[i]->set_attr("interpretation_warning", warning);
00429     }
00430   }
00431 
00432   return 0;
00433 }
00434 
00436 PetscErrorCode IceModel::write_timeseries() {
00437   PetscErrorCode ierr;
00438   vector<DiagnosticTimeseries*>::iterator i;
00439 
00440   // return if no time-series requested
00441   if (!save_ts) return 0;
00442 
00443   // return if wrote all the records already
00444   if (current_ts == ts_times.size())
00445     return 0;
00446 
00447   // return if did not yet reach the time we need to save at
00448   if (ts_times[current_ts] > grid.year)
00449     return 0;
00450 
00451   // compute values of requested scalar quantities:
00452   for (i = timeseries.begin(); i < timeseries.end(); ++i) {
00453     PetscScalar tmp;
00454 
00455     ierr = compute_by_name((*i)->short_name, tmp); CHKERRQ(ierr);
00456     
00457     (*i)->append(grid.year, tmp);
00458   }
00459 
00460   // Interpolate to put them on requested times:
00461   while ((current_ts < ts_times.size()) &&
00462          (ts_times[current_ts] <= grid.year)) {
00463     
00464     for (i = timeseries.begin(); i < timeseries.end(); ++i) {
00465       ierr = (*i)->interp(ts_times[current_ts]); CHKERRQ(ierr);
00466     }
00467 
00468     current_ts++;
00469   }
00470 
00471   return 0;
00472 }
00473 
00474 
00476 PetscErrorCode IceModel::init_extras() {
00477   PetscErrorCode ierr;
00478   bool split, times_set, file_set, save_vars;
00479   string times, vars;
00480   current_extra = 0;
00481 
00482   ierr = PetscOptionsBegin(grid.com, "", "Options controlling 2D and 3D diagnostic output", ""); CHKERRQ(ierr);
00483   {
00484     ierr = PISMOptionsString("-extra_file", "Specifies the output file",
00485                              extra_filename, file_set); CHKERRQ(ierr);
00486 
00487     ierr = PISMOptionsString("-extra_times", "Specifies times to save at",
00488                              times, times_set); CHKERRQ(ierr);
00489                              
00490     ierr = PISMOptionsString("-extra_vars", "Spacifies a comma-separated list of variables to save",
00491                              vars, save_vars); CHKERRQ(ierr);
00492 
00493     ierr = PISMOptionsIsSet("-extra_split", "Specifies whether to save to separate files",
00494                             split); CHKERRQ(ierr);
00495   }
00496   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00497 
00498   if (file_set ^ times_set) {
00499     PetscPrintf(grid.com,
00500       "PISM ERROR: you need to specify both -extra_file and -extra_times to save spatial time-series.\n");
00501     PISMEnd();
00502   }
00503 
00504   if (!file_set && !times_set) {
00505     save_extra = false;
00506     return 0;
00507   }
00508 
00509   ierr = parse_times(grid.com, times, extra_times);
00510   if (ierr != 0) {
00511     PetscPrintf(grid.com, "PISM ERROR: parsing the -extra_times argument failed.\n");
00512     PISMEnd();
00513   }
00514   if (extra_times.size() == 0) {
00515     PetscPrintf(grid.com, "PISM ERROR: no argument for -extra_times option.\n");
00516     PISMEnd();
00517   }
00518 
00519   save_extra = true;
00520   extra_file_is_ready = false;
00521   split_extra = false;
00522 
00523   if (split) {
00524     split_extra = true;
00525   } else if (!ends_with(extra_filename, ".nc")) {
00526     ierr = verbPrintf(2, grid.com,
00527                       "PISM WARNING: spatial time-series file name '%s' does not have the '.nc' suffix!\n",
00528                       extra_filename.c_str());
00529     CHKERRQ(ierr);
00530   }
00531   
00532   if (split) {
00533     ierr = verbPrintf(2, grid.com, "saving spatial time-series to '%s+year.nc'; ",
00534                       extra_filename.c_str()); CHKERRQ(ierr);
00535   } else {
00536     ierr = verbPrintf(2, grid.com, "saving spatial time-series to '%s'; ",
00537                       extra_filename.c_str()); CHKERRQ(ierr);
00538   }
00539 
00540   if (extra_times.size() > 500) {
00541     ierr = verbPrintf(2, grid.com,
00542                       "PISM WARNING: more than 500 times requested. This might fill your hard-drive!\n");
00543     CHKERRQ(ierr);
00544   }
00545 
00546   ierr = verbPrintf(2, grid.com, "times requested: %s\n", times.c_str()); CHKERRQ(ierr);
00547 
00548   string var_name;
00549   if (save_vars) {
00550     ierr = verbPrintf(2, grid.com, "variables requested: %s\n", vars.c_str()); CHKERRQ(ierr);
00551     istringstream arg(vars);
00552 
00553     while (getline(arg, var_name, ','))
00554       extra_vars.insert(var_name);
00555 
00556   } else {
00557     ierr = verbPrintf(2, grid.com, "PISM WARNING: -extra_vars was not set."
00558                       " Writing model_state, mapping and climate_steady variables...\n"); CHKERRQ(ierr);
00559 
00560     set<string> vars_set = variables.keys();
00561 
00562     set<string>::iterator i = vars_set.begin();
00563     while (i != vars_set.end()) {
00564       IceModelVec *var = variables.get(*i);
00565       
00566       string intent = var->string_attr("pism_intent");
00567       if ((intent == "model_state") ||
00568           (intent == "mapping") ||
00569           (intent == "climate_steady")) {
00570         extra_vars.insert(*i);
00571       }
00572       i++;
00573     }
00574 
00575     if (stress_balance)
00576       stress_balance->add_vars_to_output("small", extra_vars);
00577 
00578   }
00579   if (extra_vars.size() == 0) {
00580     ierr = verbPrintf(2, grid.com, 
00581        "PISM WARNING: no variables list after -extra_vars ... writing empty file ...\n"); CHKERRQ(ierr);
00582   }
00583 
00584   return 0;
00585 }
00586 
00588 PetscErrorCode IceModel::write_extras() {
00589   PetscErrorCode ierr;
00590   PISMIO nc(&grid);
00591   double saving_after = -1.0e30; // initialize to avoid compiler warning; this
00592                                  // value is never used, because saving_after
00593                                  // is only used if save_now == true, and in
00594                                  // this case saving_after is guaranteed to be
00595                                  // initialized. See the code below.
00596   char filename[PETSC_MAX_PATH_LEN];
00597 
00598   // determine if the user set the -save_at and -save_to options
00599   if (!save_extra)
00600     return 0;
00601 
00602   // do we need to save *now*?
00603   if ( current_extra < extra_times.size() && grid.year >= extra_times[current_extra] ) {
00604     saving_after = extra_times[current_extra];
00605 
00606     while (current_extra < extra_times.size() && extra_times[current_extra] <= grid.year)
00607       current_extra++;
00608   } else {
00609     // we don't need to save now, so just return
00610     return 0;
00611   }
00612 
00613   if (saving_after < grid.start_year) {
00614     // Suppose a user tells PISM to write data at times 0:1000:10000. Suppose
00615     // also that PISM writes a backup file at year 2500 and gets stopped.
00616     // 
00617     // When restarted, PISM will decide that it's time to write data for time
00618     // 2000, but
00619     // * that record was written already and
00620     // * PISM will end up writing at year 2500, producing a file containing one
00621     //   more record than necessary.
00622     // 
00623     // This check makes sure that this never happens.
00624     return 0;
00625   }
00626 
00627   if (split_extra) {
00628     extra_file_is_ready = false;        // each time-series record is written to a separate file
00629     snprintf(filename, PETSC_MAX_PATH_LEN, "%s-%06.0f.nc",
00630              extra_filename.c_str(), grid.year);
00631   } else {
00632     strncpy(filename, extra_filename.c_str(), PETSC_MAX_PATH_LEN);
00633   }
00634 
00635   ierr = verbPrintf(3, grid.com, 
00636                     "\nsaving spatial time-series to %s at %.5f a\n\n",
00637                     filename, grid.year);
00638   CHKERRQ(ierr);
00639 
00640   // create line for history in .nc file, including time of write
00641   string date_str = pism_timestamp();
00642   char tmp[TEMPORARY_STRING_LENGTH];
00643   snprintf(tmp, TEMPORARY_STRING_LENGTH,
00644            "%s: %s saving spatial time-series record at %10.5f a\n",
00645            date_str.c_str(), executable_short_name.c_str(), grid.year);
00646 
00647   if (!extra_file_is_ready) {
00648 
00649     // default behavior is to move the file aside if it exists already; option allows appending
00650     bool append;
00651     ierr = PISMOptionsIsSet("-extra_append", append); CHKERRQ(ierr);
00652 
00653     // Prepare the file:
00654     ierr = nc.open_for_writing(filename, (append==PETSC_TRUE), true); CHKERRQ(ierr); // check_dims == true
00655     ierr = nc.close(); CHKERRQ(ierr);
00656 
00657     ierr = write_metadata(filename); CHKERRQ(ierr); 
00658 
00659     extra_file_is_ready = true;
00660   }
00661     
00662   ierr = nc.open_for_writing(filename, true, true); CHKERRQ(ierr);
00663   // append == true, check_dims == true
00664   ierr = nc.append_time(grid.year); CHKERRQ(ierr);
00665   ierr = nc.write_history(tmp); CHKERRQ(ierr); // append the history
00666   ierr = nc.close(); CHKERRQ(ierr);
00667 
00668   ierr = write_variables(filename, extra_vars, NC_FLOAT);  CHKERRQ(ierr);
00669     
00670   return 0;
00671 }
00672 
00674 
00677 PetscErrorCode IceModel::extras_max_timestep(double t_years, double& dt_years) {
00678 
00679   if (!save_extra) {
00680     dt_years = -1;
00681     return 0;
00682   }
00683 
00684   bool force_times;
00685   force_times = config.get_flag("force_output_times");
00686 
00687   if (!force_times) {
00688     dt_years = -1;
00689     return 0;
00690   }
00691 
00692   vector<double>::iterator j;
00693   j = upper_bound(extra_times.begin(), extra_times.end(), t_years);
00694 
00695   if (j == extra_times.end()) {
00696     dt_years = -1;
00697     return 0;
00698   }
00699 
00700   dt_years = *j - t_years;
00701   return 0;
00702 }
00703 
00705 
00708 PetscErrorCode IceModel::ts_max_timestep(double t_years, double& dt_years) {
00709 
00710   if (!save_ts) {
00711     dt_years = -1;
00712     return 0;
00713   }
00714 
00715   bool force_times;
00716   force_times = config.get_flag("force_output_times");
00717 
00718   if (!force_times) {
00719     dt_years = -1;
00720     return 0;
00721   }
00722 
00723   vector<double>::iterator j;
00724   j = upper_bound(ts_times.begin(), ts_times.end(), t_years);
00725 
00726   if (j == ts_times.end()) {
00727     dt_years = -1;
00728     return 0;
00729   }
00730 
00731   dt_years = *j - t_years;
00732   return 0;
00733 }
00734 
00736 PetscErrorCode IceModel::flush_timeseries() {
00737   // flush all the time-series buffers:
00738   vector<DiagnosticTimeseries*>::iterator i;
00739   for (i = timeseries.begin(); i < timeseries.end(); ++i) {
00740     (*i)->flush();
00741   }
00742 
00743   return 0;
00744 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines