Loading [MathJax]/extensions/tex2jax.js
OGS
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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::vector< std::size_t > 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::vector< std::size_t > 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::vector< std::size_t > 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::vector< std::size_t > 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::vector< std::size_t > const &node_id_mapping)
 
void partitionMesh (std::vector< Partition > &partitions, MeshLib::Mesh const &mesh, std::vector< std::size_t > const &nodes_partition_ids, std::vector< std::size_t > 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);
419 if (vtk_ghost_type == nullptr)
420 {
421 OGS_FATAL("Could not create vtkGhostType cell data array.");
422 }
423
424 vtk_ghost_type->resize(total_number_of_cells);
425 std::size_t offset = 0;
426 for (auto const& partition : partitions)
427 {
428 offset += partition.regular_elements.size();
429 for (std::size_t i = 0; i < partition.ghost_elements.size(); ++i)
430 {
431 if (partition.duplicate_ghost_cell[i])
432 {
433 (*vtk_ghost_type)[offset + i] |=
434 vtkDataSetAttributes::DUPLICATECELL;
435 }
436 }
437 offset += partition.ghost_elements.size();
438 }
439}
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 518 of file NodeWiseMeshPartitioner.cpp.

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

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::vector< std::size_t > const & bulk_node_ids )

Definition at line 567 of file NodeWiseMeshPartitioner.cpp.

571{
572 auto node_partition_ids = ranges::views::transform(
573 [&](MeshLib::Element const* const element)
574 {
575 auto node_lookup = ranges::views::transform(
576 [&](std::size_t const i)
577 { return node_partition_map[bulk_node_ids[i]]; });
578
579 return element->nodes() | MeshLib::views::ids | node_lookup |
580 ranges::to<std::vector>;
581 });
582
583 return elements | node_partition_ids | ranges::to<std::vector>;
584}
constexpr std::span< Node *const > nodes() const
Span of element's nodes, their pointers actually.
Definition Element.h:72
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 1037 of file NodeWiseMeshPartitioner.cpp.

1038{
1039 return {static_cast<long>(partition.nodes.size()),
1040 static_cast<long>(partition.regular_elements.size() +
1042 partition.regular_elements)),
1043 static_cast<long>(partition.ghost_elements.size() +
1045 partition.ghost_elements))};
1046}
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().

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
std::size_t size() const

References MeshLib::getIntegrationPointMetaData(), MeshLib::getIntegrationPointMetaDataSingleField(), MeshToolsLib::getNumberOfElementIntegrationPoints(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::PropertyVectorBase::getPropertyName(), and MeshLib::PropertyVector< PROP_VAL_TYPE >::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().

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< PROP_VAL_TYPE >::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::vector< std::size_t > const & node_id_mapping )

Definition at line 669 of file NodeWiseMeshPartitioner.cpp.

673{
674 for (std::size_t part_id = 0; part_id < partitions.size(); part_id++)
675 {
676 auto& partition = partitions[part_id];
677 std::vector<MeshLib::Node*> base_ghost_nodes;
678 std::vector<MeshLib::Node*> higher_order_ghost_nodes;
679 std::tie(base_ghost_nodes, higher_order_ghost_nodes) =
681 part_id, mesh.getNodes(), partition.ghost_elements,
682 nodes_partition_ids, mesh, node_id_mapping);
683
684 std::copy(begin(base_ghost_nodes), end(base_ghost_nodes),
685 std::back_inserter(partition.nodes));
686
687 partition.number_of_base_nodes =
688 partition.number_of_regular_base_nodes + base_ghost_nodes.size();
689
690 std::copy(begin(higher_order_ghost_nodes),
691 end(higher_order_ghost_nodes),
692 std::back_inserter(partition.nodes));
693 }
694}
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::vector< std::size_t > 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 635 of file NodeWiseMeshPartitioner.cpp.

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

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::vector< std::size_t > const & bulk_node_ids )

Definition at line 586 of file NodeWiseMeshPartitioner.cpp.

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

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 1134 of file NodeWiseMeshPartitioner.cpp.

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

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::vector< std::size_t > 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 1113 of file NodeWiseMeshPartitioner.cpp.

1118{
1119 constexpr unsigned mat_id =
1120 0; // TODO: Material ID to be set from the mesh data
1121 const long nn = elem.getNumberOfNodes();
1122 elem_info[counter++] = mat_id;
1123 elem_info[counter++] = static_cast<long>(elem.getCellType());
1124 elem_info[counter++] = nn;
1125
1126 for (long i = 0; i < nn; i++)
1127 {
1128 auto const& n = *elem.getNode(i);
1129 elem_info[counter++] = local_node_ids.at(n.getID());
1130 }
1131}
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 1048 of file NodeWiseMeshPartitioner.cpp.

1050{
1051 return {
1052 static_cast<long>(oldConfig.node_rank_offset +
1053 offsets.node * sizeof(MeshLib::IO::NodeData)),
1054 // Offset the ending entry of the element integer variables of
1055 // the non-ghost elements of this partition in the vector of elem_info.
1056 static_cast<long>(oldConfig.element_rank_offset +
1057 offsets.regular_elements * sizeof(long)),
1058
1059 // Offset the ending entry of the element integer variables of
1060 // the ghost elements of this partition in the vector of elem_info.
1061 static_cast<long>(oldConfig.ghost_element_rank_offset +
1062 offsets.ghost_elements * sizeof(long))};
1063}
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 496 of file NodeWiseMeshPartitioner.cpp.

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

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::vector< std::size_t > 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::vector< std::size_t > const & bulk_node_ids )

Definition at line 696 of file NodeWiseMeshPartitioner.cpp.

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

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 442 of file NodeWiseMeshPartitioner.cpp.

445{
446 using namespace MeshLib;
447
448 MeshLib::Properties const& properties = mesh->getProperties();
449
450 // Count the number of integration point data of all partitions:
451 setIntegrationPointNumberOfPartition(properties, partitions);
452
453 Properties partitioned_properties;
454 auto count_tuples = [&](MeshItemType const mesh_item_type)
455 {
456 return std::accumulate(
457 begin(partitions), end(partitions), 0,
458 [&](std::size_t const sum, Partition const& p)
459 { return sum + p.numberOfMeshItems(mesh_item_type); });
460 };
461
462 std::map<MeshItemType, std::size_t> const total_number_of_tuples = {
463 {MeshItemType::Cell, count_tuples(MeshItemType::Cell)},
464 {MeshItemType::Node, count_tuples(MeshItemType::Node)},
465 {MeshItemType::IntegrationPoint,
466 count_tuples(MeshItemType::IntegrationPoint)}};
467
468 DBUG(
469 "total number of tuples after partitioning defined for cells is {:d} "
470 "and for nodes {:d} and for integration points {:d}.",
471 total_number_of_tuples.at(MeshItemType::Cell),
472 total_number_of_tuples.at(MeshItemType::Node),
473 total_number_of_tuples.at(MeshItemType::IntegrationPoint));
474
475 // 1 create new PV
476 // 2 resize the PV with total_number_of_tuples
477 // 3 copy the values according to the partition info
479 properties,
480 [&](auto type, auto const property)
481 {
483 mesh->getElements(), partitioned_properties, properties,
484 partitions,
485 dynamic_cast<PropertyVector<decltype(type)> const*>(property),
486 total_number_of_tuples);
487 });
488
489 addVtkGhostTypeProperty(partitioned_properties,
490 partitions,
491 total_number_of_tuples.at(MeshItemType::Cell));
492
493 return partitioned_properties;
494}
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)

References addVtkGhostTypeProperty(), applyToPropertyVectors(), copyPropertyVector(), DBUG(), 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 599 of file NodeWiseMeshPartitioner.cpp.

601{
602 std::vector<MeshLib::Node const*> higher_order_nodes;
603 // after splitIntoBaseAndHigherOrderNodes() partition.nodes contains only
604 // base nodes
605 std::tie(partition.nodes, higher_order_nodes) =
607 partition.number_of_regular_base_nodes = partition.nodes.size();
608 std::copy(begin(higher_order_nodes), end(higher_order_nodes),
609 std::back_inserter(partition.nodes));
610 partition.number_of_regular_nodes = partition.nodes.size();
611}
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 613 of file NodeWiseMeshPartitioner.cpp.

615{
616 for (auto& partition : partitions)
617 {
619 }
620}
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 622 of file NodeWiseMeshPartitioner.cpp.

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

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 1070 of file NodeWiseMeshPartitioner.cpp.

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

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

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 1220 of file NodeWiseMeshPartitioner.cpp.

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

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 953 of file NodeWiseMeshPartitioner.cpp.

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

931{
932 if (pv == nullptr)
933 {
934 return false;
935 }
936 // skip property of different mesh item type. Return true, because this
937 // operation was successful.
938 if (pv->getMeshItemType() != mesh_item_type)
939 {
940 return true;
941 }
942
944 pvmd.property_name = pv->getPropertyName();
948 writePropertyVectorValues(out_val, *pv);
950 return true;
951}
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< PROP_VAL_TYPE >::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 921 of file NodeWiseMeshPartitioner.cpp.

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

References MeshLib::PropertyVector< PROP_VAL_TYPE >::size().

Referenced by writePropertyVector().