OGS
CreateOutputConfig.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <spdlog/fmt/ranges.h>
7
8#include <map>
9
10#include "BaseLib/Algorithm.h"
11#include "BaseLib/ConfigTree.h"
12#include "BaseLib/FileTools.h" // required for reading output_times from binary file
13#include "MaterialLib/Utils/MediaCreation.h" // required for splitMaterialIDString
14#include "MeshLib/Mesh.h"
17#ifdef USE_PETSC
19#endif // USE_PETSC
20
21std::string createMeshOutputName(std::vector<int> const& material_ids,
22 std::string const& mesh_name)
23{
24 if (material_ids.empty())
25 {
26 return mesh_name;
27 }
28 return mesh_name + "_" + fmt::format("{}", fmt::join(material_ids, "_"));
29}
30
32 BaseLib::ConfigTree const& output_mesh_config,
33 std::vector<std::unique_ptr<MeshLib::Mesh>>& meshes)
34{
35 auto const mesh_name = output_mesh_config.getValue<std::string>();
36 auto const& mesh = MeshLib::findMeshByName(meshes, mesh_name);
37
38 auto material_id_string =
40 output_mesh_config.getConfigAttributeOptional<std::string>(
41 "material_ids");
42
43 if (!material_id_string)
44 {
45 return mesh_name;
46 }
47
48 auto const material_ids_for_output =
49 MaterialLib::splitMaterialIdString(*material_id_string);
50#ifdef USE_PETSC
51 // this mesh isn't yet a NodePartitionedMesh
52 auto subdomain_mesh = MeshLib::createMaterialIDsBasedSubMesh(
53 mesh, material_ids_for_output,
54 createMeshOutputName(material_ids_for_output, mesh_name));
55 auto const* bulk_mesh =
56 dynamic_cast<MeshLib::NodePartitionedMesh const*>(&mesh);
58 bulk_mesh, subdomain_mesh.get()));
59#else
61 mesh, material_ids_for_output,
62 createMeshOutputName(material_ids_for_output, mesh_name)));
63#endif
64
65 return meshes.back()->getName();
66}
67
68namespace ProcessLib
69{
71 const BaseLib::ConfigTree& config,
72 std::vector<std::unique_ptr<MeshLib::Mesh>>& meshes)
73{
74 OutputConfig output_config;
75
76 output_config.output_type = [](auto output_type)
77 {
78 try
79 {
80 const std::map<std::string, OutputType> outputType_to_enum = {
82 {"VTK", OutputType::vtk},
84 {"XDMF", OutputType::xdmf}};
85 auto type = outputType_to_enum.at(output_type);
86
87 return type;
88 }
89 catch (std::out_of_range&)
90 {
92 "No supported file type provided. Read `{:s}' from <output><type> \
93 in prj File. Supported: VTK, XDMF.",
94 output_type);
95 }
97 }(config.getConfigParameter<std::string>("type"));
98
99 output_config.prefix =
101 config.getConfigParameter<std::string>("prefix", "{:meshname}");
102
103 output_config.suffix =
105 config.getConfigParameter<std::string>("suffix",
106 "_ts_{:timestep}_t_{:time}");
107
108 output_config.compress_output =
110 config.getConfigParameter("compress_output", true);
111
112 auto const hdf =
114 config.getConfigSubtreeOptional("hdf");
115
116 output_config.number_of_files = [&hdf]() -> unsigned int
117 {
118 if (hdf)
119 {
121 return hdf->getConfigParameter<unsigned int>("number_of_files");
122 }
123 return 1;
124 }();
125 output_config.chunk_size_bytes = [&hdf]() -> unsigned int
126 {
127 if (hdf)
128 {
130 return hdf->getConfigParameter<unsigned int>("chunk_size_bytes");
131 }
132 return 1048576; // default chunk size in bytes according to
133 // https://www.hdfgroup.org/2022/10/improve-hdf5-performance-using-caching/
134 }();
135 output_config.store_static_data_separately = [&hdf]() -> bool
136 {
137 if (hdf)
138 {
139 return hdf
141 ->getConfigParameterOptional<bool>(
142 "store_static_data_separately")
143 .value_or(false);
144 }
145 return false; // default store_static_data_separately == false
146 }();
147
148 output_config.data_mode =
150 config.getConfigParameter<std::string>("data_mode", "Appended");
151
152 //
153 // Construction of output times
154 //
155
156 output_config.fixed_output_times =
158 config.getConfigParameter<std::vector<double>>("fixed_output_times",
159 {});
160 if (output_config.fixed_output_times.empty())
161 {
163 std::string filename = config.getConfigParameter<std::string>(
164 "fixed_output_times_from_file", "no_file");
165
166 if (filename != "no_file")
167 {
168 output_config.fixed_output_times =
170 filename, config.projectDirectory().string());
171 }
172 }
173 // Remove possible duplicated elements and sort.
175
176 auto& repeats_each_steps = output_config.repeats_each_steps;
177
179 if (auto const timesteps = config.getConfigSubtreeOptional("timesteps"))
180 {
182 for (auto pair : timesteps->getConfigSubtreeList("pair"))
183 {
185 auto repeat = pair.getConfigParameter<unsigned>("repeat");
187 auto each_steps = pair.getConfigParameter<unsigned>("each_steps");
188
189 assert(repeat != 0 && each_steps != 0);
190 repeats_each_steps.emplace_back(repeat, each_steps);
191 }
192
193 if (repeats_each_steps.empty())
194 {
195 OGS_FATAL(
196 "You have not given any pair (<repeat/>, <each_steps/>) that "
197 "defines at which timesteps output shall be written. "
198 "Aborting.");
199 }
200 }
201 // In case nothing was specified, i.e. no explicit time steps or fixed
202 // output times, every time step will be written.
203 if (output_config.fixed_output_times.empty() &&
204 output_config.repeats_each_steps.empty())
205 {
206 repeats_each_steps.emplace_back(1, 1);
207 }
208
210 auto const out_vars = config.getConfigSubtree("variables");
211
212 auto& output_variables = output_config.output_variables;
213 for (auto out_var :
215 out_vars.getConfigParameterList<std::string>("variable"))
216 {
217 if (output_variables.find(out_var) != output_variables.cend())
218 {
219 OGS_FATAL("output variable `{:s}' specified more than once.",
220 out_var);
221 }
222
223 DBUG("adding output variable `{:s}'", out_var);
224 output_variables.insert(out_var);
225 }
226
227 // XDMF specific settings
228 auto const xdmf_config =
230 config.getConfigSubtreeOptional("xdmf_config");
231
232 // Optional list of output variables that are written once instead of per
233 // time step, i.e. as static attributes.
234 if (auto const static_vars =
235 xdmf_config
236 ?
237 xdmf_config->getConfigSubtreeOptional("static_variables")
238 : std::optional<BaseLib::ConfigTree>{})
239 {
240 auto& static_output_variables = output_config.static_output_variables;
241 for (
242 auto const& var :
244 static_vars->getConfigParameterList<std::string>("variable"))
245 {
246 // static variable has to be in output_variables
247 if (!output_variables.empty() &&
248 output_variables.find(var) == output_variables.cend())
249 {
250 OGS_FATAL(
251 "static output `{:s}' is not in output variables list.",
252 var);
253 }
254 if (!static_output_variables.insert(var).second)
255 {
256 OGS_FATAL(
257 "static output variable `{:s}' specified more than once.",
258 var);
259 }
260 DBUG("adding static output variable `{:s}'", var);
261 }
262 }
263
264 output_config.output_extrapolation_residuals =
266 config.getConfigParameter<bool>("output_extrapolation_residuals",
267 false);
268
269 auto& mesh_names_for_output = output_config.mesh_names_for_output;
271 if (auto const meshes_config = config.getConfigSubtreeOptional("meshes"))
272 {
273 if (output_config.prefix.find("{:meshname}") == std::string::npos)
274 {
275 OGS_FATAL(
276 "There are multiple meshes defined in the output section of "
277 "the project file, but the prefix doesn't contain "
278 "'{{:meshname}}'. Thus the names for the files, the simulation "
279 "results should be written to, would not be distinguishable "
280 "for different meshes.");
281 }
283 for (auto mesh_config : meshes_config->getConfigParameterList("mesh"))
284 {
285 mesh_names_for_output.push_back(
286 parseOutputMeshConfig(mesh_config, meshes));
287 INFO("Configure mesh '{:s}' for output.",
288 mesh_names_for_output.back());
289 }
290 }
291
292 if (auto const geometrical_sets_config =
294 config.getConfigSubtreeOptional("geometrical_sets"))
295 {
296 for (
297 auto geometrical_set_config :
299 geometrical_sets_config->getConfigSubtreeList("geometrical_set"))
300 {
301 auto const geometrical_set_name =
303 geometrical_set_config.getConfigParameter<std::string>("name",
304 "");
305 auto const geometry_name =
307 geometrical_set_config.getConfigParameter<std::string>(
308 "geometry");
309 mesh_names_for_output.push_back(geometrical_set_name + "_" +
310 geometry_name);
311 }
312 }
313
314 output_config.output_iteration_results =
316 config.getConfigParameter<bool>("output_iteration_results", false);
317
318 return output_config;
319}
320} // namespace ProcessLib
std::string createMeshOutputName(std::vector< int > const &material_ids, std::string const &mesh_name)
std::string parseOutputMeshConfig(BaseLib::ConfigTree const &output_mesh_config, std::vector< std::unique_ptr< MeshLib::Mesh > > &meshes)
#define OGS_FATAL(...)
Definition Error.h:10
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
std::filesystem::path projectDirectory() const
T getConfigParameter(std::string const &param) const
ConfigTree getConfigSubtree(std::string const &root) const
std::optional< T > getConfigAttributeOptional(std::string const &attr) const
const std::string getName() const
Get name of the mesh.
Definition Mesh.h:95
void makeVectorUnique(std::vector< T > &v)
Definition Algorithm.h:198
std::vector< double > readDoublesFromBinaryFile(const std::string &filename, const std::string &project_directory)
std::vector< int > splitMaterialIdString(std::string const &material_id_string, char const separator)
Mesh & findMeshByName(std::vector< std::unique_ptr< Mesh > > const &meshes, std::string_view const name)
Definition Mesh.cpp:356
std::unique_ptr< MeshLib::Mesh > createMaterialIDsBasedSubMesh(MeshLib::Mesh const &mesh, std::vector< int > const &material_ids, std::string const &name_for_created_mesh)
std::unique_ptr< NodePartitionedMesh > transformMeshToNodePartitionedMesh(NodePartitionedMesh const *const bulk_mesh, Mesh const *const subdomain_mesh)
OutputConfig createOutputConfig(const BaseLib::ConfigTree &config, std::vector< std::unique_ptr< MeshLib::Mesh > > &meshes)
std::vector< PairRepeatEachSteps > repeats_each_steps
std::vector< double > fixed_output_times
unsigned int number_of_files
unsigned int chunk_size_bytes
std::set< std::string > output_variables
std::set< std::string > static_output_variables
std::vector< std::string > mesh_names_for_output