tConfig.cc - pism - [fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
(HTM) git clone git://src.adamsgaard.dk/pism
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) LICENSE
---
tConfig.cc (7441B)
---
1 /* Copyright (C) 2014, 2015, 2016, 2017, 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 "Config.hh"
21 #include "pism/util/io/File.hh"
22 #include "pism_options.hh"
23 #include "error_handling.hh"
24 #include "io/io_helpers.hh"
25 #include "pism/util/Logger.hh"
26 #include "pism/util/pism_utilities.hh"
27 #include "pism/pism_config.hh" // pism::config_file
28
29 namespace pism {
30
31 NetCDFConfig::NetCDFConfig(MPI_Comm com, const std::string &name, units::System::Ptr system)
32 : Config(system),
33 m_com(com),
34 m_data(name, system) {
35 }
36
37 NetCDFConfig::~NetCDFConfig() {
38 }
39
40 bool NetCDFConfig::is_set_impl(const std::string &name) const {
41 return m_data.has_attribute(name);
42 }
43
44 // doubles
45
46 double NetCDFConfig::get_number_impl(const std::string &name) const {
47 const VariableMetadata::DoubleAttrs& doubles = m_data.get_all_doubles();
48 if (doubles.find(name) != doubles.end()) {
49 return m_data.get_number(name);
50 } else {
51 throw RuntimeError::formatted(PISM_ERROR_LOCATION,
52 "parameter '%s' is unset. (Parameters read from '%s'.)",
53 name.c_str(), m_config_filename.c_str());
54 }
55
56 return 0; // can't happen
57 }
58
59 std::vector<double> NetCDFConfig::get_numbers_impl(const std::string &name) const {
60 const VariableMetadata::DoubleAttrs& doubles = m_data.get_all_doubles();
61 if (doubles.find(name) != doubles.end()) {
62 return m_data.get_numbers(name);
63 } else {
64 throw RuntimeError::formatted(PISM_ERROR_LOCATION,
65 "parameter '%s' is unset. (Parameters read from '%s'.)",
66 name.c_str(), m_config_filename.c_str());
67 }
68
69 return {}; // can't happen
70 }
71
72 Config::Doubles NetCDFConfig::all_doubles_impl() const {
73 Doubles result;
74
75 for (auto d : m_data.get_all_doubles()) {
76 result[d.first] = d.second;
77 }
78 return result;
79 }
80
81
82 void NetCDFConfig::set_number_impl(const std::string &name, double value) {
83 m_data.set_number(name, value);
84 }
85
86 void NetCDFConfig::set_numbers_impl(const std::string &name,
87 const std::vector<double> &values) {
88 m_data.set_numbers(name, values);
89 }
90
91 // strings
92
93 std::string NetCDFConfig::get_string_impl(const std::string &name) const {
94 const VariableMetadata::StringAttrs& strings = m_data.get_all_strings();
95 if (strings.find(name) != strings.end()) {
96 return m_data.get_string(name);
97 } else {
98 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Parameter '%s' was not set. (Read from '%s'.)\n",
99 name.c_str(), m_config_filename.c_str());
100 }
101
102 return std::string(); // will never happen
103 }
104
105 Config::Strings NetCDFConfig::all_strings_impl() const {
106 VariableMetadata::StringAttrs strings = m_data.get_all_strings();
107 Strings result;
108
109 for (auto s : strings) {
110 std::string name = s.first;
111 std::string value = s.second;
112
113 auto k = strings.find(name + "_type");
114 if (k != strings.end() and k->second == "flag") {
115 // Flags are stored as strings. Skip them.
116 continue;
117 }
118
119 result[name] = value;
120 }
121 return result;
122 }
123
124 void NetCDFConfig::set_string_impl(const std::string &name, const std::string &value) {
125 m_data.set_string(name, value);
126 }
127
128 // flags
129
130 static bool string_is_false(const std::string &value) {
131 return value == "false" or value == "off" or value == "no";
132 }
133
134 static bool string_is_true(const std::string &value) {
135 return value == "true" or value == "on" or value == "yes";
136 }
137
138 bool NetCDFConfig::get_flag_impl(const std::string &name) const {
139 const VariableMetadata::StringAttrs& strings = m_data.get_all_strings();
140 auto j = strings.find(name);
141 if (j != strings.end()) {
142
143 const std::string &value = j->second;
144
145 if (string_is_false(value)) {
146 return false;
147 }
148
149 if (string_is_true(value)) {
150 return true;
151 }
152
153 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Parameter '%s' (%s) cannot be interpreted as a flag.\n"
154 "Please make sure that it is set to one of 'true', 'yes', 'on', 'false', 'no', 'off'.",
155 name.c_str(), value.c_str());
156 }
157
158 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Parameter '%s' was not set. (Read from '%s'.)",
159 name.c_str(), m_config_filename.c_str());
160
161 return true; // will never happen
162 }
163
164 Config::Flags NetCDFConfig::all_flags_impl() const {
165 Flags result;
166
167 for (auto b : m_data.get_all_strings()) {
168 std::string name = b.first;
169 std::string value = b.second;
170
171 if (string_is_true(value)) {
172 result[name] = true;
173 } else if (string_is_false(value)) {
174 result[name] = false;
175 }
176 }
177 return result;
178 }
179
180 //! Set a value of a flag flag.
181 void NetCDFConfig::set_flag_impl(const std::string &name, bool value) {
182 if (value) {
183 m_data.set_string(name, "true");
184 } else {
185 m_data.set_string(name, "false");
186 }
187 }
188
189 // file I/O
190
191 //! Read flag flags and double parameters from a NetCDF file.
192 /*!
193 Erases all the present parameters before reading.
194 */
195 void NetCDFConfig::read_impl(const File &nc) {
196
197 io::read_attributes(nc, m_data.get_name(), m_data);
198
199 m_config_filename = nc.filename();
200 }
201
202 //! Write a config variable to a file (with all its attributes).
203 void NetCDFConfig::write_impl(const File &nc) const {
204
205 bool variable_exists = nc.find_variable(m_data.get_name());
206
207 if (not variable_exists) {
208 nc.define_variable(m_data.get_name(),
209 PISM_BYTE, std::vector<std::string>());
210
211 io::write_attributes(nc, m_data, PISM_DOUBLE);
212 } else {
213 io::write_attributes(nc, m_data, PISM_DOUBLE);
214 }
215 }
216
217
218 //! Config that respects command-line options and stores data in a NetCDF variable.
219 DefaultConfig::DefaultConfig(MPI_Comm com,
220 const std::string &variable_name,
221 const std::string &option,
222 units::System::Ptr system)
223 : NetCDFConfig(com, variable_name, system),
224 m_option(option) {
225 // empty
226 }
227
228 DefaultConfig::~DefaultConfig() {
229 // empty
230 }
231
232 void DefaultConfig::init(const Logger &log, bool use_default_path) {
233 options::String file(m_option,
234 "Name of the file to read " + m_data.get_name() + " from",
235 pism::config_file);
236 if (use_default_path or file.is_set()) {
237 this->read(m_com, file);
238 log.message(2, "Reading configuration parameters (%s) from file '%s'.\n",
239 m_data.get_name().c_str(), file->c_str());
240 }
241 }
242
243 void DefaultConfig::init_with_default(const Logger &log) {
244 this->init(log, true);
245 }
246
247 void DefaultConfig::init(const Logger &log) {
248 this->init(log, false);
249 }
250
251 } // end of namespace pism