00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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 PetscEnd();
00054 }
00055
00056
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 PetscEnd();
00068 }
00069
00070 if (ts_times.size() == 0) {
00071 PetscPrintf(grid.com, "PISM ERROR: no argument for -ts_times option.\n");
00072 PetscEnd();
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_variables");
00093 istringstream arg(var_name);
00094
00095 while (getline(arg, var_name, ' ')) {
00096 if (!var_name.empty())
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 if (find(ts_vars.begin(), ts_vars.end(), "ivol") != ts_vars.end()) {
00116 DiagnosticTimeseries *ivol = new DiagnosticTimeseries(&grid, "ivol", "t");
00117
00118 ivol->set_units("m3", "");
00119 ivol->set_dimension_units("years", "");
00120 ivol->output_filename = ts_filename;
00121
00122 ivol->set_attr("long_name", "total ice volume");
00123 ivol->set_attr("valid_min", 0.0);
00124
00125 timeseries.push_back(ivol);
00126 }
00127
00128 if (find(ts_vars.begin(), ts_vars.end(), "ienthalpy") != ts_vars.end()) {
00129 DiagnosticTimeseries *ienthalpy = new DiagnosticTimeseries(&grid, "ienthalpy", "t");
00130
00131 ienthalpy->set_units("J", "");
00132 ienthalpy->set_dimension_units("years", "");
00133 ienthalpy->output_filename = ts_filename;
00134
00135 ienthalpy->set_attr("long_name", "total ice enthalpy");
00136 ienthalpy->set_attr("valid_min", 0.0);
00137
00138 timeseries.push_back(ienthalpy);
00139 }
00140
00141 if (find(ts_vars.begin(), ts_vars.end(), "imass") != ts_vars.end()) {
00142 DiagnosticTimeseries *imass = new DiagnosticTimeseries(&grid, "imass", "t");
00143
00144 imass->set_units("kg", "");
00145 imass->set_dimension_units("years", "");
00146 imass->output_filename = ts_filename;
00147
00148 imass->set_attr("long_name", "total ice mass");
00149 imass->set_attr("valid_min", 0.0);
00150
00151 timeseries.push_back(imass);
00152 }
00153
00154 if (find(ts_vars.begin(), ts_vars.end(), "iarea") != ts_vars.end()) {
00155 DiagnosticTimeseries *iarea = new DiagnosticTimeseries(&grid, "iarea", "t");
00156
00157 iarea->set_units("m2", "");
00158 iarea->set_dimension_units("years", "");
00159 iarea->output_filename = ts_filename;
00160
00161 iarea->set_attr("long_name", "ice area");
00162 iarea->set_attr("valid_min", 0.0);
00163
00164 timeseries.push_back(iarea);
00165 }
00166
00167 if (find(ts_vars.begin(), ts_vars.end(), "iareag") != ts_vars.end()) {
00168 DiagnosticTimeseries *iareag = new DiagnosticTimeseries(&grid, "iareag", "t");
00169
00170 iareag->set_units("m2", "");
00171 iareag->set_dimension_units("years", "");
00172 iareag->output_filename = ts_filename;
00173
00174 iareag->set_attr("long_name", "grounded ice area");
00175 iareag->set_attr("valid_min", 0.0);
00176
00177 timeseries.push_back(iareag);
00178 }
00179
00180 if (find(ts_vars.begin(), ts_vars.end(), "iareaf") != ts_vars.end()) {
00181 DiagnosticTimeseries *iareaf = new DiagnosticTimeseries(&grid, "iareaf", "t");
00182
00183 iareaf->set_units("m2", "");
00184 iareaf->set_dimension_units("years", "");
00185 iareaf->output_filename = ts_filename;
00186
00187 iareaf->set_attr("long_name", "floating ice area");
00188 iareaf->set_attr("valid_min", 0.0);
00189
00190 timeseries.push_back(iareaf);
00191 }
00192
00193 if (find(ts_vars.begin(), ts_vars.end(), "dt") != ts_vars.end()) {
00194 DiagnosticTimeseries *delta_t = new DiagnosticTimeseries(&grid, "dt", "t");
00195
00196 delta_t->set_units("s", "years");
00197 delta_t->set_dimension_units("years", "");
00198 delta_t->output_filename = ts_filename;
00199
00200 delta_t->set_attr("long_name", "mass continuity time-step");
00201 delta_t->set_attr("valid_min", 0.0);
00202
00203 timeseries.push_back(delta_t);
00204 }
00205
00206 if (find(ts_vars.begin(), ts_vars.end(), "divoldt") != ts_vars.end()) {
00207 DiagnosticTimeseries *divoldt = new DiagnosticTimeseries(&grid, "divoldt", "t");
00208
00209 divoldt->set_units("m3 s-1", "");
00210 divoldt->set_dimension_units("years", "");
00211 divoldt->output_filename = ts_filename;
00212
00213 divoldt->set_attr("long_name", "total ice volume rate of change");
00214
00215 timeseries.push_back(divoldt);
00216 }
00217
00218 if (find(ts_vars.begin(), ts_vars.end(), "dimassdt") != ts_vars.end()) {
00219 DiagnosticTimeseries *dimassdt = new DiagnosticTimeseries(&grid, "dimassdt", "t");
00220
00221 dimassdt->set_units("kg s-1", "");
00222 dimassdt->set_dimension_units("years", "");
00223 dimassdt->output_filename = ts_filename;
00224
00225 dimassdt->set_attr("long_name", "total ice mass rate of change");
00226
00227 timeseries.push_back(dimassdt);
00228 }
00229
00230 if (find(ts_vars.begin(), ts_vars.end(), "total_surface_ice_flux") != ts_vars.end()) {
00231 DiagnosticTimeseries *tsif = new DiagnosticTimeseries(&grid, "total_surface_ice_flux", "t");
00232
00233 tsif->set_units("kg s-1", "");
00234 tsif->set_dimension_units("years", "");
00235 tsif->output_filename = ts_filename;
00236
00237 tsif->set_attr("long_name", "total top surface ice flux");
00238 tsif->set_attr("comment", "positive means ice gain");
00239
00240 timeseries.push_back(tsif);
00241 }
00242
00243 if (find(ts_vars.begin(), ts_vars.end(), "total_basal_ice_flux") != ts_vars.end()) {
00244 DiagnosticTimeseries *tbif = new DiagnosticTimeseries(&grid, "total_basal_ice_flux", "t");
00245
00246 tbif->set_units("kg s-1", "");
00247 tbif->set_dimension_units("years", "");
00248 tbif->output_filename = ts_filename;
00249
00250 tbif->set_attr("long_name", "total basal ice flux");
00251 tbif->set_attr("comment", "positive means ice gain");
00252
00253 timeseries.push_back(tbif);
00254 }
00255
00256 if (find(ts_vars.begin(), ts_vars.end(), "total_sub_shelf_ice_flux") != ts_vars.end()) {
00257 DiagnosticTimeseries *tssif = new DiagnosticTimeseries(&grid, "total_sub_shelf_ice_flux", "t");
00258
00259 tssif->set_units("kg s-1", "");
00260 tssif->set_dimension_units("years", "");
00261 tssif->output_filename = ts_filename;
00262
00263 tssif->set_attr("long_name", "total sub-ice-shelf ice flux");
00264 tssif->set_attr("comment", "positive means ice gain");
00265
00266 timeseries.push_back(tssif);
00267 }
00268
00269 return 0;
00270 }
00271
00273 PetscErrorCode IceModel::write_timeseries() {
00274 PetscErrorCode ierr;
00275
00276
00277 if (!save_ts) return 0;
00278
00279
00280 if (current_ts == ts_times.size())
00281 return 0;
00282
00283
00284 if (ts_times[current_ts] > grid.year)
00285 return 0;
00286
00287
00288 vector<DiagnosticTimeseries*>::iterator i;
00289 for (i = timeseries.begin(); i < timeseries.end(); ++i) {
00290 PetscScalar tmp;
00291
00292 ierr = compute_by_name((*i)->short_name, tmp); CHKERRQ(ierr);
00293
00294 (*i)->append(grid.year, tmp);
00295 }
00296
00297
00298 while ((current_ts < ts_times.size()) &&
00299 (ts_times[current_ts] <= grid.year)) {
00300
00301 vector<DiagnosticTimeseries*>::iterator i;
00302 for (i = timeseries.begin(); i < timeseries.end(); ++i) {
00303 ierr = (*i)->interp(ts_times[current_ts]); CHKERRQ(ierr);
00304 }
00305
00306 current_ts++;
00307 }
00308
00309 return 0;
00310 }
00311
00312
00314 PetscErrorCode IceModel::init_extras() {
00315 PetscErrorCode ierr;
00316 bool split, times_set, file_set, save_vars;
00317 string times, vars;
00318 current_extra = 0;
00319
00320 ierr = PetscOptionsBegin(grid.com, "", "Options controlling 2D and 3D diagnostic output", ""); CHKERRQ(ierr);
00321 {
00322 ierr = PISMOptionsString("-extra_file", "Specifies the output file",
00323 extra_filename, file_set); CHKERRQ(ierr);
00324
00325 ierr = PISMOptionsString("-extra_times", "Specifies times to save at",
00326 times, times_set); CHKERRQ(ierr);
00327
00328 ierr = PISMOptionsString("-extra_vars", "Spacifies a comma-separated list of variables to save",
00329 vars, save_vars); CHKERRQ(ierr);
00330
00331 ierr = PISMOptionsIsSet("-extra_split", "Specifies whether to save to separate files",
00332 split); CHKERRQ(ierr);
00333 }
00334 ierr = PetscOptionsEnd(); CHKERRQ(ierr);
00335
00336 if (file_set ^ times_set) {
00337 PetscPrintf(grid.com,
00338 "PISM ERROR: you need to specify both -extra_file and -extra_times to save spatial time-series.\n");
00339 PetscEnd();
00340 }
00341
00342 if (!file_set && !times_set) {
00343 save_extra = false;
00344 return 0;
00345 }
00346
00347 ierr = parse_times(grid.com, times, extra_times);
00348 if (ierr != 0) {
00349 PetscPrintf(grid.com, "PISM ERROR: parsing the -extra_times argument failed.\n");
00350 PetscEnd();
00351 }
00352 if (extra_times.size() == 0) {
00353 PetscPrintf(grid.com, "PISM ERROR: no argument for -extra_times option.\n");
00354 PetscEnd();
00355 }
00356
00357 save_extra = true;
00358 extra_file_is_ready = false;
00359 split_extra = false;
00360
00361 if (split) {
00362 split_extra = true;
00363 } else if (!ends_with(extra_filename, ".nc")) {
00364 ierr = verbPrintf(2, grid.com,
00365 "PISM WARNING: spatial time-series file name '%s' does not have the '.nc' suffix!\n",
00366 extra_filename.c_str());
00367 CHKERRQ(ierr);
00368 }
00369
00370 if (split) {
00371 ierr = verbPrintf(2, grid.com, "saving spatial time-series to '%s+year.nc'; ",
00372 extra_filename.c_str()); CHKERRQ(ierr);
00373 } else {
00374 ierr = verbPrintf(2, grid.com, "saving spatial time-series to '%s'; ",
00375 extra_filename.c_str()); CHKERRQ(ierr);
00376 }
00377
00378 if (extra_times.size() > 500) {
00379 ierr = verbPrintf(2, grid.com,
00380 "PISM WARNING: more than 500 times requested. This might fill your hard-drive!\n");
00381 CHKERRQ(ierr);
00382 }
00383
00384 ierr = verbPrintf(2, grid.com, "times requested: %s\n", times.c_str()); CHKERRQ(ierr);
00385
00386 string var_name;
00387 if (save_vars) {
00388 ierr = verbPrintf(2, grid.com, "variables requested: %s\n", vars.c_str()); CHKERRQ(ierr);
00389 istringstream arg(vars);
00390
00391 while (getline(arg, var_name, ','))
00392 extra_vars.insert(var_name);
00393
00394 } else {
00395 ierr = verbPrintf(2, grid.com, "PISM WARNING: -extra_vars was not set. Writing model_state, mapping and climate_steady variables...\n"); CHKERRQ(ierr);
00396
00397 set<IceModelVec*> vars = variables.get_variables();
00398 set<IceModelVec*>::iterator i = vars.begin();
00399 while (i != vars.end()) {
00400
00401 string intent = (*i)->string_attr("pism_intent");
00402 if ( (intent == "model_state") || (intent == "mapping") ||
00403 (intent == "climate_steady") )
00404 extra_vars.insert((*i)->string_attr("name"));
00405
00406 ++i;
00407 }
00408
00409
00410 if (config.get_flag("use_ssa_velocity")) {
00411 extra_vars.insert("uvbar_ssa");
00412 }
00413
00414 }
00415 if (extra_vars.size() == 0) {
00416 ierr = verbPrintf(2, grid.com,
00417 "PISM WARNING: no variables list after -extra_vars ... writing empty file ...\n"); CHKERRQ(ierr);
00418 }
00419
00420 return 0;
00421 }
00422
00424 PetscErrorCode IceModel::write_extras() {
00425 PetscErrorCode ierr;
00426 PISMIO nc(&grid);
00427 double saving_after = -1.0e30;
00428
00429
00430
00431
00432 char filename[PETSC_MAX_PATH_LEN];
00433
00434
00435 if (!save_extra)
00436 return 0;
00437
00438
00439 if ( (grid.year >= extra_times[current_extra]) &&
00440 (current_extra < extra_times.size()) ) {
00441 saving_after = extra_times[current_extra];
00442
00443 while ((current_extra < extra_times.size()) &&
00444 (extra_times[current_extra] <= grid.year))
00445 current_extra++;
00446 } else {
00447
00448 return 0;
00449 }
00450
00451 if (split_extra) {
00452 extra_file_is_ready = false;
00453 snprintf(filename, PETSC_MAX_PATH_LEN, "%s-%06.0f.nc",
00454 extra_filename.c_str(), grid.year);
00455 } else {
00456 strncpy(filename, extra_filename.c_str(), PETSC_MAX_PATH_LEN);
00457 }
00458
00459 ierr = verbPrintf(3, grid.com,
00460 "\nsaving spatial time-series to %s at %.5f a\n\n",
00461 filename, grid.year);
00462 CHKERRQ(ierr);
00463
00464
00465 string date_str = pism_timestamp();
00466 char tmp[TEMPORARY_STRING_LENGTH];
00467 snprintf(tmp, TEMPORARY_STRING_LENGTH,
00468 "%s: %s saving spatial time-series record at %10.5f a\n",
00469 date_str.c_str(), executable_short_name.c_str(), grid.year);
00470
00471 if (!extra_file_is_ready) {
00472
00473
00474 bool append;
00475 ierr = PISMOptionsIsSet("-extra_append", append); CHKERRQ(ierr);
00476
00477
00478 ierr = nc.open_for_writing(filename, (append==PETSC_TRUE), true); CHKERRQ(ierr);
00479 ierr = nc.close(); CHKERRQ(ierr);
00480
00481 ierr = global_attributes.write(filename); CHKERRQ(ierr);
00482 ierr = mapping.write(filename); CHKERRQ(ierr);
00483 extra_file_is_ready = true;
00484 }
00485
00486 ierr = nc.open_for_writing(filename, true, true); CHKERRQ(ierr);
00487
00488 ierr = nc.append_time(grid.year); CHKERRQ(ierr);
00489 ierr = nc.write_history(tmp); CHKERRQ(ierr);
00490 ierr = nc.close(); CHKERRQ(ierr);
00491
00492 ierr = write_variables(filename, extra_vars, NC_FLOAT); CHKERRQ(ierr);
00493
00494 if (surface != PETSC_NULL) {
00495 ierr = surface->write_fields(extra_vars, grid.year, dt / secpera, filename); CHKERRQ(ierr);
00496 } else {
00497 SETERRQ(1,"PISM ERROR: surface == PETSC_NULL");
00498 }
00499 if (ocean != PETSC_NULL) {
00500 ierr = ocean->write_fields(extra_vars, grid.year, dt / secpera, filename); CHKERRQ(ierr);
00501 } else {
00502 SETERRQ(1,"PISM ERROR: ocean == PETSC_NULL");
00503 }
00504
00505 return 0;
00506 }
00507
00509
00512 PetscErrorCode IceModel::extras_max_timestep(double t_years, double& dt_years) {
00513
00514 if (!save_extra) {
00515 dt_years = -1;
00516 return 0;
00517 }
00518
00519 bool force_times;
00520 force_times = config.get_flag("force_output_times");
00521
00522 if (!force_times) {
00523 dt_years = -1;
00524 return 0;
00525 }
00526
00527 vector<double>::iterator j;
00528 j = upper_bound(extra_times.begin(), extra_times.end(), t_years);
00529
00530 if (j == extra_times.end()) {
00531 dt_years = -1;
00532 return 0;
00533 }
00534
00535 dt_years = *j - t_years;
00536 return 0;
00537 }
00538
00540
00543 PetscErrorCode IceModel::ts_max_timestep(double t_years, double& dt_years) {
00544
00545 if (!save_ts) {
00546 dt_years = -1;
00547 return 0;
00548 }
00549
00550 bool force_times;
00551 force_times = config.get_flag("force_output_times");
00552
00553 if (!force_times) {
00554 dt_years = -1;
00555 return 0;
00556 }
00557
00558 vector<double>::iterator j;
00559 j = upper_bound(ts_times.begin(), ts_times.end(), t_years);
00560
00561 if (j == ts_times.end()) {
00562 dt_years = -1;
00563 return 0;
00564 }
00565
00566 dt_years = *j - t_years;
00567 return 0;
00568 }