PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
SynchronousOutputWriter.cc
Go to the documentation of this file.
1/* Copyright (C) 2025, 2026 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 "pism/util/io/SynchronousOutputWriter.hh"
21#include "pism/util/Config.hh"
22#include "pism/util/VariableMetadata.hh"
23#include "pism/util/io/File.hh"
24#include "pism/util/io/IO_Flags.hh"
25#include "pism/util/error_handling.hh"
26#include "pism/util/GridInfo.hh"
27#include <cstddef>
28
29namespace pism {
30
31const File &SynchronousOutputWriter::file(const std::string &file_name) {
32 if (m_files[file_name] == nullptr) {
33 auto file = std::make_shared<File>(comm(), file_name, m_backend, io::PISM_READWRITE_MOVE);
34
36
37 m_files[file_name] = file;
38 }
39
40 return *m_files[file_name];
41}
42
44 const std::set<VariableMetadata> & /*array_variables*/) {
45 // empty
46}
47
49 : OutputWriter(comm, config) {
50 m_compression_level = static_cast<int>(config.get_number("output.compression_level"));
51 m_backend = string_to_backend(config.get_string("output.format"));
52 set_is_async(false);
53}
54
55void SynchronousOutputWriter::define_variable_impl(const std::string &file_name,
56 const std::string &variable_name,
57 const std::vector<std::string> &dims,
58 io::Type type,
59 const VariableAttributes &attributes) {
60 const auto &output_file = file(file_name);
61
62 if (output_file.variable_exists(variable_name)) {
63 return;
64 }
65
66 output_file.define_variable(variable_name, type, dims);
67
68 write_attributes(file_name, variable_name, attributes.strings, attributes.numbers, type);
69}
70
71void SynchronousOutputWriter::append_time_impl(const std::string &file_name, double time_seconds) {
72 write_array(file_name, time_name(), { time_dimension_length(file_name) }, { 1 },
73 { time_seconds });
74}
75
76void SynchronousOutputWriter::append_history_impl(const std::string &file_name,
77 const std::string &text) {
78 const auto &output_file = file(file_name);
79
80 auto old_history = output_file.read_text_attribute("PISM_GLOBAL", "history");
81
82 output_file.write_attribute("PISM_GLOBAL", "history", old_history + text);
83}
84
85void SynchronousOutputWriter::append_impl(const std::string &file_name) {
86 if (m_files[file_name] == nullptr) {
87 m_files[file_name] =
88 std::make_shared<File>(comm(), file_name, io::PISM_GUESS, io::PISM_READWRITE);
89 }
90}
91
92void SynchronousOutputWriter::sync_impl(const std::string &file_name) {
93 m_files[file_name]->sync();
94}
95
96void SynchronousOutputWriter::close_impl(const std::string &file_name) {
97 if (m_files[file_name] != nullptr) {
98 m_files[file_name]->close();
99 m_files[file_name].reset();
100 }
101}
102
103void SynchronousOutputWriter::define_dimension_impl(const std::string &file_name,
104 const std::string &name, unsigned int length) {
105 const auto &output_file = file(file_name);
106
107 if (output_file.dimension_exists(name)) {
108 return;
109 }
110
111 output_file.define_dimension(name, length);
112}
113
115 const std::string &file_name, const std::map<std::string, std::string> &strings,
116 const std::map<std::string, std::vector<double> > &numbers) {
117 write_attributes(file_name, "PISM_GLOBAL", strings, numbers, io::PISM_DOUBLE);
118}
119
121 const std::string &file_name, const std::string &var_name,
122 const std::map<std::string, std::string> &strings,
123 const std::map<std::string, std::vector<double> > &numbers, io::Type output_type) {
124 const auto &output_file = file(file_name);
125
126 // Write text attributes:
127 for (const auto &s : strings) {
128 const auto &name = s.first;
129 const auto &value = s.second;
130
131 if (value.empty()) {
132 continue;
133 }
134
135 output_file.write_attribute(var_name, name, value);
136 }
137
138 // Write double attributes:
139 for (const auto &d : numbers) {
140 const auto &name = d.first;
141 const auto &values = d.second;
142
143 if (values.empty()) {
144 continue;
145 }
146
147 if (output_type == io::PISM_CHAR) {
148 // save attributes of a character variable as "double"
149 output_type = io::PISM_DOUBLE;
150 }
151
152 output_file.write_attribute(var_name, name, output_type, values);
153 }
154}
155
156unsigned int SynchronousOutputWriter::time_dimension_length_impl(const std::string &file_name) {
157 const auto &output_file = file(file_name);
158 return output_file.dimension_length(time_name());
159}
160
161double SynchronousOutputWriter::last_time_value_impl(const std::string &file_name) {
162 const auto &output_file = file(file_name);
163
164 auto t_length = output_file.dimension_length(time_name());
165
166 if (t_length > 0) {
167 double time = 0;
168 output_file.read_variable("time", { t_length - 1 }, { 1 }, &time);
169 return time;
170 }
172 "time dimension in '%s' is absent or has length zero",
173 file_name.c_str());
174}
175
176void SynchronousOutputWriter::write_array_impl(const std::string &file_name,
177 const std::string &variable_name,
178 const std::vector<unsigned int> &start,
179 const std::vector<unsigned int> &count,
180 const double *data) {
181 const auto &output_file = file(file_name);
182
183 output_file.write_variable(variable_name, start, count, data);
184}
185
186void SynchronousOutputWriter::write_text_impl(const std::string &file_name,
187 const std::string &variable_name,
188 const std::vector<unsigned int> &start,
189 const std::vector<unsigned int> &count,
190 const std::string &input) {
191 const auto &output_file = file(file_name);
192
193 output_file.write_text_variable(variable_name, start, count, input);
194}
195
197 const std::string &variable_name,
198 const double *data) {
199
200 const auto &output_file = file(file_name);
201
202 const auto &metadata = variable_info(variable_name);
203
204 if (metadata.grid_info() == nullptr) {
205 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "variable '%s' has no grid info",
206 variable_name.c_str());
207 }
208
209 const auto &grid = *metadata.grid_info();
210
211 unsigned int n_levels = std::max(metadata.levels().size(), (std::size_t)1);
212
213 std::vector<unsigned int> start = { grid.ys, grid.xs, 0 };
214 std::vector<unsigned int> count = { grid.ym, grid.xm, n_levels };
215
216 if (metadata.get_time_dependent()) {
217 auto t_length = time_dimension_length(file_name);
218 auto t_start = t_length > 0 ? t_length - 1 : 0;
219
220 start.insert(start.cbegin(), t_start);
221 count.insert(count.cbegin(), 1);
222 }
223
224 if (not experiment_id().empty()) {
225 start.insert(start.cbegin(), 0);
226 count.insert(count.cbegin(), 1);
227 }
228
229 output_file.write_variable(variable_name, start, count, data);
230}
231
232} // namespace pism
double get_number(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
Definition Config.cc:188
std::string get_string(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
Definition Config.cc:322
A class for storing and accessing PISM configuration flags and parameters.
Definition Config.hh:56
void set_compression_level(int level) const
Definition File.cc:189
High-level PISM I/O class.
Definition File.hh:57
unsigned int time_dimension_length(const std::string &file_name)
void set_is_async(bool flag)
const std::string & time_name() const
MPI_Comm comm() const
const std::string & experiment_id() const
const VariableMetadata & variable_info(const std::string &variable_name) const
void write_array(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::vector< double > &input)
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
void append_history_impl(const std::string &file_name, const std::string &text)
const File & file(const std::string &file_name)
void define_dimension_impl(const std::string &file_name, const std::string &name, unsigned int length)
void write_text_impl(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::string &input)
SynchronousOutputWriter(MPI_Comm comm, const Config &config)
void write_distributed_array_impl(const std::string &file_name, const std::string &variable_name, const double *data)
void append_impl(const std::string &file_name)
void write_attributes(const std::string &file_name, const std::string &var_name, const std::map< std::string, std::string > &strings, const std::map< std::string, std::vector< double > > &numbers, io::Type output_type)
std::map< std::string, std::shared_ptr< File > > m_files
void define_variable_impl(const std::string &file_name, const std::string &variable_name, const std::vector< std::string > &dims, io::Type type, const VariableAttributes &attributes)
unsigned int time_dimension_length_impl(const std::string &file_name)
void append_time_impl(const std::string &file_name, double time_seconds)
void set_global_attributes_impl(const std::string &file_name, const std::map< std::string, std::string > &strings, const std::map< std::string, std::vector< double > > &numbers)
void write_array_impl(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const double *data)
void close_impl(const std::string &file_name)
void sync_impl(const std::string &file_name)
void initialize_impl(const std::set< VariableMetadata > &array_variables)
double last_time_value_impl(const std::string &file_name)
std::map< std::string, std::string > strings
string and boolean attributes
std::map< std::string, std::vector< double > > numbers
scalar and array attributes
#define PISM_ERROR_LOCATION
@ PISM_GUESS
Definition IO_Flags.hh:57
@ PISM_READWRITE_MOVE
create a file for writing, move foo.nc to foo.nc~ if present
Definition IO_Flags.hh:75
@ PISM_READWRITE
open an existing file for reading and writing
Definition IO_Flags.hh:71
@ PISM_DOUBLE
Definition IO_Flags.hh:53
@ PISM_CHAR
Definition IO_Flags.hh:49
io::Backend string_to_backend(const std::string &backend)
Definition File.cc:56
int count
Definition test_cube.c:16