|
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 <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(¤t_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
1.7.3