pism

[fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
git clone git://src.adamsgaard.dk/pism # fast
git clone https://src.adamsgaard.dk/pism.git # slow
Log | Files | Refs | README | LICENSE Back to index

output_save.cc (5594B)


      1 /* Copyright (C) 2017, 2018, 2019 PISM Authors
      2  *
      3  * This file is part of PISM.
      4  *
      5  * PISM is free software; you can redistribute it and/or modify it under the
      6  * terms of the GNU General Public License as published by the Free Software
      7  * Foundation; either version 3 of the License, or (at your option) any later
      8  * version.
      9  *
     10  * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
     11  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
     13  * details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with PISM; if not, write to the Free Software
     17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18  */
     19 
     20 #include "IceModel.hh"
     21 
     22 #include "pism/util/pism_utilities.hh"
     23 #include "pism/util/Profiling.hh"
     24 
     25 namespace pism {
     26 
     27 //! Computes the maximum time-step we can take and still hit all `-save_times`.
     28 MaxTimestep IceModel::save_max_timestep(double my_t) {
     29 
     30   if ((not m_save_snapshots) or
     31       (not m_config->get_flag("time_stepping.hit_save_times"))) {
     32     return MaxTimestep("reporting (-save_times)");
     33   }
     34 
     35   return reporting_max_timestep(m_snapshot_times, my_t, "reporting (-save_times)");
     36 }
     37 
     38 //! Initializes the snapshot-saving mechanism.
     39 void IceModel::init_snapshots() {
     40   m_current_snapshot = 0;
     41 
     42   m_snapshots_filename = m_config->get_string("output.snapshot.file");
     43   bool filename_set = not m_snapshots_filename.empty();
     44 
     45   auto save_times = m_config->get_string("output.snapshot.times");
     46   bool times_set = not save_times.empty();
     47 
     48   bool split = m_config->get_flag("output.snapshot.split");
     49 
     50   m_snapshot_vars = output_variables(m_config->get_string("output.snapshot.size"));
     51 
     52   if (filename_set ^ times_set) {
     53     throw RuntimeError(PISM_ERROR_LOCATION,
     54                        "you need to set both output.snapshot.file and output.snapshot.times"
     55                        " to save snapshots.");
     56   }
     57 
     58   if (not filename_set and not times_set) {
     59     m_save_snapshots = false;
     60     return;
     61   }
     62 
     63   try {
     64     // parse
     65     std::vector<double> times = m_time->parse_times(save_times);
     66 
     67     // discard times before the beginning and after the end of the run
     68     m_snapshot_times.clear();
     69     for (const auto &t : times) {
     70       if (t >= m_time->start() and t <= m_time->end()) {
     71         m_snapshot_times.push_back(t);
     72       }
     73     }
     74   } catch (RuntimeError &e) {
     75     e.add_context("processing output.snapshot.times");
     76     throw;
     77   }
     78 
     79   if (m_snapshot_times.size() == 0) {
     80     throw RuntimeError(PISM_ERROR_LOCATION,
     81                        "output.snapshot.times was set, but all requested times"
     82                        " are outside of the modeled time interval");
     83   }
     84 
     85   m_save_snapshots = true;
     86   m_snapshots_file_is_ready = false;
     87   m_split_snapshots = false;
     88 
     89   if (split) {
     90     m_split_snapshots = true;
     91   } else if (not ends_with(m_snapshots_filename, ".nc")) {
     92     m_log->message(2,
     93                "PISM WARNING: snapshots file name does not have the '.nc' suffix!\n");
     94   }
     95 
     96   if (split) {
     97     m_log->message(2, "saving snapshots to '%s+year.nc'; ",
     98                m_snapshots_filename.c_str());
     99   } else {
    100     m_log->message(2, "saving snapshots to '%s'; ",
    101                m_snapshots_filename.c_str());
    102   }
    103 
    104   m_log->message(2, "times requested: %s\n", save_times.c_str());
    105 }
    106 
    107   //! Writes a snapshot of the model state (if necessary)
    108 void IceModel::write_snapshot() {
    109   double saving_after = -1.0e30; // initialize to avoid compiler warning; this
    110   // value is never used, because saving_after
    111   // is only used if save_now == true, and in
    112   // this case saving_after is guaranteed to be
    113   // initialized. See the code below.
    114   char filename[PETSC_MAX_PATH_LEN];
    115 
    116   // determine if the user set the -save_times and -save_file options
    117   if (not m_save_snapshots) {
    118     return;
    119   }
    120 
    121   // do we need to save *now*?
    122   if ((m_time->current() >= m_snapshot_times[m_current_snapshot]) and
    123       (m_current_snapshot < m_snapshot_times.size())) {
    124     saving_after = m_snapshot_times[m_current_snapshot];
    125 
    126     while ((m_current_snapshot < m_snapshot_times.size()) and
    127            (m_snapshot_times[m_current_snapshot] <= m_time->current())) {
    128       m_current_snapshot++;
    129     }
    130   } else {
    131     // we don't need to save now, so just return
    132     return;
    133   }
    134 
    135   // flush time-series buffers
    136   flush_timeseries();
    137 
    138   if (m_split_snapshots) {
    139     m_snapshots_file_is_ready = false;    // each snapshot is written to a separate file
    140     snprintf(filename, PETSC_MAX_PATH_LEN, "%s_%s.nc",
    141              m_snapshots_filename.c_str(), m_time->date(saving_after).c_str());
    142   } else {
    143     strncpy(filename, m_snapshots_filename.c_str(), PETSC_MAX_PATH_LEN);
    144   }
    145 
    146   m_log->message(2,
    147              "saving snapshot to %s at %s, for time-step goal %s\n",
    148              filename, m_time->date().c_str(),
    149              m_time->date(saving_after).c_str());
    150 
    151   const Profiling &profiling = m_ctx->profiling();
    152 
    153   profiling.begin("io.snapshots");
    154   IO_Mode mode = m_snapshots_file_is_ready ? PISM_READWRITE : PISM_READWRITE_MOVE;
    155   {
    156     File file(m_grid->com,
    157               filename,
    158               string_to_backend(m_config->get_string("output.format")),
    159               mode,
    160               m_ctx->pio_iosys_id());
    161 
    162     if (not m_snapshots_file_is_ready) {
    163       write_metadata(file, WRITE_MAPPING, PREPEND_HISTORY);
    164 
    165       m_snapshots_file_is_ready = true;
    166     }
    167 
    168     write_run_stats(file);
    169 
    170     save_variables(file, INCLUDE_MODEL_STATE, m_snapshot_vars, m_time->current());
    171   }
    172   profiling.end("io.snapshots");
    173 }
    174 
    175 } // end of namespace pism