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 = {
81 {"VTK", OutputType::vtk}, {"XDMF", OutputType::xdmf}};
82 auto type = outputType_to_enum.at(output_type);
83
84 return type;
85 }
86 catch (std::out_of_range&)
87 {
89 "No supported file type provided. Read `{:s}' from <output><type> \
90 in prj File. Supported: VTK, XDMF.",
91 output_type);
92 }
94 }(config.getConfigParameter<std::string>("type"));
95
96 output_config.prefix =
98 config.getConfigParameter<std::string>("prefix", "{:meshname}");
99
100 output_config.suffix =
102 config.getConfigParameter<std::string>("suffix",
103 "_ts_{:timestep}_t_{:time}");
104
105 output_config.compress_output =
107 config.getConfigParameter("compress_output", true);
108
109 auto const hdf =
111 config.getConfigSubtreeOptional("hdf");
112
113 output_config.number_of_files = [&hdf]() -> unsigned int
114 {
115 if (hdf)
116 {
118 return hdf->getConfigParameter<unsigned int>("number_of_files");
119 }
120 return 1;
121 }();
122 output_config.chunk_size_bytes = [&hdf]() -> unsigned int
123 {
124 if (hdf)
125 {
127 return hdf->getConfigParameter<unsigned int>("chunk_size_bytes");
128 }
129 return 1048576; // default chunk size in bytes according to
130 // https://www.hdfgroup.org/2022/10/improve-hdf5-performance-using-caching/
131 }();
132
133 output_config.data_mode =
135 config.getConfigParameter<std::string>("data_mode", "Appended");
136
137 //
138 // Construction of output times
139 //
140
141 output_config.fixed_output_times =
143 config.getConfigParameter<std::vector<double>>("fixed_output_times",
144 {});
145 if (output_config.fixed_output_times.empty())
146 {
148 std::string filename = config.getConfigParameter<std::string>(
149 "fixed_output_times_from_file", "no_file");
150
151 if (filename != "no_file")
152 {
153 output_config.fixed_output_times =
155 filename, config.projectDirectory().string());
156 }
157 }
158 // Remove possible duplicated elements and sort.
160
161 auto& repeats_each_steps = output_config.repeats_each_steps;
162
164 if (auto const timesteps = config.getConfigSubtreeOptional("timesteps"))
165 {
167 for (auto pair : timesteps->getConfigSubtreeList("pair"))
168 {
170 auto repeat = pair.getConfigParameter<unsigned>("repeat");
172 auto each_steps = pair.getConfigParameter<unsigned>("each_steps");
173
174 assert(repeat != 0 && each_steps != 0);
175 repeats_each_steps.emplace_back(repeat, each_steps);
176 }
177
178 if (repeats_each_steps.empty())
179 {
180 OGS_FATAL(
181 "You have not given any pair (<repeat/>, <each_steps/>) that "
182 "defines at which timesteps output shall be written. "
183 "Aborting.");
184 }
185 }
186 // In case nothing was specified, i.e. no explicit time steps or fixed
187 // output times, every time step will be written.
188 if (output_config.fixed_output_times.empty() &&
189 output_config.repeats_each_steps.empty())
190 {
191 repeats_each_steps.emplace_back(1, 1);
192 }
193
195 auto const out_vars = config.getConfigSubtree("variables");
196
197 auto& output_variables = output_config.output_variables;
198 for (auto out_var :
200 out_vars.getConfigParameterList<std::string>("variable"))
201 {
202 if (output_variables.find(out_var) != output_variables.cend())
203 {
204 OGS_FATAL("output variable `{:s}' specified more than once.",
205 out_var);
206 }
207
208 DBUG("adding output variable `{:s}'", out_var);
209 output_variables.insert(out_var);
210 }
211
212 output_config.output_extrapolation_residuals =
214 config.getConfigParameter<bool>("output_extrapolation_residuals",
215 false);
216
217 auto& mesh_names_for_output = output_config.mesh_names_for_output;
219 if (auto const meshes_config = config.getConfigSubtreeOptional("meshes"))
220 {
221 if (output_config.prefix.find("{:meshname}") == std::string::npos)
222 {
223 OGS_FATAL(
224 "There are multiple meshes defined in the output section of "
225 "the project file, but the prefix doesn't contain "
226 "'{{:meshname}}'. Thus the names for the files, the simulation "
227 "results should be written to, would not be distinguishable "
228 "for different meshes.");
229 }
231 for (auto mesh_config : meshes_config->getConfigParameterList("mesh"))
232 {
233 mesh_names_for_output.push_back(
234 parseOutputMeshConfig(mesh_config, meshes));
235 INFO("Configure mesh '{:s}' for output.",
236 mesh_names_for_output.back());
237 }
238 }
239
240 if (auto const geometrical_sets_config =
242 config.getConfigSubtreeOptional("geometrical_sets"))
243 {
244 for (
245 auto geometrical_set_config :
247 geometrical_sets_config->getConfigSubtreeList("geometrical_set"))
248 {
249 auto const geometrical_set_name =
251 geometrical_set_config.getConfigParameter<std::string>("name",
252 "");
253 auto const geometry_name =
255 geometrical_set_config.getConfigParameter<std::string>(
256 "geometry");
257 mesh_names_for_output.push_back(geometrical_set_name + "_" +
258 geometry_name);
259 }
260 }
261
262 output_config.output_iteration_results =
264 config.getConfigParameter<bool>("output_iteration_results", false);
265
266 return output_config;
267}
268} // 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:19
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:94
void makeVectorUnique(std::vector< T > &v)
Definition Algorithm.h:173
std::vector< double > readDoublesFromBinaryFile(const std::string &filename, const std::string &project_directory)
std::vector< int > splitMaterialIdString(std::string const &material_id_string)
Mesh & findMeshByName(std::vector< std::unique_ptr< Mesh > > const &meshes, std::string_view const name)
Definition Mesh.cpp:354
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::vector< std::string > mesh_names_for_output