OGS
PVD2XDMF.cpp File Reference

Detailed Description

Definition in file PVD2XDMF.cpp.

#include <tclap/CmdLine.h>
#include <mpi.h>
#include <array>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <string>
#include "BaseLib/FileTools.h"
#include "BaseLib/Logging.h"
#include "BaseLib/MemWatch.h"
#include "BaseLib/RunTime.h"
#include "BaseLib/StringTools.h"
#include "InfoLib/GitInfo.h"
#include "MeshLib/Elements/Element.h"
#include "MeshLib/IO/XDMF/XdmfHdfWriter.h"
#include "MeshLib/IO/readMeshFromFile.h"
#include "MeshLib/Mesh.h"
Include dependency graph for PVD2XDMF.cpp:

Go to the source code of this file.

Functions

std::vector< std::pair< double, std::string > > readPvd (std::string const &pvd_filename)
 
template<typename T >
bool copyPropertyVector (MeshLib::Properties const &properties, MeshLib::PropertyVectorBase *destination_pv)
 
void testIfMeshesAreEqual (MeshLib::Mesh const &mesh, MeshLib::Mesh const &main_mesh, std::string error_message)
 
int main (int argc, char *argv[])
 

Function Documentation

◆ copyPropertyVector()

template<typename T >
bool copyPropertyVector ( MeshLib::Properties const & properties,
MeshLib::PropertyVectorBase * destination_pv )

Definition at line 59 of file PVD2XDMF.cpp.

61{
62 if (!dynamic_cast<MeshLib::PropertyVector<T>*>(destination_pv))
63 {
64 return false;
65 }
66
67 auto const* pv = properties.getPropertyVector<T>(
68 destination_pv->getPropertyName(), destination_pv->getMeshItemType(),
69 destination_pv->getNumberOfGlobalComponents());
70
71 assert(pv != nullptr);
72
73 std::copy(
74 std::begin(*pv), std::end(*pv),
75 std::begin(dynamic_cast<MeshLib::PropertyVector<T>&>(*destination_pv)));
76
77 return true;
78}
MeshItemType getMeshItemType() const
int getNumberOfGlobalComponents() const
std::string const & getPropertyName() const

References MeshLib::PropertyVectorBase::getMeshItemType(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::PropertyVectorBase::getPropertyName(), and MeshLib::Properties::getPropertyVector().

Referenced by main().

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 109 of file PVD2XDMF.cpp.

110{
111 TCLAP::CmdLine cmd(
112 "Converts a time series from PVD to XDMF format.\n\n"
113 "OpenGeoSys-6 software, version " +
115 ".\n"
116 "Copyright (c) 2012-2024, OpenGeoSys Community "
117 "(http://www.opengeosys.org)",
119
120 TCLAP::ValueArg<std::string> log_level_arg(
121 "l", "log-level",
122 "the verbosity of logging messages: none, error, warn, info, "
123 "debug, "
124 "all",
125 false,
126#ifdef NDEBUG
127 "info",
128#else
129 "all",
130#endif
131 "LOG_LEVEL");
132 cmd.add(log_level_arg);
133
134 TCLAP::UnlabeledValueArg<std::string> pvd_file_arg("pvd-file", "pvd file",
135 true, "", "file");
136 cmd.add(pvd_file_arg);
137
138 TCLAP::ValueArg<std::string> outdir_arg("o", "output-directory",
139 "the output directory to write to",
140 false, ".", "PATH");
141 cmd.add(outdir_arg);
142
143 cmd.parse(argc, argv);
144#ifdef USE_PETSC
145 MPI_Init(&argc, &argv);
146#endif
147 BaseLib::setConsoleLogLevel(log_level_arg.getValue());
148
149 auto const pvd_file_dir = BaseLib::extractPath(pvd_file_arg.getValue());
150
151 auto const timeseries = readPvd(pvd_file_arg.getValue());
152
153 if (timeseries.empty())
154 {
155 OGS_FATAL("Empty time series.");
156 }
157
158 // Initialized from the first timeseries entry and data is updated for each
159 // subsequent time step.
160 std::unique_ptr<MeshLib::Mesh> main_mesh;
161
162 std::filesystem::path const output_file{
163 BaseLib::extractBaseNameWithoutExtension(pvd_file_arg.getValue()) +
164 ".xdmf"};
165 std::filesystem::path output_file_path{outdir_arg.getValue()};
166 if (outdir_arg.getValue() != "")
167 {
168 output_file_path =
169 BaseLib::joinPaths(outdir_arg.getValue(), output_file.string());
170 }
171 std::set<std::string> variable_output_names;
172 std::unique_ptr<MeshLib::IO::XdmfHdfWriter> mesh_xdmf_hdf_writer;
173 // read first file in the time series; it is determining variables.
174 {
175 auto [time, filename] = timeseries[0];
176 DBUG("{} - {}", time, filename);
177
178 main_mesh.reset(MeshLib::IO::readMeshFromFile(
179 BaseLib::joinPaths(pvd_file_dir, filename)));
180 if (main_mesh == nullptr)
181 {
182 OGS_FATAL("Could not read mesh from '{:s}'.",
183 BaseLib::joinPaths(pvd_file_dir, filename));
184 }
185
186 for (auto const& p : main_mesh->getProperties())
187 {
188 variable_output_names.insert(std::string(p.first));
189 }
190 mesh_xdmf_hdf_writer = std::make_unique<MeshLib::IO::XdmfHdfWriter>(
191 std::vector{std::cref(*main_mesh)}, output_file_path,
192 0 /*timestep*/, time, variable_output_names,
193 true /*output_file.compression*/, 1 /*output_file.n_files*/,
194 1048576 /*chunk_size_bytes*/);
195 }
196
197 for (std::size_t timestep = 1; timestep < timeseries.size(); ++timestep)
198 {
199 auto [time, filename] = timeseries[timestep];
200 DBUG("{} - {}", time, filename);
201
202 std::unique_ptr<MeshLib::Mesh> mesh{MeshLib::IO::readMeshFromFile(
203 BaseLib::joinPaths(pvd_file_dir, filename))};
204 if (mesh == nullptr)
205 {
206 OGS_FATAL("Could not read mesh from '{:s}'.",
207 BaseLib::joinPaths(pvd_file_dir, filename));
208 }
209
211 *mesh, *main_mesh,
212 fmt::format("Error in comparison of mesh from file '{:s}' to the "
213 "main mesh:\n",
214 BaseLib::joinPaths(pvd_file_dir, filename)));
215
216 // We have to copy the values because the xdmf writer remembers the data
217 // pointers. Therefore replacing the properties will not work.
218 for (auto& [name, pv] : main_mesh->getProperties())
219 {
220 if (copyPropertyVector<double>(mesh->getProperties(), pv) ||
221 copyPropertyVector<float>(mesh->getProperties(), pv) ||
222 copyPropertyVector<int>(mesh->getProperties(), pv) ||
223 copyPropertyVector<long>(mesh->getProperties(), pv) ||
224 copyPropertyVector<unsigned>(mesh->getProperties(), pv) ||
225 copyPropertyVector<unsigned long>(mesh->getProperties(), pv) ||
226 copyPropertyVector<std::size_t>(mesh->getProperties(), pv) ||
227 copyPropertyVector<char>(mesh->getProperties(), pv) ||
228 copyPropertyVector<unsigned char>(mesh->getProperties(), pv))
229 {
230 continue;
231 }
232 OGS_FATAL(
233 "Could not copy property vector '{:s}' from '{:s}' mesh to the "
234 "main_mesh.",
235 name, BaseLib::joinPaths(pvd_file_dir, filename));
236 }
237
238 mesh_xdmf_hdf_writer->writeStep(time);
239 }
240#ifdef USE_PETSC
241 MPI_Finalize();
242#endif
243 return EXIT_SUCCESS;
244}
#define OGS_FATAL(...)
Definition Error.h:26
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:30
void testIfMeshesAreEqual(MeshLib::Mesh const &mesh, MeshLib::Mesh const &main_mesh, std::string error_message)
Definition PVD2XDMF.cpp:80
std::vector< std::pair< double, std::string > > readPvd(std::string const &pvd_filename)
Definition PVD2XDMF.cpp:33
bool copyPropertyVector(MeshLib::Properties const &properties, MeshLib::PropertyVectorBase *destination_pv)
Definition PVD2XDMF.cpp:59
void setConsoleLogLevel(std::string const &level_string)
Definition Logging.cpp:37
std::string extractPath(std::string const &pathname)
std::string extractBaseNameWithoutExtension(std::string const &pathname)
std::string joinPaths(std::string const &pathA, std::string const &pathB)
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name, bool const compute_element_neighbors)

References copyPropertyVector(), DBUG(), BaseLib::extractBaseNameWithoutExtension(), BaseLib::extractPath(), BaseLib::joinPaths(), OGS_FATAL, GitInfoLib::GitInfo::ogs_version, MeshLib::IO::readMeshFromFile(), readPvd(), BaseLib::setConsoleLogLevel(), and testIfMeshesAreEqual().

◆ readPvd()

std::vector< std::pair< double, std::string > > readPvd ( std::string const & pvd_filename)

Definition at line 33 of file PVD2XDMF.cpp.

35{
36 DBUG("Start reading the PVD file {:s}", pvd_filename);
37 boost::property_tree::ptree pvd;
38 read_xml(pvd_filename, pvd,
39 boost::property_tree::xml_parser::trim_whitespace);
40
41 std::vector<std::pair<double, std::string>> timeseries;
42 for (auto const& dataset : pvd.get_child("VTKFile.Collection"))
43 {
44 if (dataset.first != "DataSet")
45 {
46 OGS_FATAL("Expected DataSet tag but got '{:s}'", dataset.first);
47 }
48
49 auto const time = dataset.second.get<double>("<xmlattr>.timestep");
50 auto const file = dataset.second.get<std::string>("<xmlattr>.file");
51 timeseries.emplace_back(time, file);
52 }
53 DBUG("Finished reading the PVD file {:s}", pvd_filename);
54
55 return timeseries;
56}

References DBUG(), and OGS_FATAL.

Referenced by main().

◆ testIfMeshesAreEqual()

void testIfMeshesAreEqual ( MeshLib::Mesh const & mesh,
MeshLib::Mesh const & main_mesh,
std::string error_message )

Definition at line 80 of file PVD2XDMF.cpp.

83{
84 if (mesh.getDimension() != main_mesh.getDimension())
85 {
87 "{:s}The mesh has dimension {} which is different from the "
88 "dimension {} of in the main mesh.",
89 error_message, mesh.getDimension(), main_mesh.getDimension());
90 }
91 if (mesh.getNumberOfElements() != main_mesh.getNumberOfElements())
92 {
94 "{:s}The mesh has {} elements which is different from the number "
95 "of elements ({}) in the main mesh.",
96 error_message, mesh.getNumberOfElements(),
97 main_mesh.getNumberOfElements());
98 }
99 if (mesh.getNumberOfNodes() != main_mesh.getNumberOfNodes())
100 {
101 OGS_FATAL(
102 "{:s}The mesh has {} nodes which is different from the number of "
103 "nodes ({}) in the main mesh.",
104 error_message, mesh.getNumberOfNodes(),
105 main_mesh.getNumberOfNodes());
106 }
107}

References MeshLib::Mesh::getDimension(), MeshLib::Mesh::getNumberOfElements(), MeshLib::Mesh::getNumberOfNodes(), and OGS_FATAL.

Referenced by main().