OGS
PVTU2VTU.cpp File Reference
#include <tclap/CmdLine.h>
#include <algorithm>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <filesystem>
#include <fstream>
#include <memory>
#include <numeric>
#include <range/v3/algorithm/copy.hpp>
#include <range/v3/algorithm/transform.hpp>
#include <range/v3/numeric/accumulate.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/filter.hpp>
#include <string>
#include <unordered_set>
#include <vector>
#include "BaseLib/DemangleTypeInfo.h"
#include "BaseLib/FileTools.h"
#include "BaseLib/Logging.h"
#include "BaseLib/MPI.h"
#include "BaseLib/RunTime.h"
#include "BaseLib/TCLAPArguments.h"
#include "GeoLib/AABB.h"
#include "GeoLib/OctTree.h"
#include "InfoLib/GitInfo.h"
#include "MathLib/Point3d.h"
#include "MeshLib/Elements/Element.h"
#include "MeshLib/IO/VtkIO/VtuInterface.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/Node.h"
#include "MeshLib/Properties.h"
#include "MeshLib/Utils/IntegrationPointWriter.h"
#include "MeshLib/Utils/getOrCreateMeshProperty.h"
#include "MeshToolsLib/IntegrationPointDataTools.h"
Include dependency graph for PVTU2VTU.cpp:

Go to the source code of this file.

Classes

struct  MeshEntityMapInfo

Functions

template<typename T>
bool createPropertyVector (MeshLib::Mesh &merged_mesh, std::vector< std::unique_ptr< MeshLib::Mesh > > const &partitioned_meshes, MeshLib::PropertyVector< T > const *const pv, MeshLib::Properties const &properties, std::vector< MeshEntityMapInfo > const &merged_node_map, std::vector< MeshEntityMapInfo > const &merged_element_map)
std::vector< std::string > readVtuFileNames (std::string const &pvtu_file_name)
std::tuple< std::vector< MeshLib::Node * >, std::vector< std::size_t > > getMergedNodesVector (std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
std::tuple< std::vector< MeshLib::Element * >, std::vector< MeshEntityMapInfo > > getRegularElements (std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
MeshLib::NodegetExistingNodeFromOctTree (GeoLib::OctTree< MeshLib::Node, 16 > &oct_tree, Eigen::Vector3d const &extent, MeshLib::Node const &node, std::size_t const element_id)
void resetNodesInRegularElements (std::vector< MeshLib::Element * > const &regular_elements, GeoLib::OctTree< MeshLib::Node, 16 > &oct_tree, Eigen::Vector3d const &extent)
std::pair< std::vector< MeshLib::Node * >, std::vector< MeshEntityMapInfo > > makeNodesUnique (std::vector< MeshLib::Node * > const &all_merged_nodes_tmp, std::vector< std::size_t > const &partition_offsets, GeoLib::OctTree< MeshLib::Node, 16 > &oct_tree)
std::unique_ptr< MeshLib::MeshmergeSubdomainMeshes (std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
template<typename T>
bool transfer (MeshLib::Properties const &subdomain_properties, MeshLib::Mesh &original_mesh, MeshLib::PropertyVector< std::size_t > const &global_ids, std::string_view const property_name, MeshLib::MeshItemType const mesh_item_type)
void transferPropertiesFromPartitionedMeshToUnpartitionedMesh (MeshLib::Mesh const &subdomain_mesh, MeshLib::Mesh &original_mesh, MeshLib::MeshItemType const mesh_item_type)
void transferPropertiesFromPartitionedMeshToUnpartitionedMesh (MeshLib::Mesh const &subdomain_mesh, MeshLib::Mesh &original_mesh)
int main (int argc, char *argv[])

Function Documentation

◆ createPropertyVector()

template<typename T>
bool createPropertyVector ( MeshLib::Mesh & merged_mesh,
std::vector< std::unique_ptr< MeshLib::Mesh > > const & partitioned_meshes,
MeshLib::PropertyVector< T > const *const pv,
MeshLib::Properties const & properties,
std::vector< MeshEntityMapInfo > const & merged_node_map,
std::vector< MeshEntityMapInfo > const & merged_element_map )

Definition at line 48 of file PVTU2VTU.cpp.

55{
56 if (pv == nullptr)
57 {
58 return false;
59 }
60
61 if (pv->getPropertyName() == "vtkGhostType")
62 {
63 // Do nothing
64 return true;
65 }
66
67 auto const item_type = pv->getMeshItemType();
68
69 auto const pv_name = pv->getPropertyName();
70
71 auto const pv_num_components = pv->getNumberOfGlobalComponents();
72
73 if (pv_name == "OGS_VERSION" || pv_name == "IntegrationPointMetaData")
74 {
76 merged_mesh, pv_name, item_type, pv_num_components);
77 new_pv->assign(*pv);
78
79 return true;
80 }
81
82 std::vector<MeshLib::PropertyVector<T>*> partition_property_vectors;
83 partition_property_vectors.reserve(partitioned_meshes.size());
84 for (auto const& mesh : partitioned_meshes)
85 {
86 partition_property_vectors.emplace_back(
87 mesh->getProperties().getPropertyVector<T>(pv_name, item_type,
88 pv_num_components));
89 }
90
91 auto createNewCellOrNodePropertyVector =
92 [&](std::vector<MeshEntityMapInfo> const& mesh_entity_map)
93 {
95 merged_mesh, pv_name, item_type, pv_num_components);
96 std::size_t counter = 0;
97 for (auto const& entity_info : mesh_entity_map)
98 {
99 auto const& partition_pv =
100 partition_property_vectors[entity_info.partition_id];
101 for (int i_com = 0; i_com < pv_num_components; i_com++)
102 {
103 (*new_pv)[counter * pv_num_components + i_com] =
104 (*partition_pv)[entity_info.original_id *
105 pv_num_components +
106 i_com];
107 }
108 counter++;
109 }
110 };
111
112 if (item_type == MeshLib::MeshItemType::Node)
113 {
114 createNewCellOrNodePropertyVector(merged_node_map);
115 return true;
116 }
117
118 if (item_type == MeshLib::MeshItemType::Cell)
119 {
120 createNewCellOrNodePropertyVector(merged_element_map);
121 return true;
122 }
123
125 {
126 std::vector<std::vector<std::size_t>> partition_element_offsets;
127 partition_element_offsets.reserve(partitioned_meshes.size());
128 for (auto const& mesh : partitioned_meshes)
129 {
130 partition_element_offsets.emplace_back(
132 mesh->getElements(), *pv, properties));
133 }
134
136 merged_mesh, pv_name, item_type, pv_num_components);
137
138 // Count the integration points
139 auto const ip_meta_data =
141 MeshLib::getIntegrationPointMetaData(properties), pv_name);
142
143 auto number_of_integration_points = [&](auto const* element)
144 {
146 ip_meta_data, *element);
147 };
148
149 std::size_t const counter = ranges::accumulate(
150 merged_mesh.getElements() |
151 ranges::views::transform(number_of_integration_points),
152 std::size_t{0});
153 new_pv->resize(counter * pv_num_components);
154
155 auto const global_ip_offsets =
157 merged_mesh.getElements(), *pv, properties);
158
159 std::size_t element_counter = 0;
160 for (auto const& element_info : merged_element_map)
161 {
162 MeshLib::PropertyVector<T> const& partition_pv =
163 *(partition_property_vectors[element_info.partition_id]);
164
165 auto const& offsets =
166 partition_element_offsets[element_info.partition_id];
167
168 int const begin_pos = offsets[element_info.original_id];
169 int const end_pos = offsets[element_info.original_id + 1];
170
171 std::copy(partition_pv.begin() + begin_pos,
172 partition_pv.begin() + end_pos,
173 new_pv->begin() + global_ip_offsets[element_counter]);
174
175 element_counter++;
176 }
177 }
178
179 return true;
180}
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition Mesh.h:100
MeshItemType getMeshItemType() const
int getNumberOfGlobalComponents() const
std::string const & getPropertyName() const
constexpr PROP_VAL_TYPE * begin()
PropertyVector< T > * getOrCreateMeshProperty(Mesh &mesh, std::string const &property_name, MeshItemType const item_type, int const number_of_components)
std::optional< IntegrationPointMetaData > getIntegrationPointMetaData(MeshLib::Properties const &properties)
IntegrationPointMetaDataSingleField getIntegrationPointMetaDataSingleField(std::optional< IntegrationPointMetaData > const &ip_meta_data, std::string const &field_name)
std::vector< std::size_t > getIntegrationPointDataOffsetsOfMeshElements(std::vector< MeshLib::Element * > const &mesh_elements, MeshLib::PropertyVectorBase const &pv, MeshLib::Properties const &properties)
int getNumberOfElementIntegrationPoints(MeshLib::IntegrationPointMetaDataSingleField const &ip_meta_data, MeshLib::Element const &e)

References MeshLib::PropertyVector< PROP_VAL_TYPE >::begin(), MeshLib::Cell, MeshLib::Mesh::getElements(), MeshToolsLib::getIntegrationPointDataOffsetsOfMeshElements(), MeshLib::getIntegrationPointMetaData(), MeshLib::getIntegrationPointMetaDataSingleField(), MeshLib::PropertyVectorBase::getMeshItemType(), MeshToolsLib::getNumberOfElementIntegrationPoints(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::getOrCreateMeshProperty(), MeshLib::PropertyVectorBase::getPropertyName(), MeshLib::IntegrationPoint, and MeshLib::Node.

Referenced by mergeSubdomainMeshes().

◆ getExistingNodeFromOctTree()

MeshLib::Node * getExistingNodeFromOctTree ( GeoLib::OctTree< MeshLib::Node, 16 > & oct_tree,
Eigen::Vector3d const & extent,
MeshLib::Node const & node,
std::size_t const element_id )

Definition at line 286 of file PVTU2VTU.cpp.

289{
290 std::vector<MeshLib::Node*> query_nodes;
291 auto const eps =
292 std::numeric_limits<double>::epsilon() * extent.squaredNorm();
293 Eigen::Vector3d const min = node.asEigenVector3d().array() - eps;
294 auto constexpr dir = std::numeric_limits<double>::max();
295 Eigen::Vector3d const max = {std::nextafter(node[0] + eps, dir),
296 std::nextafter(node[1] + eps, dir),
297 std::nextafter(node[2] + eps, dir)};
298 oct_tree.getPointsInRange(min, max, query_nodes);
299
300 if (query_nodes.empty())
301 {
302 OGS_FATAL(
303 "query_nodes for node [{}], ({}, {}, {}) of element "
304 "[{}] are empty, eps is {}",
305 node.getID(), node[0], node[1], node[2], element_id, eps);
306 }
307 auto const it =
308 std::find_if(query_nodes.begin(), query_nodes.end(),
309 [&node, eps](auto const* p)
310 {
311 return (p->asEigenVector3d() - node.asEigenVector3d())
312 .squaredNorm() < eps;
313 });
314 if (it == query_nodes.end())
315 {
316 OGS_FATAL(
317 "did not find node: [{}] ({}, {}, {}) of element [{}] in "
318 "query_nodes",
319 node.getID(), node[0], node[1], node[2], element_id);
320 }
321 return *it;
322}
#define OGS_FATAL(...)
Definition Error.h:19
void getPointsInRange(T const &min, T const &max, std::vector< POINT * > &pnts) const

References MathLib::Point3d::asEigenVector3d(), MathLib::Point3dWithID::getID(), GeoLib::OctTree< POINT, MAX_POINTS >::getPointsInRange(), and OGS_FATAL.

Referenced by resetNodesInRegularElements().

◆ getMergedNodesVector()

std::tuple< std::vector< MeshLib::Node * >, std::vector< std::size_t > > getMergedNodesVector ( std::vector< std::unique_ptr< MeshLib::Mesh > > const & meshes)

Definition at line 225 of file PVTU2VTU.cpp.

226{
227 std::vector<std::size_t> number_of_nodes_per_partition;
228 ranges::transform(meshes, std::back_inserter(number_of_nodes_per_partition),
229 [](auto const& mesh)
230 { return mesh->getNumberOfNodes(); });
231 std::vector<std::size_t> const offsets =
232 BaseLib::sizesToOffsets(number_of_nodes_per_partition);
233
234 std::vector<MeshLib::Node*> all_nodes;
235 all_nodes.reserve(offsets.back());
236 for (auto const& mesh : meshes)
237 {
238 ranges::copy(mesh->getNodes(), std::back_inserter(all_nodes));
239 }
240 return {all_nodes, offsets};
241}
std::vector< ranges::range_value_t< R > > sizesToOffsets(R const &sizes)
Definition Algorithm.h:276

References BaseLib::sizesToOffsets().

Referenced by mergeSubdomainMeshes().

◆ getRegularElements()

std::tuple< std::vector< MeshLib::Element * >, std::vector< MeshEntityMapInfo > > getRegularElements ( std::vector< std::unique_ptr< MeshLib::Mesh > > const & meshes)

Definition at line 244 of file PVTU2VTU.cpp.

245{
246 std::vector<MeshLib::Element*> regular_elements;
247
248 std::size_t partition_counter = 0;
249 std::vector<MeshEntityMapInfo> merged_element_map;
250 for (auto const& mesh : meshes)
251 {
252 MeshLib::Properties const& properties = mesh->getProperties();
253
254 auto const* const ghost_id_vector =
255 properties.getPropertyVector<unsigned char>("vtkGhostType");
256 assert(ghost_id_vector);
257
258 auto const& mesh_elements = mesh->getElements();
259
260 auto const last_element_id_of_previous_partition =
261 regular_elements.size();
262
263 auto is_regular_element = [&](MeshLib::Element const* element)
264 { return (*ghost_id_vector)[element->getID()] == 0; };
265
266 auto regular_mesh_elements =
267 mesh_elements | ranges::views::filter(is_regular_element);
268 regular_elements.insert(regular_elements.end(),
269 regular_mesh_elements.begin(),
270 regular_mesh_elements.end());
271
272 for (auto element_id = last_element_id_of_previous_partition;
273 element_id < regular_elements.size();
274 element_id++)
275 {
276 merged_element_map.push_back(
277 {partition_counter, regular_elements[element_id]->getID()});
278 }
279
280 partition_counter++;
281 }
282
283 return {regular_elements, merged_element_map};
284}
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
PropertyVector< T > const * getPropertyVector(std::string_view name) const

References MeshLib::Properties::getPropertyVector().

Referenced by mergeSubdomainMeshes().

◆ main()

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

Definition at line 561 of file PVTU2VTU.cpp.

562{
563 TCLAP::CmdLine cmd(
564 "This tool merges VTU files of PVTU into one single VTU file. Apart "
565 "from the mesh data, all property data are merged as well"
566 "\n\nOpenGeoSys-6 software, version " +
568 ".\n"
569 "Copyright (c) 2012-2026, OpenGeoSys Community "
570 "(http://www.opengeosys.org)",
572
573 TCLAP::ValueArg<std::string> output_arg(
574 "o", "output", "Output (.vtu). The output mesh file (format = *.vtu)",
575 true, "", "OUTPUT_FILE");
576 cmd.add(output_arg);
577
578 TCLAP::ValueArg<std::string> input_arg(
579 "i", "input", "Input (.pvtu). The partitioned input mesh file", true,
580 "", "INPUT_FILE");
581 cmd.add(input_arg);
582
583 TCLAP::ValueArg<std::string> original_mesh_input_arg(
584 "m", "original_mesh",
585 "optional, the original unpartitioned input mesh (*.vtu)", false, "",
586 "");
587 cmd.add(original_mesh_input_arg);
588
589 auto log_level_arg = BaseLib::makeLogLevelArg();
590
591 cmd.add(log_level_arg);
592 cmd.parse(argc, argv);
593
594 BaseLib::MPI::Setup mpi_setup(argc, argv);
595 BaseLib::initOGSLogger(log_level_arg.getValue());
596
597 if (BaseLib::getFileExtension(input_arg.getValue()) != ".pvtu")
598 {
599 OGS_FATAL("The extension of input file name {:s} is not \"pvtu\"",
600 input_arg.getValue());
601 }
602 if (BaseLib::getFileExtension(output_arg.getValue()) != ".vtu")
603 {
604 OGS_FATAL("The extension of output file name {:s} is not \"vtu\"",
605 output_arg.getValue());
606 }
607
608 auto const vtu_file_names = readVtuFileNames(input_arg.getValue());
609
610 std::vector<std::unique_ptr<MeshLib::Mesh>> meshes;
611 meshes.reserve(vtu_file_names.size());
612
613 BaseLib::RunTime io_timer;
614 io_timer.start();
615 for (auto const& file_name : vtu_file_names)
616 {
617 auto mesh = std::unique_ptr<MeshLib::Mesh>(
619
620 MeshLib::Properties const& properties = mesh->getProperties();
621
622 if (!properties.existsPropertyVector<unsigned char>("vtkGhostType"))
623 {
624 OGS_FATAL(
625 "Property vector vtkGhostType does not exist in mesh {:s}.",
626 file_name);
627 }
628
629 meshes.emplace_back(std::move(mesh));
630 }
631 INFO("Reading meshes took {} s", io_timer.elapsed());
632
633 std::unique_ptr<MeshLib::Mesh> merged_mesh;
634 if (original_mesh_input_arg.getValue().empty())
635 {
636 // use old, slow method that generates node and element orderings not
637 // consistent with the original mesh
638 merged_mesh = mergeSubdomainMeshes(meshes);
639 }
640 else
641 {
642 BaseLib::RunTime io_timer;
643 io_timer.start();
644 merged_mesh = std::unique_ptr<MeshLib::Mesh>(
646 original_mesh_input_arg.getValue()));
647 INFO("Reading original unpartitioned mesh took {} s",
648 io_timer.elapsed());
649 for (auto const& subdomain_mesh : meshes)
650 {
652 *(subdomain_mesh.get()), *merged_mesh);
653 }
654 }
655
656 MeshLib::IO::VtuInterface writer(merged_mesh.get());
657
658 BaseLib::RunTime writing_timer;
659 writing_timer.start();
660 auto const result = writer.writeToFile(output_arg.getValue());
661 if (!result)
662 {
663 ERR("Could not write mesh to '{:s}'.", output_arg.getValue());
664 return EXIT_FAILURE;
665 }
666 INFO("writing mesh took {} s", writing_timer.elapsed());
667
668 // Since the Node pointers of 'merged_nodes' and Element pointers of
669 // 'regular_elements' are held by 'meshes', the partitioned meshes, the
670 // memory by these pointers are released by 'meshes' automatically.
671 // Therefore, only node vector and element vector of merged_mesh should be
672 // cleaned.
673 merged_mesh->shallowClean();
674
675 return EXIT_SUCCESS;
676}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
std::unique_ptr< MeshLib::Mesh > mergeSubdomainMeshes(std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
Definition PVTU2VTU.cpp:374
void transferPropertiesFromPartitionedMeshToUnpartitionedMesh(MeshLib::Mesh const &subdomain_mesh, MeshLib::Mesh &original_mesh, MeshLib::MeshItemType const mesh_item_type)
Definition PVTU2VTU.cpp:482
std::vector< std::string > readVtuFileNames(std::string const &pvtu_file_name)
Definition PVTU2VTU.cpp:182
Count the running time.
Definition RunTime.h:18
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:31
void start()
Start the timer.
Definition RunTime.h:21
Reads and writes VtkXMLUnstructuredGrid-files (vtu) to and from OGS data structures....
static MeshLib::Mesh * readVTUFile(std::string const &file_name, bool const compute_element_neighbors=false)
bool existsPropertyVector(std::string_view name) const
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:56
std::string getFileExtension(const std::string &path)
GITINFOLIB_EXPORT const std::string ogs_version

References BaseLib::RunTime::elapsed(), ERR(), MeshLib::Properties::existsPropertyVector(), BaseLib::getFileExtension(), INFO(), BaseLib::initOGSLogger(), BaseLib::makeLogLevelArg(), mergeSubdomainMeshes(), OGS_FATAL, GitInfoLib::GitInfo::ogs_version, MeshLib::IO::VtuInterface::readVTUFile(), readVtuFileNames(), BaseLib::RunTime::start(), transferPropertiesFromPartitionedMeshToUnpartitionedMesh(), and MeshLib::IO::VtuInterface::writeToFile().

◆ makeNodesUnique()

std::pair< std::vector< MeshLib::Node * >, std::vector< MeshEntityMapInfo > > makeNodesUnique ( std::vector< MeshLib::Node * > const & all_merged_nodes_tmp,
std::vector< std::size_t > const & partition_offsets,
GeoLib::OctTree< MeshLib::Node, 16 > & oct_tree )

Definition at line 346 of file PVTU2VTU.cpp.

349{
350 std::vector<MeshLib::Node*> unique_merged_nodes;
351 unique_merged_nodes.reserve(all_merged_nodes_tmp.size());
352
353 std::vector<MeshEntityMapInfo> merged_node_map;
354 merged_node_map.reserve(all_merged_nodes_tmp.size());
355
356 for (std::size_t i = 0; i < partition_offsets.size() - 1; ++i)
357 {
358 for (std::size_t pos = partition_offsets[i];
359 pos < partition_offsets[i + 1];
360 ++pos)
361 {
362 auto* node = all_merged_nodes_tmp[pos];
363 MeshLib::Node* node_ptr = nullptr;
364 if (oct_tree.addPoint(node, node_ptr))
365 {
366 unique_merged_nodes.push_back(node);
367 merged_node_map.push_back({i, pos - partition_offsets[i]});
368 }
369 }
370 }
371 return {unique_merged_nodes, merged_node_map};
372}
bool addPoint(POINT *pnt, POINT *&ret_pnt)

References GeoLib::OctTree< POINT, MAX_POINTS >::addPoint().

Referenced by mergeSubdomainMeshes().

◆ mergeSubdomainMeshes()

std::unique_ptr< MeshLib::Mesh > mergeSubdomainMeshes ( std::vector< std::unique_ptr< MeshLib::Mesh > > const & meshes)

Definition at line 374 of file PVTU2VTU.cpp.

376{
377 BaseLib::RunTime merged_element_timer;
378 merged_element_timer.start();
379 // If structured binding is used for the returned tuple, Mac compiler gives
380 // an error in reference to local binding in calling applyToPropertyVectors.
381 auto [regular_elements, merged_element_map] = getRegularElements(meshes);
382 INFO(
383 "Collection of {} regular elements and computing element map took {} s",
384 regular_elements.size(), merged_element_timer.elapsed());
385
386 // alternative implementation of getNodesOfRegularElements
387 BaseLib::RunTime collect_nodes_timer;
388 collect_nodes_timer.start();
389 auto [all_merged_nodes_tmp, partition_offsets] =
390 getMergedNodesVector(meshes);
391 INFO("Collection of {} nodes and computing offsets took {} s",
392 all_merged_nodes_tmp.size(), collect_nodes_timer.elapsed());
393
394 BaseLib::RunTime merged_nodes_timer;
395 merged_nodes_timer.start();
396 GeoLib::AABB aabb(all_merged_nodes_tmp.begin(), all_merged_nodes_tmp.end());
397 auto oct_tree = std::unique_ptr<GeoLib::OctTree<MeshLib::Node, 16>>(
399 aabb.getMinPoint(), aabb.getMaxPoint(), 1e-16));
400
401 auto [unique_merged_nodes, merged_node_map] =
402 makeNodesUnique(all_merged_nodes_tmp, partition_offsets, *oct_tree);
403 INFO("Make nodes unique ({} unique nodes) / computing map took {} s",
404 unique_merged_nodes.size(), merged_nodes_timer.elapsed());
405
406 BaseLib::RunTime reset_nodes_in_elements_timer;
407 reset_nodes_in_elements_timer.start();
408 auto const extent = aabb.getMaxPoint() - aabb.getMinPoint();
409 resetNodesInRegularElements(regular_elements, *oct_tree, extent);
410 INFO("Reset nodes in regular elements took {} s",
411 reset_nodes_in_elements_timer.elapsed());
412
413 BaseLib::RunTime mesh_creation_timer;
414 mesh_creation_timer.start();
415 // The Node pointers of 'merged_nodes' and Element pointers of
416 // 'regular_elements' are shared with 'meshes', the partitioned meshes.
417 auto merged_mesh = std::make_unique<MeshLib::Mesh>(
418 "pvtu_merged_mesh", unique_merged_nodes, regular_elements,
419 false /* compute_element_neighbors */);
420 INFO("creation of merged mesh took {} s", mesh_creation_timer.elapsed());
421
422 auto const& properties = meshes[0]->getProperties();
423
424 BaseLib::RunTime property_timer;
425 property_timer.start();
427 properties,
428 [&, &merged_node_map = merged_node_map,
429 &merged_element_map = merged_element_map](auto type,
430 auto const& property)
431 {
433 *merged_mesh, meshes,
434 dynamic_cast<MeshLib::PropertyVector<decltype(type)> const*>(
435 property),
436 properties, merged_node_map, merged_element_map);
437 });
438 INFO("merge properties into merged mesh took {} s",
439 property_timer.elapsed());
440 return merged_mesh;
441}
std::pair< std::vector< MeshLib::Node * >, std::vector< MeshEntityMapInfo > > makeNodesUnique(std::vector< MeshLib::Node * > const &all_merged_nodes_tmp, std::vector< std::size_t > const &partition_offsets, GeoLib::OctTree< MeshLib::Node, 16 > &oct_tree)
Definition PVTU2VTU.cpp:346
void resetNodesInRegularElements(std::vector< MeshLib::Element * > const &regular_elements, GeoLib::OctTree< MeshLib::Node, 16 > &oct_tree, Eigen::Vector3d const &extent)
Definition PVTU2VTU.cpp:324
std::tuple< std::vector< MeshLib::Element * >, std::vector< MeshEntityMapInfo > > getRegularElements(std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
Definition PVTU2VTU.cpp:244
bool createPropertyVector(MeshLib::Mesh &merged_mesh, std::vector< std::unique_ptr< MeshLib::Mesh > > const &partitioned_meshes, MeshLib::PropertyVector< T > const *const pv, MeshLib::Properties const &properties, std::vector< MeshEntityMapInfo > const &merged_node_map, std::vector< MeshEntityMapInfo > const &merged_element_map)
Definition PVTU2VTU.cpp:48
std::tuple< std::vector< MeshLib::Node * >, std::vector< std::size_t > > getMergedNodesVector(std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
Definition PVTU2VTU.cpp:225
Class AABB is an axis aligned bounding box around a given set of geometric points of (template) type ...
Definition AABB.h:45
static OctTree< POINT, MAX_POINTS > * createOctTree(Eigen::Vector3d ll, Eigen::Vector3d ur, double eps=std::numeric_limits< double >::epsilon())
Definition OctTree-impl.h:7
void applyToPropertyVectors(Properties const &properties, Function f)

References GeoLib::OctTree< POINT, MAX_POINTS >::createOctTree(), createPropertyVector(), BaseLib::RunTime::elapsed(), GeoLib::AABB::getMaxPoint(), getMergedNodesVector(), GeoLib::AABB::getMinPoint(), getRegularElements(), INFO(), makeNodesUnique(), resetNodesInRegularElements(), and BaseLib::RunTime::start().

Referenced by main().

◆ readVtuFileNames()

std::vector< std::string > readVtuFileNames ( std::string const & pvtu_file_name)

Definition at line 182 of file PVTU2VTU.cpp.

183{
184 std::ifstream ins(pvtu_file_name);
185
186 if (!ins)
187 {
188 OGS_FATAL("Could not open pvtu file {:s}.", pvtu_file_name);
189 }
190
191 using boost::property_tree::ptree;
192 ptree pt;
193 read_xml(ins, pt);
194
195 auto root = pt.get_child("VTKFile");
196
197 std::vector<std::string> vtu_file_names;
198
199 std::string file_path = BaseLib::extractPath(pvtu_file_name);
200
201 for (ptree::value_type const& v : root.get_child("PUnstructuredGrid"))
202 {
203 if (v.first == "Piece")
204 {
205 vtu_file_names.push_back(BaseLib::joinPaths(
206 file_path,
207 // only gets the vtu file name:
208 std::filesystem::path(v.second.get("<xmlattr>.Source", ""))
209 .filename()
210 .string()));
211 }
212 }
213
214 if (vtu_file_names.empty())
215 {
216 OGS_FATAL("PVTU file {:s} does not contain any vtu piece",
217 pvtu_file_name);
218 }
219
220 return vtu_file_names;
221}
std::string extractPath(std::string const &pathname)
std::string joinPaths(std::string const &pathA, std::string const &pathB)

References BaseLib::extractPath(), BaseLib::joinPaths(), and OGS_FATAL.

Referenced by main().

◆ resetNodesInRegularElements()

void resetNodesInRegularElements ( std::vector< MeshLib::Element * > const & regular_elements,
GeoLib::OctTree< MeshLib::Node, 16 > & oct_tree,
Eigen::Vector3d const & extent )

Definition at line 324 of file PVTU2VTU.cpp.

328{
329 for (auto& e : regular_elements)
330 {
331 for (unsigned i = 0; i < e->getNumberOfNodes(); i++)
332 {
333 auto* const node = e->getNode(i);
334 MeshLib::Node* node_ptr = nullptr;
335 if (!oct_tree.addPoint(node, node_ptr))
336 {
337 auto const node_ptr = getExistingNodeFromOctTree(
338 oct_tree, extent, *node, e->getID());
339 e->setNode(i, node_ptr);
340 }
341 }
342 }
343}
MeshLib::Node * getExistingNodeFromOctTree(GeoLib::OctTree< MeshLib::Node, 16 > &oct_tree, Eigen::Vector3d const &extent, MeshLib::Node const &node, std::size_t const element_id)
Definition PVTU2VTU.cpp:286

References GeoLib::OctTree< POINT, MAX_POINTS >::addPoint(), and getExistingNodeFromOctTree().

Referenced by mergeSubdomainMeshes().

◆ transfer()

template<typename T>
bool transfer ( MeshLib::Properties const & subdomain_properties,
MeshLib::Mesh & original_mesh,
MeshLib::PropertyVector< std::size_t > const & global_ids,
std::string_view const property_name,
MeshLib::MeshItemType const mesh_item_type )

Definition at line 444 of file PVTU2VTU.cpp.

449{
450 if (!subdomain_properties.existsPropertyVector<T>(property_name))
451 {
452 INFO("Skipping property '{}' since it is not from type '{}'.",
453 property_name, BaseLib::typeToString<T>());
454 return false;
455 }
456 auto const* subdomain_pv =
457 subdomain_properties.getPropertyVector<T>(property_name);
458 auto const number_of_components =
459 subdomain_pv->getNumberOfGlobalComponents();
460
461 auto* original_pv = MeshLib::getOrCreateMeshProperty<T>(
462 original_mesh, std::string(property_name), mesh_item_type,
463 number_of_components);
464
465 for (std::size_t i = 0; i < global_ids.size(); ++i)
466 {
467 auto const& global_id = global_ids[i];
468 for (std::remove_cvref_t<decltype(number_of_components)>
469 component_number = 0;
470 component_number < number_of_components;
471 ++component_number)
472 {
473 original_pv->getComponent(global_id, component_number) =
474 subdomain_pv->getComponent(i, component_number);
475 }
476 }
477 INFO("Data array {} from data type '{}' transferred.", property_name,
479 return true;
480}
constexpr std::size_t size() const
std::string typeToString()

References MeshLib::Properties::existsPropertyVector(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::getOrCreateMeshProperty(), MeshLib::Properties::getPropertyVector(), INFO(), MeshLib::PropertyVector< PROP_VAL_TYPE >::size(), and BaseLib::typeToString().

Referenced by transferPropertiesFromPartitionedMeshToUnpartitionedMesh().

◆ transferPropertiesFromPartitionedMeshToUnpartitionedMesh() [1/2]

void transferPropertiesFromPartitionedMeshToUnpartitionedMesh ( MeshLib::Mesh const & subdomain_mesh,
MeshLib::Mesh & original_mesh )

◆ transferPropertiesFromPartitionedMeshToUnpartitionedMesh() [2/2]

void transferPropertiesFromPartitionedMeshToUnpartitionedMesh ( MeshLib::Mesh const & subdomain_mesh,
MeshLib::Mesh & original_mesh,
MeshLib::MeshItemType const mesh_item_type )

Definition at line 482 of file PVTU2VTU.cpp.

485{
486 auto const& subdomain_properties = subdomain_mesh.getProperties();
487 if (!subdomain_properties.existsPropertyVector<std::size_t>(
488 MeshLib::globalIDString(mesh_item_type), mesh_item_type, 1))
489 {
490 OGS_FATAL(
491 "The data array '{}' is required for the transfer of data from "
492 "subdomain mesh to the global mesh. But it doesn't exist in "
493 "subdomain mesh '{}'.",
494 MeshLib::globalIDString(mesh_item_type), subdomain_mesh.getName());
495 }
496 auto const* global_ids =
497 subdomain_properties.getPropertyVector<std::size_t>(
498 MeshLib::globalIDString(mesh_item_type), mesh_item_type, 1);
499 if (global_ids == nullptr)
500 {
501 OGS_FATAL("The data array '{}' is not available but required.",
502 MeshLib::globalIDString(mesh_item_type));
503 }
504
505 auto const& property_names =
506 subdomain_properties.getPropertyVectorNames(mesh_item_type);
507
508 for (auto const& property_name : property_names)
509 {
510 if (property_name == MeshLib::globalIDString(mesh_item_type))
511 {
512 continue;
513 }
514 if (property_name == MeshLib::getBulkIDString(mesh_item_type))
515 {
516 INFO(
517 "Skipping property '{}' since it is adjusted locally in "
518 "NodeWiseMeshPartitioner::renumberBulkNodeIdsProperty().",
519 MeshLib::getBulkIDString(mesh_item_type));
520 continue;
521 }
522 if (property_name == "vtkGhostType")
523 {
524 INFO(
525 "Skipping property 'vtkGhostType' since it is only required "
526 "for parallel execution.");
527 continue;
528 }
529 if (transfer<double>(subdomain_properties, original_mesh, *global_ids,
530 property_name, mesh_item_type) ||
531 transfer<float>(subdomain_properties, original_mesh, *global_ids,
532 property_name, mesh_item_type) ||
533 transfer<unsigned>(subdomain_properties, original_mesh, *global_ids,
534 property_name, mesh_item_type) ||
535 transfer<unsigned long>(subdomain_properties, original_mesh,
536 *global_ids, property_name,
537 mesh_item_type) ||
538 transfer<std::size_t>(subdomain_properties, original_mesh,
539 *global_ids, property_name, mesh_item_type) ||
540 transfer<int>(subdomain_properties, original_mesh, *global_ids,
541 property_name, mesh_item_type) ||
542 transfer<long>(subdomain_properties, original_mesh, *global_ids,
543 property_name, mesh_item_type))
544 {
545 INFO("Data array {} transferred from '{}' to'{}'", property_name,
546 subdomain_mesh.getName(), original_mesh.getName());
547 }
548 }
549}
bool transfer(MeshLib::Properties const &subdomain_properties, MeshLib::Mesh &original_mesh, MeshLib::PropertyVector< std::size_t > const &global_ids, std::string_view const property_name, MeshLib::MeshItemType const mesh_item_type)
Definition PVTU2VTU.cpp:444
const std::string getName() const
Get name of the mesh.
Definition Mesh.h:94
constexpr std::string_view getBulkIDString(MeshItemType mesh_item_type)
constexpr std::string_view globalIDString(MeshLib::MeshItemType const mesh_item_type)

References MeshLib::getBulkIDString(), MeshLib::Mesh::getName(), MeshLib::Mesh::getProperties(), MeshLib::Properties::getPropertyVector(), MeshLib::globalIDString(), INFO(), OGS_FATAL, and transfer().

Referenced by main(), and transferPropertiesFromPartitionedMeshToUnpartitionedMesh().