URI:
       toutput_save.cc - pism - [fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
  HTML git clone git://src.adamsgaard.dk/pism
   DIR Log
   DIR Files
   DIR Refs
   DIR LICENSE
       ---
       toutput_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