OGS
PVD2XDMF.cpp File Reference
#include <tclap/CmdLine.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/MPI.h"
#include "BaseLib/MemWatch.h"
#include "BaseLib/StringTools.h"
#include "BaseLib/TCLAPArguments.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 50 of file PVD2XDMF.cpp.

52{
53 if (!dynamic_cast<MeshLib::PropertyVector<T>*>(destination_pv))
54 {
55 return false;
56 }
57
58 auto const* pv = properties.getPropertyVector<T>(
59 destination_pv->getPropertyName(), destination_pv->getMeshItemType(),
60 destination_pv->getNumberOfGlobalComponents());
61
62 assert(pv != nullptr);
63
64 std::copy(
65 std::begin(*pv), std::end(*pv),
66 std::begin(dynamic_cast<MeshLib::PropertyVector<T>&>(*destination_pv)));
67
68 return true;
69}
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 100 of file PVD2XDMF.cpp.

101{
102 TCLAP::CmdLine cmd(
103 "Converts a time series from PVD to XDMF format.\n\n"
104 "OpenGeoSys-6 software, version " +
106 ".\n"
107 "Copyright (c) 2012-2026, OpenGeoSys Community "
108 "(http://www.opengeosys.org)",
110
111 auto log_level_arg = BaseLib::makeLogLevelArg();
112 cmd.add(log_level_arg);
113
114 TCLAP::UnlabeledValueArg<std::string> pvd_file_arg(
115 "pvd-file", "Input (.pvd) file", true, "", "INPUT_FILE");
116 cmd.add(pvd_file_arg);
117
118 TCLAP::ValueArg<std::string> outdir_arg(
119 "o", "output-directory", "Output. The output directory to write to",
120 false, ".", "OUTPUT_PATH");
121 cmd.add(outdir_arg);
122
123 cmd.parse(argc, argv);
124
125 BaseLib::MPI::Setup mpi_setup(argc, argv);
126 BaseLib::initOGSLogger(log_level_arg.getValue());
127
128 auto const pvd_file_dir = BaseLib::extractPath(pvd_file_arg.getValue());
129
130 auto const timeseries = readPvd(pvd_file_arg.getValue());
131
132 if (timeseries.empty())
133 {
134 OGS_FATAL("Empty time series.");
135 }
136
137 // Initialized from the first timeseries entry and data is updated for each
138 // subsequent time step.
139 std::unique_ptr<MeshLib::Mesh> main_mesh;
140
141 std::filesystem::path const output_file{
142 BaseLib::extractBaseNameWithoutExtension(pvd_file_arg.getValue()) +
143 ".xdmf"};
144 std::filesystem::path output_file_path{outdir_arg.getValue()};
145 if (outdir_arg.getValue() != "")
146 {
147 output_file_path =
148 BaseLib::joinPaths(outdir_arg.getValue(), output_file.string());
149 }
150 std::set<std::string> variable_output_names;
151 std::unique_ptr<MeshLib::IO::XdmfHdfWriter> mesh_xdmf_hdf_writer;
152 // read first file in the time series; it is determining variables.
153 {
154 auto [time, filename] = timeseries[0];
155 DBUG("{} - {}", time, filename);
156
157 main_mesh.reset(MeshLib::IO::readMeshFromFile(
158 BaseLib::joinPaths(pvd_file_dir, filename)));
159 if (main_mesh == nullptr)
160 {
161 OGS_FATAL("Could not read mesh from '{:s}'.",
162 BaseLib::joinPaths(pvd_file_dir, filename));
163 }
164
165 for (auto const& p : main_mesh->getProperties())
166 {
167 variable_output_names.insert(std::string(p.first));
168 }
169 mesh_xdmf_hdf_writer = std::make_unique<MeshLib::IO::XdmfHdfWriter>(
170 std::vector{std::cref(*main_mesh)}, output_file_path,
171 0 /*timestep*/, time, variable_output_names,
172 true /*output_file.compression*/, 1 /*output_file.n_files*/,
173 1048576 /*chunk_size_bytes*/);
174 }
175
176 for (std::size_t timestep = 1; timestep < timeseries.size(); ++timestep)
177 {
178 auto [time, filename] = timeseries[timestep];
179 DBUG("{} - {}", time, filename);
180
181 std::unique_ptr<MeshLib::Mesh> mesh{MeshLib::IO::readMeshFromFile(
182 BaseLib::joinPaths(pvd_file_dir, filename))};
183 if (mesh == nullptr)
184 {
185 OGS_FATAL("Could not read mesh from '{:s}'.",
186 BaseLib::joinPaths(pvd_file_dir, filename));
187 }
188
190 *mesh, *main_mesh,
191 fmt::format("Error in comparison of mesh from file '{:s}' to the "
192 "main mesh:\n",
193 BaseLib::joinPaths(pvd_file_dir, filename)));
194
195 // We have to copy the values because the xdmf writer remembers the data
196 // pointers. Therefore replacing the properties will not work.
197 for (auto& [name, pv] : main_mesh->getProperties())
198 {
199 if (copyPropertyVector<double>(mesh->getProperties(), pv) ||
200 copyPropertyVector<float>(mesh->getProperties(), pv) ||
201 copyPropertyVector<int>(mesh->getProperties(), pv) ||
202 copyPropertyVector<long>(mesh->getProperties(), pv) ||
203 copyPropertyVector<unsigned>(mesh->getProperties(), pv) ||
204 copyPropertyVector<unsigned long>(mesh->getProperties(), pv) ||
205 copyPropertyVector<std::size_t>(mesh->getProperties(), pv) ||
206 copyPropertyVector<char>(mesh->getProperties(), pv) ||
207 copyPropertyVector<unsigned char>(mesh->getProperties(), pv))
208 {
209 continue;
210 }
211 OGS_FATAL(
212 "Could not copy property vector '{:s}' from '{:s}' mesh to the "
213 "main_mesh.",
214 name, BaseLib::joinPaths(pvd_file_dir, filename));
215 }
216
217 mesh_xdmf_hdf_writer->writeStep(time);
218 }
219 return EXIT_SUCCESS;
220}
#define OGS_FATAL(...)
Definition Error.h:19
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
void testIfMeshesAreEqual(MeshLib::Mesh const &mesh, MeshLib::Mesh const &main_mesh, std::string error_message)
Definition PVD2XDMF.cpp:71
std::vector< std::pair< double, std::string > > readPvd(std::string const &pvd_filename)
Definition PVD2XDMF.cpp:24
bool copyPropertyVector(MeshLib::Properties const &properties, MeshLib::PropertyVectorBase *destination_pv)
Definition PVD2XDMF.cpp:50
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:56
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::initOGSLogger(), BaseLib::joinPaths(), BaseLib::makeLogLevelArg(), OGS_FATAL, GitInfoLib::GitInfo::ogs_version, MeshLib::IO::readMeshFromFile(), readPvd(), and testIfMeshesAreEqual().

◆ readPvd()

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

Definition at line 24 of file PVD2XDMF.cpp.

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

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 71 of file PVD2XDMF.cpp.

74{
75 if (mesh.getDimension() != main_mesh.getDimension())
76 {
78 "{:s}The mesh has dimension {} which is different from the "
79 "dimension {} of in the main mesh.",
80 error_message, mesh.getDimension(), main_mesh.getDimension());
81 }
82 if (mesh.getNumberOfElements() != main_mesh.getNumberOfElements())
83 {
85 "{:s}The mesh has {} elements which is different from the number "
86 "of elements ({}) in the main mesh.",
87 error_message, mesh.getNumberOfElements(),
88 main_mesh.getNumberOfElements());
89 }
90 if (mesh.getNumberOfNodes() != main_mesh.getNumberOfNodes())
91 {
93 "{:s}The mesh has {} nodes which is different from the number of "
94 "nodes ({}) in the main mesh.",
95 error_message, mesh.getNumberOfNodes(),
96 main_mesh.getNumberOfNodes());
97 }
98}

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

Referenced by main().