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