Loading [MathJax]/extensions/tex2jax.js
OGS
ApplicationUtils Namespace Reference

Detailed Description

Classes

class  ComputeNaturalCoordsIntermediateResult
 
struct  ComputeNaturalCoordsResult
 
class  ComputeNaturalCoordsRootFindingProblem
 
class  ComputeNaturalCoordsSolverImplementation
 
class  ComputeNaturalCoordsSolverInterface
 
struct  ConfigOffsets
 
class  FindCellsForPoints
 
class  NodeWiseMeshPartitioner
 Mesh partitioner. More...
 
struct  Partition
 A subdomain mesh. More...
 
struct  PartitionOffsets
 
class  SolverByElementTypeRegistry
 

Functions

ComputeNaturalCoordsResult computeNaturalCoords (vtkUnstructuredGrid *const bulk_mesh, Eigen::MatrixXd const &real_coords, double const tolerance, int const max_iter)
 
template<typename T >
void addPointData (vtkUnstructuredGrid *grid, std::string const &name, Eigen::MatrixX< T > const &data)
 
vtkSmartPointer< vtkUnstructuredGrid > toVTKGrid (ComputeNaturalCoordsResult const &result)
 
void writeMETIS (std::vector< MeshLib::Element * > const &elements, const std::string &file_name)
 
std::vector< std::size_t > readMetisData (const std::string &file_name_base, long const number_of_partitions, std::size_t const number_of_nodes)
 
void removeMetisPartitioningFiles (std::string const &file_name_base, long const number_of_partitions)
 
NodeWiseMeshPartitioner::IntegerType getNumberOfIntegerVariablesOfElements (std::vector< const MeshLib::Element * > const &elements)
 
std::size_t partitionLookup (std::size_t const &node_id, std::vector< std::size_t > const &partition_ids, std::span< std::size_t const > const node_id_mapping)
 
std::pair< std::vector< MeshLib::Node const * >, std::vector< MeshLib::Node const * > > splitIntoBaseAndHigherOrderNodes (std::vector< MeshLib::Node const * > const &nodes, MeshLib::Mesh const &mesh)
 
std::tuple< std::vector< MeshLib::Node * >, std::vector< MeshLib::Node * > > findGhostNodesInPartition (std::size_t const part_id, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element const * > const &ghost_elements, std::vector< std::size_t > const &partition_ids, MeshLib::Mesh const &mesh, std::span< std::size_t const > const node_id_mapping)
 
template<typename T >
std::size_t copyNodePropertyVectorValues (Partition const &p, std::size_t const offset, MeshLib::PropertyVector< T > const &pv, MeshLib::PropertyVector< T > &partitioned_pv)
 
template<typename T >
std::size_t copyCellPropertyVectorValues (Partition const &p, std::size_t const offset, MeshLib::PropertyVector< T > const &pv, MeshLib::PropertyVector< T > &partitioned_pv)
 
template<typename T >
std::size_t copyFieldPropertyDataToPartitions (MeshLib::Properties const &properties, Partition const &p, std::size_t const id_offset_partition, std::vector< std::size_t > const &element_ip_data_offsets, MeshLib::PropertyVector< T > const &pv, MeshLib::PropertyVector< T > &partitioned_pv)
 
void setIntegrationPointNumberOfPartition (MeshLib::Properties const &properties, std::vector< Partition > &partitions)
 
template<typename T >
bool copyPropertyVector (std::vector< MeshLib::Element * > const &global_mesh_elements, MeshLib::Properties &partitioned_properties, MeshLib::Properties const &properties, std::vector< Partition > const &partitions, MeshLib::PropertyVector< T > const *const pv, std::map< MeshLib::MeshItemType, std::size_t > const &total_number_of_tuples)
 
void addVtkGhostTypeProperty (MeshLib::Properties &partitioned_properties, std::vector< Partition > const &partitions, std::size_t const total_number_of_cells)
 
MeshLib::Properties partitionProperties (std::unique_ptr< MeshLib::Mesh > const &mesh, std::vector< Partition > &partitions)
 Partition existing properties and add vtkGhostType cell data array property.
 
void markDuplicateGhostCells (MeshLib::Mesh const &mesh, std::vector< Partition > &partitions)
 
void checkFieldPropertyVectorSize (std::vector< MeshLib::Element * > const &global_mesh_elements, MeshLib::Properties const &properties)
 
std::vector< std::vector< std::size_t > > computePartitionIDPerElement (std::vector< std::size_t > const &node_partition_map, std::vector< MeshLib::Element * > const &elements, std::span< std::size_t const > const bulk_node_ids)
 
void distributeNodesToPartitions (std::vector< Partition > &partitions, std::vector< std::size_t > const &nodes_partition_ids, std::vector< MeshLib::Node * > const &nodes, std::span< std::size_t const > const bulk_node_ids)
 
void reorderNodesIntoBaseAndHigherOrderNodes (Partition &partition, MeshLib::Mesh const &mesh)
 
void reorderNodesIntoBaseAndHigherOrderNodesPerPartition (std::vector< Partition > &partitions, MeshLib::Mesh const &mesh)
 
void setNumberOfNodesInPartitions (std::vector< Partition > &partitions, MeshLib::Mesh const &mesh)
 
void distributeElementsIntoPartitions (std::vector< Partition > &partitions, MeshLib::Mesh const &mesh, std::vector< std::vector< std::size_t > > const &partition_ids_per_element)
 
void determineAndAppendGhostNodesToPartitions (std::vector< Partition > &partitions, MeshLib::Mesh const &mesh, std::vector< std::size_t > const &nodes_partition_ids, std::span< std::size_t const > const node_id_mapping)
 
void partitionMesh (std::vector< Partition > &partitions, MeshLib::Mesh const &mesh, std::vector< std::size_t > const &nodes_partition_ids, std::span< std::size_t const > const bulk_node_ids)
 
template<typename T >
void writePropertyVectorValues (std::ostream &os, MeshLib::PropertyVector< T > const &pv)
 
template<typename T >
bool writePropertyVector (MeshLib::PropertyVector< T > const *const pv, MeshLib::MeshItemType const mesh_item_type, std::ostream &out_val, std::ostream &out_meta)
 
void writeProperties (const std::string &file_name_base, MeshLib::Properties const &partitioned_properties, std::vector< Partition > const &partitions, MeshLib::MeshItemType const mesh_item_type)
 
PartitionOffsets computePartitionOffsets (Partition const &partition)
 
ConfigOffsets incrementConfigOffsets (ConfigOffsets const &oldConfig, PartitionOffsets const &offsets)
 
std::tuple< std::vector< long >, std::vector< long > > writeConfigData (const std::string &file_name_base, std::vector< Partition > const &partitions)
 
void getElementIntegerVariables (const MeshLib::Element &elem, const std::unordered_map< std::size_t, long > &local_node_ids, std::vector< long > &elem_info, long &counter)
 
std::unordered_map< std::size_t, long > enumerateLocalNodeIds (std::vector< MeshLib::Node const * > const &nodes)
 Generates a mapping of given node ids to a new local (renumbered) node ids.
 
void writeElements (std::string const &file_name_base, std::vector< Partition > const &partitions, std::vector< long > const &regular_element_offsets, std::vector< long > const &ghost_element_offsets)
 
void writeNodes (const std::string &file_name_base, std::vector< Partition > const &partitions, std::vector< std::size_t > const &global_node_ids)
 

Function Documentation

◆ addPointData()

template<typename T >
void ApplicationUtils::addPointData ( vtkUnstructuredGrid * grid,
std::string const & name,
Eigen::MatrixX< T > const & data )

Definition at line 157 of file ComputeNaturalCoordsAlgorithm.h.

159{
160 INFO("converting {}", name);
161 vtkNew<vtkAOSDataArrayTemplate<T>> array;
162 array->SetName(name.c_str());
163 array->SetNumberOfComponents(data.cols());
164 array->SetNumberOfTuples(grid->GetNumberOfPoints());
165
166 if (grid->GetNumberOfPoints() != data.rows())
167 {
168 OGS_FATAL(
169 "Got {} rows in the table but expected {} rows, same as number of "
170 "points in the grid.",
171 data.rows(), grid->GetNumberOfPoints());
172 }
173 for (Eigen::Index i = 0; i < data.rows(); ++i)
174 {
175 // copy to contiguous storage
176 Eigen::RowVectorX<T> const row = data.row(i);
177
178 array->SetTypedTuple(i, row.data());
179 DBUG("> {}", row);
180 }
181
182 grid->GetPointData()->AddArray(array);
183}
#define OGS_FATAL(...)
Definition Error.h:26
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:35
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:30

References DBUG(), INFO(), and OGS_FATAL.

Referenced by toVTKGrid().

◆ addVtkGhostTypeProperty()

void ApplicationUtils::addVtkGhostTypeProperty ( MeshLib::Properties & partitioned_properties,
std::vector< Partition > const & partitions,
std::size_t const total_number_of_cells )

Definition at line 412 of file NodeWiseMeshPartitioner.cpp.

415{
416 auto* vtk_ghost_type =
417 partitioned_properties.createNewPropertyVector<unsigned char>(
418 "vtkGhostType", MeshLib::MeshItemType::Cell, total_number_of_cells,
419 1);
420 if (vtk_ghost_type == nullptr)
421 {
422 OGS_FATAL("Could not create vtkGhostType cell data array.");
423 }
424
425 assert(vtk_ghost_type->size() == total_number_of_cells);
426 std::size_t offset = 0;
427 for (auto const& partition : partitions)
428 {
429 offset += partition.regular_elements.size();
430 for (std::size_t i = 0; i < partition.ghost_elements.size(); ++i)
431 {
432 if (partition.duplicate_ghost_cell[i])
433 {
434 (*vtk_ghost_type)[offset + i] |=
435 vtkDataSetAttributes::DUPLICATECELL;
436 }
437 }
438 offset += partition.ghost_elements.size();
439 }
440}
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
Definition Properties.h:17

References MeshLib::Cell, MeshLib::Properties::createNewPropertyVector(), and OGS_FATAL.

Referenced by partitionProperties().

◆ checkFieldPropertyVectorSize()

void ApplicationUtils::checkFieldPropertyVectorSize ( std::vector< MeshLib::Element * > const & global_mesh_elements,
MeshLib::Properties const & properties )

Definition at line 519 of file NodeWiseMeshPartitioner.cpp.

522{
523 auto const& opt_ip_meta_data_all =
525 for (auto const& [name, property] : properties)
526 {
527 auto const item_type = property->getMeshItemType();
528
530 {
531 continue;
532 }
533
534 // For special field data such as OGS_VERSION, IntegrationPointMetaData,
535 // etc., which are not "real" integration points:
536 if (property->getPropertyName().find("_ip") == std::string::npos)
537 {
538 continue;
539 }
540
541 std::size_t number_of_total_integration_points = 0;
542 auto const ip_meta_data =
544 opt_ip_meta_data_all, property->getPropertyName());
545 for (auto const element : global_mesh_elements)
546 {
547 int const number_of_integration_points =
549 *element);
550 number_of_total_integration_points += number_of_integration_points;
551 }
552
553 const auto pv =
554 dynamic_cast<MeshLib::PropertyVector<double> const*>(property);
555 std::size_t const component_number = pv->getNumberOfGlobalComponents();
556 if (pv->size() != number_of_total_integration_points * component_number)
557 {
558 OGS_FATAL(
559 "The property vector's size {:d} for integration point data "
560 "{:s} does not match its actual size {:d}. The field data in "
561 "the vtu file are wrong.",
562 pv->size(), name,
563 number_of_total_integration_points * component_number);
564 }
565 }
566}
int getNumberOfGlobalComponents() const
std::optional< IntegrationPointMetaData > getIntegrationPointMetaData(MeshLib::Properties const &properties)
IntegrationPointMetaDataSingleField getIntegrationPointMetaDataSingleField(std::optional< IntegrationPointMetaData > const &ip_meta_data, std::string const &field_name)
int getNumberOfElementIntegrationPoints(MeshLib::IntegrationPointMetaDataSingleField const &ip_meta_data, MeshLib::Element const &e)

References MeshLib::getIntegrationPointMetaData(), MeshLib::getIntegrationPointMetaDataSingleField(), MeshToolsLib::getNumberOfElementIntegrationPoints(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::IntegrationPoint, and OGS_FATAL.

Referenced by ApplicationUtils::NodeWiseMeshPartitioner::partitionByMETIS().

◆ computeNaturalCoords()

ComputeNaturalCoordsResult ApplicationUtils::computeNaturalCoords ( vtkUnstructuredGrid *const bulk_mesh,
Eigen::MatrixXd const & real_coords,
double const tolerance,
int const max_iter )

Definition at line 78 of file ComputeNaturalCoordsAlgorithm.h.

81{
82 // Check inputs ------------------------------------------------------------
83
84 if (real_coords.cols() != 3)
85 {
86 OGS_FATAL("Wrong number of input coordinates");
87 }
88
89 // General definitions -----------------------------------------------------
90 using SolverRegistry =
91 SolverByElementTypeRegistry<ComputeNaturalCoordsSolverInterface,
92 ComputeNaturalCoordsSolverImplementation>;
93
94 double const real_coords_tolerance = tolerance;
95
96 // Initialization ----------------------------------------------------------
97 FindCellsForPoints findCellsForPoints;
98 findCellsForPoints.initialize(bulk_mesh);
99
100 ComputeNaturalCoordsIntermediateResult result;
101
102 // Do computation for each point ------------------------------------------
103 for (Eigen::Index rc_idx = 0; rc_idx < real_coords.rows(); ++rc_idx)
104 {
105 Eigen::RowVector3d const real_coords_single_point =
106 real_coords.row(rc_idx);
107
108 // Find cells for point
109 auto const filtered_bulk_mesh =
110 findCellsForPoints.find(real_coords_single_point, tolerance);
111
112 // Check multiplicity
113 int const actual_multiplicity = filtered_bulk_mesh->GetNumberOfCells();
114 if (actual_multiplicity == 0)
115 {
116 OGS_FATAL(
117 "Did not find any cell for the point {} (coordinates: {})",
118 rc_idx, real_coords_single_point);
119 }
120 assert(actual_multiplicity > 0);
121 if (actual_multiplicity != 1)
122 {
123 INFO(
124 "Found more then one cell (namely {}) for point #{} "
125 "(coordinates: {})",
126 actual_multiplicity, rc_idx, real_coords_single_point);
127 }
128
129 // Convert to OGS
130 std::unique_ptr<MeshLib::Mesh> ogs_mesh(
132 filtered_bulk_mesh, "filtered_bulk_mesh"));
133
134 auto const* bulk_element_ids = MeshLib::bulkElementIDs(*ogs_mesh);
135
136 auto const& elements = ogs_mesh->getElements();
137
138 // Compute natural coordinates
139 // Found a solution, no need to test other elements ignoring
140 // multiplicity.
141 constexpr std::size_t elt_idx = 0;
142 auto const& element = *elements[elt_idx];
143 auto const bulk_element_id = bulk_element_ids->getComponent(elt_idx, 0);
144
145 auto const& solver = SolverRegistry::getFor(element);
146 auto const opt_natural_coords = solver.solve(
147 element, real_coords_single_point, max_iter, real_coords_tolerance);
148
149 result.append(opt_natural_coords, real_coords_single_point,
150 bulk_element_id, rc_idx);
151 }
152
153 return result.finished();
154}
static MeshLib::Mesh * convertUnstructuredGrid(vtkUnstructuredGrid *grid, bool const compute_element_neighbors=false, std::string const &mesh_name="vtkUnstructuredGrid")
Converts a vtkUnstructuredGrid object to a Mesh.
PropertyVector< std::size_t > const * bulkElementIDs(Mesh const &mesh)
Definition Mesh.cpp:301

References ApplicationUtils::ComputeNaturalCoordsIntermediateResult::append(), MeshLib::bulkElementIDs(), MeshLib::VtkMeshConverter::convertUnstructuredGrid(), ApplicationUtils::FindCellsForPoints::find(), ApplicationUtils::ComputeNaturalCoordsIntermediateResult::finished(), INFO(), ApplicationUtils::FindCellsForPoints::initialize(), and OGS_FATAL.

◆ computePartitionIDPerElement()

std::vector< std::vector< std::size_t > > ApplicationUtils::computePartitionIDPerElement ( std::vector< std::size_t > const & node_partition_map,
std::vector< MeshLib::Element * > const & elements,
std::span< std::size_t const > const bulk_node_ids )

Definition at line 568 of file NodeWiseMeshPartitioner.cpp.

572{
573 auto node_partition_ids = ranges::views::transform(
574 [&](MeshLib::Element const* const element)
575 {
576 auto node_lookup = ranges::views::transform(
577 [&](std::size_t const i)
578 { return node_partition_map[bulk_node_ids[i]]; });
579
580 return element->nodes() | MeshLib::views::ids | node_lookup |
581 ranges::to<std::vector>;
582 });
583
584 return elements | node_partition_ids | ranges::to<std::vector>;
585}
constexpr std::span< Node *const > nodes() const
Span of element's nodes, their pointers actually.
Definition Element.h:74
constexpr ranges::views::view_closure ids
For an element of a range view return its id.
Definition Mesh.h:227

References MeshLib::views::ids, and MeshLib::Element::nodes().

Referenced by partitionMesh().

◆ computePartitionOffsets()

PartitionOffsets ApplicationUtils::computePartitionOffsets ( Partition const & partition)

Definition at line 1038 of file NodeWiseMeshPartitioner.cpp.

1039{
1040 return {static_cast<long>(partition.nodes.size()),
1041 static_cast<long>(partition.regular_elements.size() +
1043 partition.regular_elements)),
1044 static_cast<long>(partition.ghost_elements.size() +
1046 partition.ghost_elements))};
1047}
NodeWiseMeshPartitioner::IntegerType getNumberOfIntegerVariablesOfElements(std::vector< const MeshLib::Element * > const &elements)

References getNumberOfIntegerVariablesOfElements(), ApplicationUtils::Partition::ghost_elements, ApplicationUtils::Partition::nodes, and ApplicationUtils::Partition::regular_elements.

Referenced by writeConfigData().

◆ copyCellPropertyVectorValues()

template<typename T >
std::size_t ApplicationUtils::copyCellPropertyVectorValues ( Partition const & p,
std::size_t const offset,
MeshLib::PropertyVector< T > const & pv,
MeshLib::PropertyVector< T > & partitioned_pv )

Copies the properties from global property vector pv to the partition-local one partitioned_pv. Regular elements' and ghost elements' values are copied.

Definition at line 204 of file NodeWiseMeshPartitioner.cpp.

209{
210 std::size_t const n_regular(p.regular_elements.size());
211 auto const n_components = pv.getNumberOfGlobalComponents();
212 for (std::size_t i = 0; i < n_regular; ++i)
213 {
214 const auto id = p.regular_elements[i]->getID();
215 std::copy_n(&pv[n_components * id], n_components,
216 &partitioned_pv[offset + n_components * i]);
217 }
218
219 std::size_t const n_ghost(p.ghost_elements.size());
220 for (std::size_t i = 0; i < n_ghost; ++i)
221 {
222 const auto id = p.ghost_elements[i]->getID();
223 std::copy_n(&pv[n_components * id], n_components,
224 &partitioned_pv[offset + n_components * (n_regular + i)]);
225 }
226 return n_components * (n_regular + n_ghost);
227}

References MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), ApplicationUtils::Partition::ghost_elements, and ApplicationUtils::Partition::regular_elements.

Referenced by copyPropertyVector().

◆ copyFieldPropertyDataToPartitions()

template<typename T >
std::size_t ApplicationUtils::copyFieldPropertyDataToPartitions ( MeshLib::Properties const & properties,
Partition const & p,
std::size_t const id_offset_partition,
std::vector< std::size_t > const & element_ip_data_offsets,
MeshLib::PropertyVector< T > const & pv,
MeshLib::PropertyVector< T > & partitioned_pv )

Copies the data from the property vector pv belonging to the given Partition p to the property vector partitioned_pv. partitioned_pv is ordered by partition. Regular elements' and ghost elements' values are copied.

Definition at line 234 of file NodeWiseMeshPartitioner.cpp.

241{
242 // Special field data such as OGS_VERSION, IntegrationPointMetaData,
243 // etc., which are not "real" integration points, are copied "as is"
244 // (i.e. fully) for every partition.
245 if (pv.getPropertyName().find("_ip") == std::string::npos)
246 {
247 std::copy_n(&pv[0], pv.size(), &partitioned_pv[id_offset_partition]);
248 return pv.size();
249 }
250
251 auto const n_components = pv.getNumberOfGlobalComponents();
252
253 std::size_t id_offset = 0;
254
255 auto const ip_meta_data = MeshLib::getIntegrationPointMetaDataSingleField(
257 auto copyFieldData =
258 [&](std::vector<const MeshLib::Element*> const& elements)
259 {
260 for (auto const element : elements)
261 {
262 int const number_of_element_field_data =
264 *element) *
265 n_components;
266 // The original element ID is not changed.
267 auto const element_id = element->getID();
268 int const begin_pos = element_ip_data_offsets[element_id];
269 int const end_pos = element_ip_data_offsets[element_id + 1];
270
271 std::copy(pv.begin() + begin_pos, pv.begin() + end_pos,
272 &partitioned_pv[id_offset + id_offset_partition]);
273 id_offset += number_of_element_field_data;
274 }
275 };
276
277 copyFieldData(p.regular_elements);
278 copyFieldData(p.ghost_elements);
279
280 return id_offset;
281}
std::string const & getPropertyName() const
constexpr std::size_t size() const
constexpr PROP_VAL_TYPE * begin()

References MeshLib::PropertyVector< T >::begin(), MeshLib::getIntegrationPointMetaData(), MeshLib::getIntegrationPointMetaDataSingleField(), MeshToolsLib::getNumberOfElementIntegrationPoints(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::PropertyVectorBase::getPropertyName(), ApplicationUtils::Partition::ghost_elements, ApplicationUtils::Partition::regular_elements, and MeshLib::PropertyVector< T >::size().

Referenced by copyPropertyVector().

◆ copyNodePropertyVectorValues()

template<typename T >
std::size_t ApplicationUtils::copyNodePropertyVectorValues ( Partition const & p,
std::size_t const offset,
MeshLib::PropertyVector< T > const & pv,
MeshLib::PropertyVector< T > & partitioned_pv )

Copies the properties from global property vector pv to the partition-local one partitioned_pv.

Definition at line 182 of file NodeWiseMeshPartitioner.cpp.

187{
188 auto const& nodes = p.nodes;
189 auto const nnodes = nodes.size();
190 auto const n_components = pv.getNumberOfGlobalComponents();
191 for (std::size_t i = 0; i < nnodes; ++i)
192 {
193 const auto global_id = nodes[i]->getID();
194 std::copy_n(&pv[n_components * global_id], n_components,
195 &partitioned_pv[offset + n_components * i]);
196 }
197 return n_components * nnodes;
198}

References MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), and ApplicationUtils::Partition::nodes.

Referenced by copyPropertyVector().

◆ copyPropertyVector()

template<typename T >
bool ApplicationUtils::copyPropertyVector ( std::vector< MeshLib::Element * > const & global_mesh_elements,
MeshLib::Properties & partitioned_properties,
MeshLib::Properties const & properties,
std::vector< Partition > const & partitions,
MeshLib::PropertyVector< T > const *const pv,
std::map< MeshLib::MeshItemType, std::size_t > const & total_number_of_tuples )

Definition at line 332 of file NodeWiseMeshPartitioner.cpp.

339{
340 if (pv == nullptr)
341 {
342 return false;
343 }
344 auto const item_type = pv->getMeshItemType();
345
346 std::size_t partitioned_pv_size = total_number_of_tuples.at(item_type) *
348
349 std::vector<std::size_t> element_ip_data_offsets;
351 {
352 // Special field data such as OGS_VERSION, IntegrationPointMetaData,
353 // etc., which are not "real" integration points, are copied "as is"
354 // (i.e. fully) for every partition.
355 if (pv->getPropertyName().find("_ip") == std::string::npos)
356 {
357 partitioned_pv_size = pv->size() * partitions.size();
358 }
359
360 element_ip_data_offsets =
362 global_mesh_elements, *pv, properties);
363 }
364
365 auto partitioned_pv = partitioned_properties.createNewPropertyVector<T>(
366 pv->getPropertyName(), pv->getMeshItemType(),
368 if (partitioned_pv == nullptr)
369 {
370 OGS_FATAL(
371 "Could not create partitioned property vector {:s} for {} data "
372 "array.",
374 }
375 partitioned_pv->resize(partitioned_pv_size);
376
377 auto copy_property_vector_values =
378 [&](Partition const& p, std::size_t offset)
379 {
381 {
382 return copyFieldPropertyDataToPartitions(properties, p, offset,
383 element_ip_data_offsets,
384 *pv, *partitioned_pv);
385 }
386
387 if (item_type == MeshLib::MeshItemType::Node)
388 {
389 return copyNodePropertyVectorValues(p, offset, *pv,
390 *partitioned_pv);
391 }
392 if (item_type == MeshLib::MeshItemType::Cell)
393 {
394 return copyCellPropertyVectorValues(p, offset, *pv,
395 *partitioned_pv);
396 }
397
398 OGS_FATAL(
399 "Copying of property vector values for mesh item type {:s} is not "
400 "implemented.",
401 toString(item_type));
402 };
403
404 std::size_t position_offset(0);
405 for (auto p : partitions)
406 {
407 position_offset += copy_property_vector_values(p, position_offset);
408 }
409 return true;
410}
MeshItemType getMeshItemType() const
std::size_t copyCellPropertyVectorValues(Partition const &p, std::size_t const offset, MeshLib::PropertyVector< T > const &pv, MeshLib::PropertyVector< T > &partitioned_pv)
std::size_t copyFieldPropertyDataToPartitions(MeshLib::Properties const &properties, Partition const &p, std::size_t const id_offset_partition, std::vector< std::size_t > const &element_ip_data_offsets, MeshLib::PropertyVector< T > const &pv, MeshLib::PropertyVector< T > &partitioned_pv)
std::size_t copyNodePropertyVectorValues(Partition const &p, std::size_t const offset, MeshLib::PropertyVector< T > const &pv, MeshLib::PropertyVector< T > &partitioned_pv)
static constexpr char const * toString(const MeshItemType t)
Returns a char array for a specific MeshItemType.
Definition MeshEnums.h:36
std::vector< std::size_t > getIntegrationPointDataOffsetsOfMeshElements(std::vector< MeshLib::Element * > const &mesh_elements, MeshLib::PropertyVectorBase const &pv, MeshLib::Properties const &properties)
const char * toString(mgis::behaviour::Behaviour::Kinematic kin)

References MeshLib::Cell, copyCellPropertyVectorValues(), copyFieldPropertyDataToPartitions(), copyNodePropertyVectorValues(), MeshLib::Properties::createNewPropertyVector(), MeshToolsLib::getIntegrationPointDataOffsetsOfMeshElements(), MeshLib::PropertyVectorBase::getMeshItemType(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::PropertyVectorBase::getPropertyName(), MeshLib::IntegrationPoint, MeshLib::Node, OGS_FATAL, MeshLib::PropertyVector< T >::size(), and MeshLib::toString().

Referenced by partitionProperties().

◆ determineAndAppendGhostNodesToPartitions()

void ApplicationUtils::determineAndAppendGhostNodesToPartitions ( std::vector< Partition > & partitions,
MeshLib::Mesh const & mesh,
std::vector< std::size_t > const & nodes_partition_ids,
std::span< std::size_t const > const node_id_mapping )

Definition at line 670 of file NodeWiseMeshPartitioner.cpp.

674{
675 for (std::size_t part_id = 0; part_id < partitions.size(); part_id++)
676 {
677 auto& partition = partitions[part_id];
678 std::vector<MeshLib::Node*> base_ghost_nodes;
679 std::vector<MeshLib::Node*> higher_order_ghost_nodes;
680 std::tie(base_ghost_nodes, higher_order_ghost_nodes) =
682 part_id, mesh.getNodes(), partition.ghost_elements,
683 nodes_partition_ids, mesh, node_id_mapping);
684
685 std::copy(begin(base_ghost_nodes), end(base_ghost_nodes),
686 std::back_inserter(partition.nodes));
687
688 partition.number_of_base_nodes =
689 partition.number_of_regular_base_nodes + base_ghost_nodes.size();
690
691 std::copy(begin(higher_order_ghost_nodes),
692 end(higher_order_ghost_nodes),
693 std::back_inserter(partition.nodes));
694 }
695}
std::tuple< std::vector< MeshLib::Node * >, std::vector< MeshLib::Node * > > findGhostNodesInPartition(std::size_t const part_id, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element const * > const &ghost_elements, std::vector< std::size_t > const &partition_ids, MeshLib::Mesh const &mesh, std::span< std::size_t const > const node_id_mapping)

References findGhostNodesInPartition(), and MeshLib::Mesh::getNodes().

Referenced by partitionMesh().

◆ distributeElementsIntoPartitions()

void ApplicationUtils::distributeElementsIntoPartitions ( std::vector< Partition > & partitions,
MeshLib::Mesh const & mesh,
std::vector< std::vector< std::size_t > > const & partition_ids_per_element )

Definition at line 636 of file NodeWiseMeshPartitioner.cpp.

640{
641 for (auto const& element : mesh.getElements())
642 {
643 auto const element_id = element->getID();
644 auto node_partition_ids = partition_ids_per_element[element_id];
645 // make partition ids unique
646 std::sort(node_partition_ids.begin(), node_partition_ids.end());
647 auto last =
648 std::unique(node_partition_ids.begin(), node_partition_ids.end());
649 node_partition_ids.erase(last, node_partition_ids.end());
650
651 // all element nodes belong to the same partition => regular element
652 if (node_partition_ids.size() == 1)
653 {
654 partitions[node_partition_ids[0]].regular_elements.push_back(
655 element);
656 }
657 else
658 {
659 for (auto const partition_id : node_partition_ids)
660 {
661 partitions[partition_id].ghost_elements.push_back(element);
662 }
663 }
664 }
665}

References MeshLib::Mesh::getElements().

Referenced by partitionMesh().

◆ distributeNodesToPartitions()

void ApplicationUtils::distributeNodesToPartitions ( std::vector< Partition > & partitions,
std::vector< std::size_t > const & nodes_partition_ids,
std::vector< MeshLib::Node * > const & nodes,
std::span< std::size_t const > const bulk_node_ids )

Definition at line 587 of file NodeWiseMeshPartitioner.cpp.

592{
593 for (auto const* const node : nodes)
594 {
595 partitions[nodes_partition_ids[bulk_node_ids[node->getID()]]]
596 .nodes.push_back(node);
597 }
598}

Referenced by partitionMesh().

◆ enumerateLocalNodeIds()

std::unordered_map< std::size_t, long > ApplicationUtils::enumerateLocalNodeIds ( std::vector< MeshLib::Node const * > const & nodes)

Generates a mapping of given node ids to a new local (renumbered) node ids.

Definition at line 1135 of file NodeWiseMeshPartitioner.cpp.

1137{
1138 std::unordered_map<std::size_t, long> local_ids;
1139 local_ids.reserve(nodes.size());
1140
1141 long local_node_id = 0;
1142 for (const auto* node : nodes)
1143 {
1144 local_ids[node->getID()] = local_node_id++;
1145 }
1146 return local_ids;
1147}

Referenced by writeElements().

◆ findGhostNodesInPartition()

std::tuple< std::vector< MeshLib::Node * >, std::vector< MeshLib::Node * > > ApplicationUtils::findGhostNodesInPartition ( std::size_t const part_id,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element const * > const & ghost_elements,
std::vector< std::size_t > const & partition_ids,
MeshLib::Mesh const & mesh,
std::span< std::size_t const > const node_id_mapping )

Prerequisite: the ghost elements has to be found Finds ghost nodes and non-linear element ghost nodes by walking over ghost elements.

Definition at line 137 of file NodeWiseMeshPartitioner.cpp.

144{
145 std::vector<MeshLib::Node*> base_ghost_nodes;
146 std::vector<MeshLib::Node*> higher_order_ghost_nodes;
147
148 std::vector<bool> is_ghost_node(nodes.size(), false);
149 for (const auto* ghost_elem : ghost_elements)
150 {
151 for (unsigned i = 0; i < ghost_elem->getNumberOfNodes(); i++)
152 {
153 auto const& n = ghost_elem->getNode(i);
154 auto const node_id = n->getID();
155 if (is_ghost_node[node_id])
156 {
157 continue;
158 }
159
160 if (partitionLookup(node_id, partition_ids, node_id_mapping) !=
161 part_id)
162 {
163 if (isBaseNode(*n, mesh.getElementsConnectedToNode(*n)))
164 {
165 base_ghost_nodes.push_back(nodes[node_id]);
166 }
167 else
168 {
169 higher_order_ghost_nodes.push_back(nodes[node_id]);
170 }
171 is_ghost_node[node_id] = true;
172 }
173 }
174 }
175 return std::tuple<std::vector<MeshLib::Node*>, std::vector<MeshLib::Node*>>{
176 base_ghost_nodes, higher_order_ghost_nodes};
177}

References MeshLib::Mesh::getElementsConnectedToNode(), and partitionLookup().

Referenced by determineAndAppendGhostNodesToPartitions().

◆ getElementIntegerVariables()

void ApplicationUtils::getElementIntegerVariables ( const MeshLib::Element & elem,
const std::unordered_map< std::size_t, long > & local_node_ids,
std::vector< long > & elem_info,
long & counter )

Get integer variables, which are used to define an element

Parameters
elemElement
local_node_idsLocal node indices of a partition
elem_infoA vector holds all integer variables of element definitions
counterRecorder of the number of integer variables.

Definition at line 1114 of file NodeWiseMeshPartitioner.cpp.

1119{
1120 constexpr unsigned mat_id =
1121 0; // TODO: Material ID to be set from the mesh data
1122 const long nn = elem.getNumberOfNodes();
1123 elem_info[counter++] = mat_id;
1124 elem_info[counter++] = static_cast<long>(elem.getCellType());
1125 elem_info[counter++] = nn;
1126
1127 for (long i = 0; i < nn; i++)
1128 {
1129 auto const& n = *elem.getNode(i);
1130 elem_info[counter++] = local_node_ids.at(n.getID());
1131 }
1132}
virtual CellType getCellType() const =0
virtual unsigned getNumberOfNodes() const =0
virtual const Node * getNode(unsigned idx) const =0

References MeshLib::Element::getCellType(), MeshLib::Element::getNode(), and MeshLib::Element::getNumberOfNodes().

Referenced by writeElements().

◆ getNumberOfIntegerVariablesOfElements()

NodeWiseMeshPartitioner::IntegerType ApplicationUtils::getNumberOfIntegerVariablesOfElements ( std::vector< const MeshLib::Element * > const & elements)

Calculate the total number of integer variables of an element vector. Each element has three integer variables for element ID, element type, number of nodes of the element. Therefore the total number of the integers in elements is 3 * elements.size() + sum (number of nodes of each element).

Definition at line 73 of file NodeWiseMeshPartitioner.cpp.

75{
76 return 3 * elements.size() +
77 std::accumulate(begin(elements), end(elements), 0,
78 [](auto const nnodes, auto const* e)
79 { return nnodes + e->getNumberOfNodes(); });
80}

Referenced by computePartitionOffsets(), and ApplicationUtils::Partition::writeConfig().

◆ incrementConfigOffsets()

ConfigOffsets ApplicationUtils::incrementConfigOffsets ( ConfigOffsets const & oldConfig,
PartitionOffsets const & offsets )

Definition at line 1049 of file NodeWiseMeshPartitioner.cpp.

1051{
1052 return {
1053 static_cast<long>(oldConfig.node_rank_offset +
1054 offsets.node * sizeof(MeshLib::IO::NodeData)),
1055 // Offset the ending entry of the element integer variables of
1056 // the non-ghost elements of this partition in the vector of elem_info.
1057 static_cast<long>(oldConfig.element_rank_offset +
1058 offsets.regular_elements * sizeof(long)),
1059
1060 // Offset the ending entry of the element integer variables of
1061 // the ghost elements of this partition in the vector of elem_info.
1062 static_cast<long>(oldConfig.ghost_element_rank_offset +
1063 offsets.ghost_elements * sizeof(long))};
1064}
struct NodeData used for parallel reading and also partitioning
Definition NodeData.h:18

References ApplicationUtils::ConfigOffsets::element_rank_offset, ApplicationUtils::ConfigOffsets::ghost_element_rank_offset, ApplicationUtils::PartitionOffsets::ghost_elements, ApplicationUtils::PartitionOffsets::node, ApplicationUtils::ConfigOffsets::node_rank_offset, and ApplicationUtils::PartitionOffsets::regular_elements.

Referenced by writeConfigData().

◆ markDuplicateGhostCells()

void ApplicationUtils::markDuplicateGhostCells ( MeshLib::Mesh const & mesh,
std::vector< Partition > & partitions )

Definition at line 497 of file NodeWiseMeshPartitioner.cpp.

499{
500 std::vector<bool> cell_visited(mesh.getElements().size(), false);
501
502 for (auto& partition : partitions)
503 {
504 partition.duplicate_ghost_cell.resize(partition.ghost_elements.size(),
505 true);
506
507 for (std::size_t i = 0; i < partition.ghost_elements.size(); i++)
508 {
509 const auto& ghost_element = *partition.ghost_elements[i];
510 if (!cell_visited[ghost_element.getID()])
511 {
512 cell_visited[ghost_element.getID()] = true;
513 partition.duplicate_ghost_cell[i] = false;
514 }
515 }
516 }
517}

References MeshLib::Mesh::getElements().

Referenced by partitionMesh().

◆ partitionLookup()

std::size_t ApplicationUtils::partitionLookup ( std::size_t const & node_id,
std::vector< std::size_t > const & partition_ids,
std::span< std::size_t const > const node_id_mapping )

Definition at line 102 of file NodeWiseMeshPartitioner.cpp.

105{
106 return partition_ids[node_id_mapping[node_id]];
107}

Referenced by findGhostNodesInPartition().

◆ partitionMesh()

void ApplicationUtils::partitionMesh ( std::vector< Partition > & partitions,
MeshLib::Mesh const & mesh,
std::vector< std::size_t > const & nodes_partition_ids,
std::span< std::size_t const > const bulk_node_ids )

Definition at line 697 of file NodeWiseMeshPartitioner.cpp.

701{
702 BaseLib::RunTime run_timer;
703 run_timer.start();
704 auto const partition_ids_per_element = computePartitionIDPerElement(
705 nodes_partition_ids, mesh.getElements(), bulk_node_ids);
706 INFO("partitionMesh(): Partition IDs per element computed in {:g} s",
707 run_timer.elapsed());
708
709 run_timer.start();
710 distributeNodesToPartitions(partitions, nodes_partition_ids,
711 mesh.getNodes(), bulk_node_ids);
712 INFO("partitionMesh(): distribute nodes to partitions took {:g} s",
713 run_timer.elapsed());
714
715 run_timer.start();
717 INFO(
718 "partitionMesh(): sorting [base nodes | higher order nodes] took {:g} "
719 "s",
720 run_timer.elapsed());
721
722 run_timer.start();
723 setNumberOfNodesInPartitions(partitions, mesh);
724 INFO(
725 "partitionMesh(): setting number of nodes and of all mesh base nodes "
726 "took {:g} s",
727 run_timer.elapsed());
728
729 run_timer.start();
730 distributeElementsIntoPartitions(partitions, mesh,
731 partition_ids_per_element);
732 INFO("partitionMesh(): distribute elements into partitions took {:g} s",
733 run_timer.elapsed());
734
735 run_timer.start();
737 partitions, mesh, nodes_partition_ids, bulk_node_ids);
738 INFO("partitionMesh(): determine / append ghost nodes took {:g} s",
739 run_timer.elapsed());
740
741 run_timer.start();
742 markDuplicateGhostCells(mesh, partitions);
743 INFO("partitionMesh(): markDuplicateGhostCells took {:g} s",
744 run_timer.elapsed());
745}
Count the running time.
Definition RunTime.h:29
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:42
void start()
Start the timer.
Definition RunTime.h:32
std::vector< std::vector< std::size_t > > computePartitionIDPerElement(std::vector< std::size_t > const &node_partition_map, std::vector< MeshLib::Element * > const &elements, std::span< std::size_t const > const bulk_node_ids)
void reorderNodesIntoBaseAndHigherOrderNodesPerPartition(std::vector< Partition > &partitions, MeshLib::Mesh const &mesh)
void setNumberOfNodesInPartitions(std::vector< Partition > &partitions, MeshLib::Mesh const &mesh)
void distributeNodesToPartitions(std::vector< Partition > &partitions, std::vector< std::size_t > const &nodes_partition_ids, std::vector< MeshLib::Node * > const &nodes, std::span< std::size_t const > const bulk_node_ids)
void markDuplicateGhostCells(MeshLib::Mesh const &mesh, std::vector< Partition > &partitions)
void distributeElementsIntoPartitions(std::vector< Partition > &partitions, MeshLib::Mesh const &mesh, std::vector< std::vector< std::size_t > > const &partition_ids_per_element)
void determineAndAppendGhostNodesToPartitions(std::vector< Partition > &partitions, MeshLib::Mesh const &mesh, std::vector< std::size_t > const &nodes_partition_ids, std::span< std::size_t const > const node_id_mapping)

References computePartitionIDPerElement(), determineAndAppendGhostNodesToPartitions(), distributeElementsIntoPartitions(), distributeNodesToPartitions(), BaseLib::RunTime::elapsed(), MeshLib::Mesh::getElements(), MeshLib::Mesh::getNodes(), INFO(), markDuplicateGhostCells(), reorderNodesIntoBaseAndHigherOrderNodesPerPartition(), setNumberOfNodesInPartitions(), and BaseLib::RunTime::start().

Referenced by ApplicationUtils::NodeWiseMeshPartitioner::partitionByMETIS(), and ApplicationUtils::NodeWiseMeshPartitioner::partitionOtherMesh().

◆ partitionProperties()

MeshLib::Properties ApplicationUtils::partitionProperties ( std::unique_ptr< MeshLib::Mesh > const & mesh,
std::vector< Partition > & partitions )

Partition existing properties and add vtkGhostType cell data array property.

Creates partitioned mesh properties for nodes and cells.

Definition at line 443 of file NodeWiseMeshPartitioner.cpp.

446{
447 using namespace MeshLib;
448
449 MeshLib::Properties const& properties = mesh->getProperties();
450
451 // Count the number of integration point data of all partitions:
452 setIntegrationPointNumberOfPartition(properties, partitions);
453
454 Properties partitioned_properties;
455 auto count_tuples = [&](MeshItemType const mesh_item_type)
456 {
457 return std::accumulate(
458 begin(partitions), end(partitions), 0,
459 [&](std::size_t const sum, Partition const& p)
460 { return sum + p.numberOfMeshItems(mesh_item_type); });
461 };
462
463 std::map<MeshItemType, std::size_t> const total_number_of_tuples = {
464 {MeshItemType::Cell, count_tuples(MeshItemType::Cell)},
465 {MeshItemType::Node, count_tuples(MeshItemType::Node)},
466 {MeshItemType::IntegrationPoint,
467 count_tuples(MeshItemType::IntegrationPoint)}};
468
469 DBUG(
470 "total number of tuples after partitioning defined for cells is {:d} "
471 "and for nodes {:d} and for integration points {:d}.",
472 total_number_of_tuples.at(MeshItemType::Cell),
473 total_number_of_tuples.at(MeshItemType::Node),
474 total_number_of_tuples.at(MeshItemType::IntegrationPoint));
475
476 // 1 create new PV
477 // 2 resize the PV with total_number_of_tuples
478 // 3 copy the values according to the partition info
480 properties,
481 [&](auto type, auto const property)
482 {
484 mesh->getElements(), partitioned_properties, properties,
485 partitions,
486 dynamic_cast<PropertyVector<decltype(type)> const*>(property),
487 total_number_of_tuples);
488 });
489
490 addVtkGhostTypeProperty(partitioned_properties,
491 partitions,
492 total_number_of_tuples.at(MeshItemType::Cell));
493
494 return partitioned_properties;
495}
bool copyPropertyVector(MeshLib::Properties const &properties, MeshLib::PropertyVectorBase *destination_pv)
Definition PVD2XDMF.cpp:56
void applyToPropertyVectors(Properties const &properties, Function f)
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
Definition Properties.h:33
void addVtkGhostTypeProperty(MeshLib::Properties &partitioned_properties, std::vector< Partition > const &partitions, std::size_t const total_number_of_cells)
void setIntegrationPointNumberOfPartition(MeshLib::Properties const &properties, std::vector< Partition > &partitions)
std::size_t numberOfMeshItems(MeshLib::MeshItemType const item_type) const

References addVtkGhostTypeProperty(), applyToPropertyVectors(), copyPropertyVector(), DBUG(), ApplicationUtils::Partition::numberOfMeshItems(), and setIntegrationPointNumberOfPartition().

Referenced by main(), and ApplicationUtils::NodeWiseMeshPartitioner::partitionByMETIS().

◆ readMetisData()

std::vector< std::size_t > ApplicationUtils::readMetisData ( const std::string & file_name_base,
long number_of_partitions,
std::size_t number_of_nodes )

Read metis data

Parameters
file_name_baseThe prefix of the filename.
number_of_partitionsThe number is used to compose the full filename and forms the postfix.
number_of_nodesExpected/required number of nodes to be read.

Definition at line 45 of file Metis.cpp.

48{
49 const std::string npartitions_str = std::to_string(number_of_partitions);
50
51 // Read partitioned mesh data from METIS
52 const std::string fname_parts =
53 file_name_base + ".mesh.npart." + npartitions_str;
54
55 std::ifstream npart_in(fname_parts);
56 if (!npart_in.is_open())
57 {
59 "Error: cannot open file {:s}. It may not exist!\n"
60 "Run mpmetis beforehand or use option -m",
61 fname_parts.data());
62 }
63
64 std::vector<std::size_t> partition_ids(number_of_nodes);
65
66 std::size_t counter = 0;
67 while (!npart_in.eof())
68 {
69 npart_in >> partition_ids[counter++] >> std::ws;
70 if (counter == number_of_nodes)
71 {
72 break;
73 }
74 }
75
76 if (npart_in.bad())
77 {
78 OGS_FATAL("Error while reading file {:s}.", fname_parts.data());
79 }
80
81 if (counter != number_of_nodes)
82 {
83 OGS_FATAL("Error: data in {:s} are less than expected.",
84 fname_parts.data());
85 }
86
87 return partition_ids;
88}

References OGS_FATAL.

Referenced by main().

◆ removeMetisPartitioningFiles()

void ApplicationUtils::removeMetisPartitioningFiles ( std::string const & file_name_base,
long number_of_partitions )

Removes the F.mesh.npart.P and F.mesh.epart.P files, where F is file name base and P is the number of partitions.

Definition at line 90 of file Metis.cpp.

92{
93 const std::string npartitions_str = std::to_string(number_of_partitions);
94
95 std::remove((file_name_base + ".mesh.npart." + npartitions_str).c_str());
96 std::remove((file_name_base + ".mesh.epart." + npartitions_str).c_str());
97}

Referenced by main().

◆ reorderNodesIntoBaseAndHigherOrderNodes()

void ApplicationUtils::reorderNodesIntoBaseAndHigherOrderNodes ( Partition & partition,
MeshLib::Mesh const & mesh )

Definition at line 600 of file NodeWiseMeshPartitioner.cpp.

602{
603 std::vector<MeshLib::Node const*> higher_order_nodes;
604 // after splitIntoBaseAndHigherOrderNodes() partition.nodes contains only
605 // base nodes
606 std::tie(partition.nodes, higher_order_nodes) =
608 partition.number_of_regular_base_nodes = partition.nodes.size();
609 std::copy(begin(higher_order_nodes), end(higher_order_nodes),
610 std::back_inserter(partition.nodes));
611 partition.number_of_regular_nodes = partition.nodes.size();
612}
std::pair< std::vector< MeshLib::Node const * >, std::vector< MeshLib::Node const * > > splitIntoBaseAndHigherOrderNodes(std::vector< MeshLib::Node const * > const &nodes, MeshLib::Mesh const &mesh)
std::vector< MeshLib::Node const * > nodes
nodes.

References ApplicationUtils::Partition::nodes, ApplicationUtils::Partition::number_of_regular_base_nodes, ApplicationUtils::Partition::number_of_regular_nodes, and splitIntoBaseAndHigherOrderNodes().

Referenced by reorderNodesIntoBaseAndHigherOrderNodesPerPartition().

◆ reorderNodesIntoBaseAndHigherOrderNodesPerPartition()

void ApplicationUtils::reorderNodesIntoBaseAndHigherOrderNodesPerPartition ( std::vector< Partition > & partitions,
MeshLib::Mesh const & mesh )

Definition at line 614 of file NodeWiseMeshPartitioner.cpp.

616{
617 for (auto& partition : partitions)
618 {
620 }
621}
void reorderNodesIntoBaseAndHigherOrderNodes(Partition &partition, MeshLib::Mesh const &mesh)

References reorderNodesIntoBaseAndHigherOrderNodes().

Referenced by partitionMesh().

◆ setIntegrationPointNumberOfPartition()

void ApplicationUtils::setIntegrationPointNumberOfPartition ( MeshLib::Properties const & properties,
std::vector< Partition > & partitions )

Definition at line 283 of file NodeWiseMeshPartitioner.cpp.

285{
286 auto const& opt_ip_meta_data_all =
288 for (auto const& [name, property] : properties)
289 {
290 auto const item_type = property->getMeshItemType();
291
293 {
294 continue;
295 }
296
297 // For special field data such as OGS_VERSION, IntegrationPointMetaData,
298 // etc., which are not "real" integration points:
299 if (property->getPropertyName().find("_ip") == std::string::npos)
300 {
301 continue;
302 }
303
304 auto const& ip_meta_data =
306 opt_ip_meta_data_all, property->getPropertyName());
307 auto countIntegrationPoints =
308 [&](std::vector<const MeshLib::Element*> const& elements)
309 {
310 std::size_t counter = 0;
311 for (auto const element : elements)
312 {
313 int const number_of_integration_points =
315 ip_meta_data, *element);
316 counter += number_of_integration_points;
317 }
318 return counter;
319 };
320
321 for (auto& p : partitions)
322 {
323 p.number_of_integration_points =
324 countIntegrationPoints(p.regular_elements) +
325 countIntegrationPoints(p.ghost_elements);
326 }
327 return;
328 }
329}

References MeshLib::getIntegrationPointMetaData(), MeshLib::getIntegrationPointMetaDataSingleField(), MeshToolsLib::getNumberOfElementIntegrationPoints(), and MeshLib::IntegrationPoint.

Referenced by partitionProperties().

◆ setNumberOfNodesInPartitions()

void ApplicationUtils::setNumberOfNodesInPartitions ( std::vector< Partition > & partitions,
MeshLib::Mesh const & mesh )

Definition at line 623 of file NodeWiseMeshPartitioner.cpp.

625{
626 auto const number_of_mesh_base_nodes = mesh.computeNumberOfBaseNodes();
627 auto const number_of_mesh_all_nodes = mesh.getNumberOfNodes();
628 for (auto& partition : partitions)
629 {
630 partition.number_of_regular_nodes = partition.nodes.size();
631 partition.number_of_mesh_base_nodes = number_of_mesh_base_nodes;
632 partition.number_of_mesh_all_nodes = number_of_mesh_all_nodes;
633 }
634}

References MeshLib::Mesh::computeNumberOfBaseNodes(), and MeshLib::Mesh::getNumberOfNodes().

Referenced by partitionMesh().

◆ splitIntoBaseAndHigherOrderNodes()

std::pair< std::vector< MeshLib::Node const * >, std::vector< MeshLib::Node const * > > ApplicationUtils::splitIntoBaseAndHigherOrderNodes ( std::vector< MeshLib::Node const * > const & nodes,
MeshLib::Mesh const & mesh )

Definition at line 110 of file NodeWiseMeshPartitioner.cpp.

112{
113 // Space for resulting vectors.
114 std::vector<MeshLib::Node const*> base_nodes;
115 // if linear mesh, then one reallocation, no realloc for higher order
116 // elements meshes.
117 base_nodes.reserve(nodes.size() / 2);
118 std::vector<MeshLib::Node const*> higher_order_nodes;
119 // if linear mesh, then wasted space, good estimate for quadratic
120 // order mesh, and realloc needed for higher order element meshes.
121 higher_order_nodes.reserve(nodes.size() / 2);
122
123 // Split the nodes into base nodes and extra nodes.
124 std::partition_copy(
125 begin(nodes), end(nodes), std::back_inserter(base_nodes),
126 std::back_inserter(higher_order_nodes),
127 [&](MeshLib::Node const* const n)
128 { return isBaseNode(*n, mesh.getElementsConnectedToNode(*n)); });
129
130 return {base_nodes, higher_order_nodes};
131}

References MeshLib::Mesh::getElementsConnectedToNode().

Referenced by reorderNodesIntoBaseAndHigherOrderNodes().

◆ toVTKGrid()

vtkSmartPointer< vtkUnstructuredGrid > ApplicationUtils::toVTKGrid ( ComputeNaturalCoordsResult const & result)

Creates a mesh from the points described by the passed result.

The points 2n and 2n+1 will be connected by a line element that could represent an anchor in an FEM model for instance.

Definition at line 191 of file ComputeNaturalCoordsAlgorithm.h.

193{
194 INFO("converting points");
195 auto const n_pts = result.natural_coords.rows();
196 if (n_pts == 0)
197 {
198 OGS_FATAL(
199 "No point was found in the mesh. Please check whether all anchors "
200 "are within the model region.");
201 }
202 else if (n_pts == 1)
203 {
204 OGS_FATAL(
205 "Only one point was found in the mesh. Please check whether all "
206 "anchors are within the model region.");
207 }
208 else if (n_pts % 2 != 0)
209 {
210 // number should be even if multiplicity is ignored
211 OGS_FATAL(
212 "Number of points is not even. Anchors are believed to consist of "
213 "a start and an end point.");
214 }
215
216 vtkNew<vtkUnstructuredGrid> grid;
217
218 // Points ------------------------------------------------------------------
219 vtkNew<vtkPoints> points;
220 points->SetNumberOfPoints(n_pts);
221
222 auto const& css = result.real_coords;
223 for (Eigen::Index i = 0; i < css.rows(); ++i)
224 {
225 points->SetPoint(i, css(i, 0), css(i, 1), css(i, 2));
226
227 if ((i % 2) == 1)
228 {
229 vtkNew<vtkLine> line;
230 line->GetPointIds()->SetId(0, i - 1);
231 line->GetPointIds()->SetId(1, i);
232 grid->InsertNextCell(line->GetCellType(), line->GetPointIds());
233 }
234 }
235
236 grid->SetPoints(points);
237
238 // Point data --------------------------------------------------------------
239 addPointData<double>(grid, "natural_coordinates", result.natural_coords);
240 addPointData<std::size_t>(grid, "bulk_element_ids",
241 result.bulk_element_ids.cast<std::size_t>());
242 addPointData<std::size_t>(grid, "point_cloud_node_ids",
243 result.point_cloud_node_ids.cast<std::size_t>());
244
245 return grid;
246}

References addPointData(), ApplicationUtils::ComputeNaturalCoordsResult::bulk_element_ids, INFO(), ApplicationUtils::ComputeNaturalCoordsResult::natural_coords, OGS_FATAL, ApplicationUtils::ComputeNaturalCoordsResult::point_cloud_node_ids, and ApplicationUtils::ComputeNaturalCoordsResult::real_coords.

◆ writeConfigData()

std::tuple< std::vector< long >, std::vector< long > > ApplicationUtils::writeConfigData ( const std::string & file_name_base,
std::vector< Partition > const & partitions )

Write the configuration data of the partition data in binary files.

Returns
a pair of vectors for:
  1. The number of all non-ghost element integer variables for each partition.
  2. The number of all ghost element integer variables for each partition.

Definition at line 1071 of file NodeWiseMeshPartitioner.cpp.

1073{
1074 auto const file_name_cfg = file_name_base + "_partitioned_msh_cfg" +
1075 std::to_string(partitions.size()) + ".bin";
1076 std::ofstream of_bin_cfg(file_name_cfg, std::ios::binary);
1077 if (!of_bin_cfg)
1078 {
1079 OGS_FATAL("Could not open file '{:s}' for output.", file_name_cfg);
1080 }
1081
1082 std::vector<long> partitions_element_offsets;
1083 partitions_element_offsets.reserve(partitions.size());
1084 std::vector<long> partitions_ghost_element_offsets;
1085 partitions_ghost_element_offsets.reserve(partitions.size());
1086
1087 ConfigOffsets config_offsets = {0, 0, 0}; // 0 for first partition.
1088 for (const auto& partition : partitions)
1089 {
1090 partition.writeConfig(of_bin_cfg);
1091
1092 config_offsets.writeConfig(of_bin_cfg);
1093 auto const& partition_offsets = computePartitionOffsets(partition);
1094 config_offsets =
1095 incrementConfigOffsets(config_offsets, partition_offsets);
1096
1097 partitions_element_offsets.push_back(
1098 partition_offsets.regular_elements);
1099 partitions_ghost_element_offsets.push_back(
1100 partition_offsets.ghost_elements);
1101 }
1102
1103 return std::make_tuple(partitions_element_offsets,
1104 partitions_ghost_element_offsets);
1105}
ConfigOffsets incrementConfigOffsets(ConfigOffsets const &oldConfig, PartitionOffsets const &offsets)
PartitionOffsets computePartitionOffsets(Partition const &partition)

References computePartitionOffsets(), incrementConfigOffsets(), OGS_FATAL, and ApplicationUtils::ConfigOffsets::writeConfig().

Referenced by ApplicationUtils::NodeWiseMeshPartitioner::write(), and ApplicationUtils::NodeWiseMeshPartitioner::writeOtherMesh().

◆ writeElements()

void ApplicationUtils::writeElements ( std::string const & file_name_base,
std::vector< Partition > const & partitions,
std::vector< long > const & regular_element_offsets,
std::vector< long > const & ghost_element_offsets )

Write the element integer variables of all partitions into binary files.

Parameters
file_name_baseThe prefix of the file name.
partitionsPartitions vector.
regular_element_offsetsThe numbers of all non-ghost element integer variables of each partitions.
ghost_element_offsetsThe numbers of all ghost element

Definition at line 1155 of file NodeWiseMeshPartitioner.cpp.

1159{
1160 const std::string npartitions_str = std::to_string(partitions.size());
1161
1162 auto const file_name_ele =
1163 file_name_base + "_partitioned_msh_ele" + npartitions_str + ".bin";
1164 std::ofstream element_info_os(file_name_ele, std::ios::binary);
1165 if (!element_info_os)
1166 {
1167 OGS_FATAL("Could not open file '{:s}' for output.", file_name_ele);
1168 }
1169
1170 auto const file_name_ele_g =
1171 file_name_base + "_partitioned_msh_ele_g" + npartitions_str + ".bin";
1172 std::ofstream ghost_element_info_os(file_name_ele_g, std::ios::binary);
1173 if (!ghost_element_info_os)
1174 {
1175 OGS_FATAL("Could not open file '{:s}' for output.", file_name_ele_g);
1176 }
1177
1178 for (std::size_t i = 0; i < partitions.size(); i++)
1179 {
1180 const auto& partition = partitions[i];
1181 auto const local_node_ids = enumerateLocalNodeIds(partition.nodes);
1182
1183 // Vector containing the offsets of the regular elements of this
1184 // partition
1185 std::vector<long> ele_info(regular_element_offsets[i]);
1186
1187 auto writeElementData =
1188 [&local_node_ids](
1189 std::vector<MeshLib::Element const*> const& elements,
1190 long const element_offsets,
1191 std::ofstream& output_stream)
1192 {
1193 long counter = elements.size();
1194 std::vector<long> ele_info(element_offsets);
1195
1196 for (std::size_t j = 0; j < elements.size(); j++)
1197 {
1198 const auto* elem = elements[j];
1199 ele_info[j] = counter;
1200 getElementIntegerVariables(*elem, local_node_ids, ele_info,
1201 counter);
1202 }
1203 // Write vector data of regular elements
1204 output_stream.write(reinterpret_cast<const char*>(ele_info.data()),
1205 ele_info.size() * sizeof(long));
1206 };
1207
1208 // regular elements.
1209 writeElementData(partition.regular_elements, regular_element_offsets[i],
1210 element_info_os);
1211 // Ghost elements
1212 writeElementData(partition.ghost_elements, ghost_element_offsets[i],
1213 ghost_element_info_os);
1214 }
1215}
std::unordered_map< std::size_t, long > enumerateLocalNodeIds(std::vector< MeshLib::Node const * > const &nodes)
Generates a mapping of given node ids to a new local (renumbered) node ids.
void getElementIntegerVariables(const MeshLib::Element &elem, const std::unordered_map< std::size_t, long > &local_node_ids, std::vector< long > &elem_info, long &counter)

References enumerateLocalNodeIds(), getElementIntegerVariables(), and OGS_FATAL.

Referenced by ApplicationUtils::NodeWiseMeshPartitioner::write(), and ApplicationUtils::NodeWiseMeshPartitioner::writeOtherMesh().

◆ writeMETIS()

void ApplicationUtils::writeMETIS ( std::vector< MeshLib::Element * > const & elements,
const std::string & file_name )

Write elements as METIS graph file

Parameters
elementsThe mesh elements.
file_nameFile name with an extension of mesh.

Definition at line 19 of file Metis.cpp.

21{
22 std::ofstream os(file_name, std::ios::trunc);
23 if (!os.is_open())
24 {
25 OGS_FATAL("Error: cannot open file {:s}.", file_name.data());
26 }
27
28 if (!os.good())
29 {
30 OGS_FATAL("Error: Cannot write in file {:s}.", file_name.data());
31 }
32
33 os << elements.size() << " \n";
34 for (const auto* elem : elements)
35 {
36 os << getNodeIndex(*elem, 0) + 1;
37 for (unsigned j = 1; j < elem->getNumberOfNodes(); j++)
38 {
39 os << " " << getNodeIndex(*elem, j) + 1;
40 }
41 os << "\n";
42 }
43}
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition Element.cpp:237

References OGS_FATAL.

Referenced by main().

◆ writeNodes()

void ApplicationUtils::writeNodes ( const std::string & file_name_base,
std::vector< Partition > const & partitions,
std::vector< std::size_t > const & global_node_ids )

Write the nodes of all partitions into a binary file.

Parameters
file_name_baseThe prefix of the file name.
partitionsthe list of partitions
global_node_idsglobal numbering of nodes

Definition at line 1221 of file NodeWiseMeshPartitioner.cpp.

1224{
1225 auto const file_name = file_name_base + "_partitioned_msh_nod" +
1226 std::to_string(partitions.size()) + ".bin";
1227 std::ofstream os(file_name, std::ios::binary);
1228 if (!os)
1229 {
1230 OGS_FATAL("Could not open file '{:s}' for output.", file_name);
1231 }
1232
1233 for (const auto& partition : partitions)
1234 {
1235 partition.writeNodes(os, global_node_ids);
1236 }
1237}

References OGS_FATAL.

Referenced by ApplicationUtils::NodeWiseMeshPartitioner::write(), and ApplicationUtils::NodeWiseMeshPartitioner::writeOtherMesh().

◆ writeProperties()

void ApplicationUtils::writeProperties ( const std::string & file_name_base,
MeshLib::Properties const & partitioned_properties,
std::vector< Partition > const & partitions,
MeshLib::MeshItemType const mesh_item_type )

Definition at line 954 of file NodeWiseMeshPartitioner.cpp.

958{
959 auto const number_of_properties =
960 partitioned_properties.size(mesh_item_type);
961 if (number_of_properties == 0)
962 {
963 return;
964 }
965
966 auto const file_name_infix = toString(mesh_item_type);
967
968 auto const file_name_cfg = file_name_base + "_partitioned_" +
969 file_name_infix + "_properties_cfg" +
970 std::to_string(partitions.size()) + ".bin";
971 std::ofstream out(file_name_cfg, std::ios::binary);
972 if (!out)
973 {
974 OGS_FATAL("Could not open file '{:s}' for output.", file_name_cfg);
975 }
976
977 auto const file_name_val = file_name_base + "_partitioned_" +
978 file_name_infix + "_properties_val" +
979 std::to_string(partitions.size()) + ".bin";
980 std::ofstream out_val(file_name_val, std::ios::binary);
981 if (!out_val)
982 {
983 OGS_FATAL("Could not open file '{:s}' for output.", file_name_val);
984 }
985
986 BaseLib::writeValueBinary(out, number_of_properties);
987
989 partitioned_properties,
990 [&](auto type, auto const& property)
991 {
992 return writePropertyVector<decltype(type)>(
993 dynamic_cast<MeshLib::PropertyVector<decltype(type)> const*>(
994 property),
995 mesh_item_type, out_val, out);
996 });
997
998 unsigned long offset = 0;
999 for (const auto& partition : partitions)
1000 {
1002 offset, static_cast<unsigned long>(
1003 partition.numberOfMeshItems(mesh_item_type))};
1004 DBUG(
1005 "Write meta data for node-based PropertyVector: global offset "
1006 "{:d}, number of tuples {:d}",
1007 pvpmd.offset, pvpmd.number_of_tuples);
1009 offset += pvpmd.number_of_tuples;
1010 }
1011}
void writeValueBinary(std::ostream &out, T const &val)
write value as binary into the given output stream
void writePropertyVectorPartitionMetaData(std::ostream &os, PropertyVectorPartitionMetaData const &pvpmd)

References applyToPropertyVectors(), DBUG(), OGS_FATAL, MeshLib::Properties::size(), writePropertyVector(), MeshLib::IO::writePropertyVectorPartitionMetaData(), and BaseLib::writeValueBinary().

Referenced by ApplicationUtils::NodeWiseMeshPartitioner::write(), and ApplicationUtils::NodeWiseMeshPartitioner::writeOtherMesh().

◆ writePropertyVector()

template<typename T >
bool ApplicationUtils::writePropertyVector ( MeshLib::PropertyVector< T > const *const pv,
MeshLib::MeshItemType const mesh_item_type,
std::ostream & out_val,
std::ostream & out_meta )

Definition at line 929 of file NodeWiseMeshPartitioner.cpp.

932{
933 if (pv == nullptr)
934 {
935 return false;
936 }
937 // skip property of different mesh item type. Return true, because this
938 // operation was successful.
939 if (pv->getMeshItemType() != mesh_item_type)
940 {
941 return true;
942 }
943
945 pvmd.property_name = pv->getPropertyName();
949 writePropertyVectorValues(out_val, *pv);
951 return true;
952}
constexpr std::size_t getNumberOfTuples() const
void writePropertyVectorValues(std::ostream &os, MeshLib::PropertyVector< T > const &pv)
void writePropertyVectorMetaData(std::ostream &os, PropertyVectorMetaData const &pvmd)

References MeshLib::IO::PropertyVectorMetaData::fillPropertyVectorMetaDataTypeInfo(), MeshLib::PropertyVectorBase::getMeshItemType(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::PropertyVector< T >::getNumberOfTuples(), MeshLib::PropertyVectorBase::getPropertyName(), MeshLib::IO::PropertyVectorMetaData::number_of_components, MeshLib::IO::PropertyVectorMetaData::number_of_tuples, MeshLib::IO::PropertyVectorMetaData::property_name, MeshLib::IO::writePropertyVectorMetaData(), and writePropertyVectorValues().

Referenced by writeProperties().

◆ writePropertyVectorValues()

template<typename T >
void ApplicationUtils::writePropertyVectorValues ( std::ostream & os,
MeshLib::PropertyVector< T > const & pv )

Definition at line 922 of file NodeWiseMeshPartitioner.cpp.

924{
925 os.write(reinterpret_cast<const char*>(pv.data()), pv.size() * sizeof(T));
926}
constexpr const PROP_VAL_TYPE * data() const

References MeshLib::PropertyVector< T >::data(), and MeshLib::PropertyVector< T >::size().

Referenced by writePropertyVector().