OGS
ApplicationUtils Namespace Reference

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, ComputeNaturalCoordsResult const &json_data, double const tolerance, int const max_iter)
template<typename T>
void addPointData (vtkUnstructuredGrid *grid, std::string const &name, Eigen::MatrixX< T > const &data)
template<typename T>
void addCellData (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)

Variables

template<typename SolverInterface, template< typename > class SolverImplementationTplTpl>
const std::unordered_map< std::type_index, std::unique_ptr< SolverInterface > > SolverByElementTypeRegistry< SolverInterface, SolverImplementationTplTpl >::solvers_

Function Documentation

◆ addCellData()

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

Definition at line 192 of file ComputeNaturalCoordsAlgorithm.h.

194{
195 INFO("converting {}", name);
196 vtkNew<vtkAOSDataArrayTemplate<T>> array;
197 array->SetName(name.c_str());
198 array->SetNumberOfComponents(data.cols());
199 array->SetNumberOfTuples(grid->GetNumberOfCells());
200
201 if (grid->GetNumberOfCells() != data.rows())
202 {
203 OGS_FATAL(
204 "Got {} rows in the table but expected {} rows, same as number of "
205 "cells in the grid.",
206 data.rows(), grid->GetNumberOfCells());
207 }
208 for (Eigen::Index i = 0; i < data.rows(); ++i)
209 {
210 // copy to contiguous storage
211 Eigen::RowVectorX<T> const row = data.row(i);
212
213 array->SetTypedTuple(i, row.data());
214 DBUG("> {}", row);
215 }
216
217 grid->GetCellData()->AddArray(array);
218}
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22

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

Referenced by toVTKGrid().

◆ addPointData()

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

Definition at line 163 of file ComputeNaturalCoordsAlgorithm.h.

165{
166 INFO("converting {}", name);
167 vtkNew<vtkAOSDataArrayTemplate<T>> array;
168 array->SetName(name.c_str());
169 array->SetNumberOfComponents(data.cols());
170 array->SetNumberOfTuples(grid->GetNumberOfPoints());
171
172 if (grid->GetNumberOfPoints() != data.rows())
173 {
174 OGS_FATAL(
175 "Got {} rows in the table but expected {} rows, same as number of "
176 "points in the grid.",
177 data.rows(), grid->GetNumberOfPoints());
178 }
179 for (Eigen::Index i = 0; i < data.rows(); ++i)
180 {
181 // copy to contiguous storage
182 Eigen::RowVectorX<T> const row = data.row(i);
183
184 array->SetTypedTuple(i, row.data());
185 DBUG("> {}", row);
186 }
187
188 grid->GetPointData()->AddArray(array);
189}

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

404{
405 auto* vtk_ghost_type =
406 partitioned_properties.createNewPropertyVector<unsigned char>(
408 total_number_of_cells, 1);
409 if (vtk_ghost_type == nullptr)
410 {
411 OGS_FATAL("Could not create '{}' cell data array.",
413 }
414
415 assert(vtk_ghost_type->size() == total_number_of_cells);
416 std::size_t offset = 0;
417 for (auto const& partition : partitions)
418 {
419 offset += partition.regular_elements.size();
420 for (std::size_t i = 0; i < partition.ghost_elements.size(); ++i)
421 {
422 if (partition.duplicate_ghost_cell[i])
423 {
424 (*vtk_ghost_type)[offset + i] |=
425 vtkDataSetAttributes::DUPLICATECELL;
426 }
427 }
428 offset += partition.ghost_elements.size();
429 }
430}
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
constexpr std::string vtkGhostTypeString

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

Referenced by partitionProperties().

◆ checkFieldPropertyVectorSize()

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

Definition at line 509 of file NodeWiseMeshPartitioner.cpp.

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

Definition at line 79 of file ComputeNaturalCoordsAlgorithm.h.

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

References ApplicationUtils::ComputeNaturalCoordsResult::anchor_cross_sectional_area, ApplicationUtils::ComputeNaturalCoordsResult::anchor_stiffness, ApplicationUtils::ComputeNaturalCoordsIntermediateResult::append(), MeshLib::bulkElementIDs(), MeshLib::VtkMeshConverter::convertUnstructuredGrid(), ApplicationUtils::FindCellsForPoints::find(), ApplicationUtils::ComputeNaturalCoordsIntermediateResult::finished(), INFO(), ApplicationUtils::ComputeNaturalCoordsResult::initial_anchor_stress, ApplicationUtils::FindCellsForPoints::initialize(), ApplicationUtils::ComputeNaturalCoordsResult::maximum_anchor_stress, OGS_FATAL, ApplicationUtils::ComputeNaturalCoordsResult::real_coords, and ApplicationUtils::ComputeNaturalCoordsResult::residual_anchor_stress.

Referenced by main().

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

562{
563 auto node_partition_ids = ranges::views::transform(
564 [&](MeshLib::Element const* const element)
565 {
566 auto node_lookup = ranges::views::transform(
567 [&](std::size_t const i)
568 { return node_partition_map[bulk_node_ids[i]]; });
569
570 return element->nodes() | MeshLib::views::ids | node_lookup |
571 ranges::to<std::vector>;
572 });
573
574 return elements | node_partition_ids | ranges::to<std::vector>;
575}
constexpr std::span< Node *const > nodes() const
Span of element's nodes, their pointers actually.
Definition Element.h:63
constexpr ranges::views::view_closure ids
For an element of a range view return its id.
Definition Mesh.h:218

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

Referenced by partitionMesh().

◆ computePartitionOffsets()

PartitionOffsets ApplicationUtils::computePartitionOffsets ( Partition const & partition)

Definition at line 1028 of file NodeWiseMeshPartitioner.cpp.

1029{
1030 return {static_cast<long>(partition.nodes.size()),
1031 static_cast<long>(partition.regular_elements.size() +
1033 partition.regular_elements)),
1034 static_cast<long>(partition.ghost_elements.size() +
1036 partition.ghost_elements))};
1037}
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 193 of file NodeWiseMeshPartitioner.cpp.

198{
199 std::size_t const n_regular(p.regular_elements.size());
200 auto const n_components = pv.getNumberOfGlobalComponents();
201 for (std::size_t i = 0; i < n_regular; ++i)
202 {
203 const auto id = p.regular_elements[i]->getID();
204 std::copy_n(&pv[n_components * id], n_components,
205 &partitioned_pv[offset + n_components * i]);
206 }
207
208 std::size_t const n_ghost(p.ghost_elements.size());
209 for (std::size_t i = 0; i < n_ghost; ++i)
210 {
211 const auto id = p.ghost_elements[i]->getID();
212 std::copy_n(&pv[n_components * id], n_components,
213 &partitioned_pv[offset + n_components * (n_regular + i)]);
214 }
215 return n_components * (n_regular + n_ghost);
216}
int getNumberOfGlobalComponents() const

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

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

References MeshLib::PropertyVector< PROP_VAL_TYPE >::begin(), MeshLib::getIntegrationPointMetaData(), MeshLib::getIntegrationPointMetaDataSingleField(), MeshToolsLib::getNumberOfElementIntegrationPoints(), MeshLib::PropertyVectorBase::getNumberOfGlobalComponents(), MeshLib::PropertyVectorBase::getPropertyName(), ApplicationUtils::Partition::ghost_elements, ApplicationUtils::Partition::regular_elements, 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 171 of file NodeWiseMeshPartitioner.cpp.

176{
177 auto const& nodes = p.nodes;
178 auto const nnodes = nodes.size();
179 auto const n_components = pv.getNumberOfGlobalComponents();
180 for (std::size_t i = 0; i < nnodes; ++i)
181 {
182 const auto global_id = nodes[i]->getID();
183 std::copy_n(&pv[n_components * global_id], n_components,
184 &partitioned_pv[offset + n_components * i]);
185 }
186 return n_components * nnodes;
187}

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

328{
329 if (pv == nullptr)
330 {
331 return false;
332 }
333 auto const item_type = pv->getMeshItemType();
334
335 std::size_t partitioned_pv_size = total_number_of_tuples.at(item_type) *
337
338 std::vector<std::size_t> element_ip_data_offsets;
340 {
341 // Special field data such as OGS_VERSION, IntegrationPointMetaData,
342 // etc., which are not "real" integration points, are copied "as is"
343 // (i.e. fully) for every partition.
344 if (pv->getPropertyName().find("_ip") == std::string::npos)
345 {
346 partitioned_pv_size = pv->size() * partitions.size();
347 }
348
349 element_ip_data_offsets =
351 global_mesh_elements, *pv, properties);
352 }
353
354 auto partitioned_pv = partitioned_properties.createNewPropertyVector<T>(
355 pv->getPropertyName(), pv->getMeshItemType(),
357 if (partitioned_pv == nullptr)
358 {
359 OGS_FATAL(
360 "Could not create partitioned property vector {:s} for {} data "
361 "array.",
363 }
364 partitioned_pv->resize(partitioned_pv_size);
365
366 auto copy_property_vector_values =
367 [&](Partition const& p, std::size_t offset)
368 {
370 {
371 return copyFieldPropertyDataToPartitions(properties, p, offset,
372 element_ip_data_offsets,
373 *pv, *partitioned_pv);
374 }
375
376 if (item_type == MeshLib::MeshItemType::Node)
377 {
378 return copyNodePropertyVectorValues(p, offset, *pv,
379 *partitioned_pv);
380 }
381 if (item_type == MeshLib::MeshItemType::Cell)
382 {
383 return copyCellPropertyVectorValues(p, offset, *pv,
384 *partitioned_pv);
385 }
386
387 OGS_FATAL(
388 "Copying of property vector values for mesh item type {:s} is not "
389 "implemented.",
390 toString(item_type));
391 };
392
393 std::size_t position_offset(0);
394 for (auto p : partitions)
395 {
396 position_offset += copy_property_vector_values(p, position_offset);
397 }
398 return true;
399}
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)
std::string_view toString(PhaseName phase_name)
Convert phase enum to its string representation.
Definition Phase.cpp:13
static constexpr char const * toString(const MeshItemType t)
Returns a char array for a specific MeshItemType.
Definition MeshEnums.h:26
std::vector< std::size_t > getIntegrationPointDataOffsetsOfMeshElements(std::vector< MeshLib::Element * > const &mesh_elements, MeshLib::PropertyVectorBase const &pv, MeshLib::Properties const &properties)

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::span< std::size_t const > const node_id_mapping )

Definition at line 660 of file NodeWiseMeshPartitioner.cpp.

664{
665 for (std::size_t part_id = 0; part_id < partitions.size(); part_id++)
666 {
667 auto& partition = partitions[part_id];
668 std::vector<MeshLib::Node*> base_ghost_nodes;
669 std::vector<MeshLib::Node*> higher_order_ghost_nodes;
670 std::tie(base_ghost_nodes, higher_order_ghost_nodes) =
672 part_id, mesh.getNodes(), partition.ghost_elements,
673 nodes_partition_ids, mesh, node_id_mapping);
674
675 std::copy(begin(base_ghost_nodes), end(base_ghost_nodes),
676 std::back_inserter(partition.nodes));
677
678 partition.number_of_base_nodes =
679 partition.number_of_regular_base_nodes + base_ghost_nodes.size();
680
681 std::copy(begin(higher_order_ghost_nodes),
682 end(higher_order_ghost_nodes),
683 std::back_inserter(partition.nodes));
684 }
685}
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 626 of file NodeWiseMeshPartitioner.cpp.

630{
631 for (auto const& element : mesh.getElements())
632 {
633 auto const element_id = element->getID();
634 auto node_partition_ids = partition_ids_per_element[element_id];
635 // make partition ids unique
636 std::sort(node_partition_ids.begin(), node_partition_ids.end());
637 auto last =
638 std::unique(node_partition_ids.begin(), node_partition_ids.end());
639 node_partition_ids.erase(last, node_partition_ids.end());
640
641 // all element nodes belong to the same partition => regular element
642 if (node_partition_ids.size() == 1)
643 {
644 partitions[node_partition_ids[0]].regular_elements.push_back(
645 element);
646 }
647 else
648 {
649 for (auto const partition_id : node_partition_ids)
650 {
651 partitions[partition_id].ghost_elements.push_back(element);
652 }
653 }
654 }
655}

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

582{
583 for (auto const* const node : nodes)
584 {
585 partitions[nodes_partition_ids[bulk_node_ids[node->getID()]]]
586 .nodes.push_back(node);
587 }
588}

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

1127{
1128 std::unordered_map<std::size_t, long> local_ids;
1129 local_ids.reserve(nodes.size());
1130
1131 long local_node_id = 0;
1132 for (const auto* node : nodes)
1133 {
1134 local_ids[node->getID()] = local_node_id++;
1135 }
1136 return local_ids;
1137}

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

133{
134 std::vector<MeshLib::Node*> base_ghost_nodes;
135 std::vector<MeshLib::Node*> higher_order_ghost_nodes;
136
137 std::vector<bool> is_ghost_node(nodes.size(), false);
138 for (const auto* ghost_elem : ghost_elements)
139 {
140 for (unsigned i = 0; i < ghost_elem->getNumberOfNodes(); i++)
141 {
142 auto const& n = ghost_elem->getNode(i);
143 auto const node_id = n->getID();
144 if (is_ghost_node[node_id])
145 {
146 continue;
147 }
148
149 if (partitionLookup(node_id, partition_ids, node_id_mapping) !=
150 part_id)
151 {
152 if (isBaseNode(*n, mesh.getElementsConnectedToNode(*n)))
153 {
154 base_ghost_nodes.push_back(nodes[node_id]);
155 }
156 else
157 {
158 higher_order_ghost_nodes.push_back(nodes[node_id]);
159 }
160 is_ghost_node[node_id] = true;
161 }
162 }
163 }
164 return std::tuple<std::vector<MeshLib::Node*>, std::vector<MeshLib::Node*>>{
165 base_ghost_nodes, higher_order_ghost_nodes};
166}
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)

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

1109{
1110 constexpr unsigned mat_id =
1111 0; // TODO: Material ID to be set from the mesh data
1112 const long nn = elem.getNumberOfNodes();
1113 elem_info[counter++] = mat_id;
1114 elem_info[counter++] = static_cast<long>(elem.getCellType());
1115 elem_info[counter++] = nn;
1116
1117 for (long i = 0; i < nn; i++)
1118 {
1119 auto const& n = *elem.getNode(i);
1120 elem_info[counter++] = local_node_ids.at(n.getID());
1121 }
1122}
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 62 of file NodeWiseMeshPartitioner.cpp.

64{
65 return 3 * elements.size() +
66 std::accumulate(begin(elements), end(elements), 0,
67 [](auto const nnodes, auto const* e)
68 { return nnodes + e->getNumberOfNodes(); });
69}

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

◆ incrementConfigOffsets()

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

Definition at line 1039 of file NodeWiseMeshPartitioner.cpp.

1041{
1042 return {
1043 static_cast<long>(oldConfig.node_rank_offset +
1044 offsets.node * sizeof(MeshLib::IO::NodeData)),
1045 // Offset the ending entry of the element integer variables of
1046 // the non-ghost elements of this partition in the vector of elem_info.
1047 static_cast<long>(oldConfig.element_rank_offset +
1048 offsets.regular_elements * sizeof(long)),
1049
1050 // Offset the ending entry of the element integer variables of
1051 // the ghost elements of this partition in the vector of elem_info.
1052 static_cast<long>(oldConfig.ghost_element_rank_offset +
1053 offsets.ghost_elements * sizeof(long))};
1054}
struct NodeData used for parallel reading and also partitioning
Definition NodeData.h:12

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

489{
490 std::vector<bool> cell_visited(mesh.getElements().size(), false);
491
492 for (auto& partition : partitions)
493 {
494 partition.duplicate_ghost_cell.resize(partition.ghost_elements.size(),
495 true);
496
497 for (std::size_t i = 0; i < partition.ghost_elements.size(); i++)
498 {
499 const auto& ghost_element = *partition.ghost_elements[i];
500 if (!cell_visited[ghost_element.getID()])
501 {
502 cell_visited[ghost_element.getID()] = true;
503 partition.duplicate_ghost_cell[i] = false;
504 }
505 }
506 }
507}

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

94{
95 return partition_ids[node_id_mapping[node_id]];
96}

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

691{
692 BaseLib::RunTime run_timer;
693 run_timer.start();
694 auto const partition_ids_per_element = computePartitionIDPerElement(
695 nodes_partition_ids, mesh.getElements(), bulk_node_ids);
696 INFO("partitionMesh(): Partition IDs per element computed in {:g} s",
697 run_timer.elapsed());
698
699 run_timer.start();
700 distributeNodesToPartitions(partitions, nodes_partition_ids,
701 mesh.getNodes(), bulk_node_ids);
702 INFO("partitionMesh(): distribute nodes to partitions took {:g} s",
703 run_timer.elapsed());
704
705 run_timer.start();
707 INFO(
708 "partitionMesh(): sorting [base nodes | higher order nodes] took {:g} "
709 "s",
710 run_timer.elapsed());
711
712 run_timer.start();
713 setNumberOfNodesInPartitions(partitions, mesh);
714 INFO(
715 "partitionMesh(): setting number of nodes and of all mesh base nodes "
716 "took {:g} s",
717 run_timer.elapsed());
718
719 run_timer.start();
720 distributeElementsIntoPartitions(partitions, mesh,
721 partition_ids_per_element);
722 INFO("partitionMesh(): distribute elements into partitions took {:g} s",
723 run_timer.elapsed());
724
725 run_timer.start();
727 partitions, mesh, nodes_partition_ids, bulk_node_ids);
728 INFO("partitionMesh(): determine / append ghost nodes took {:g} s",
729 run_timer.elapsed());
730
731 run_timer.start();
732 markDuplicateGhostCells(mesh, partitions);
733 INFO("partitionMesh(): markDuplicateGhostCells took {:g} s",
734 run_timer.elapsed());
735}
Count the running time.
Definition RunTime.h:18
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:31
void start()
Start the timer.
Definition RunTime.h:21
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 433 of file NodeWiseMeshPartitioner.cpp.

436{
437 using namespace MeshLib;
438
439 MeshLib::Properties const& properties = mesh->getProperties();
440
441 // Count the number of integration point data of all partitions:
442 setIntegrationPointNumberOfPartition(properties, partitions);
443
444 Properties partitioned_properties;
445 auto count_tuples = [&](MeshItemType const mesh_item_type)
446 {
447 return std::accumulate(
448 begin(partitions), end(partitions), 0,
449 [&](std::size_t const sum, Partition const& p)
450 { return sum + p.numberOfMeshItems(mesh_item_type); });
451 };
452
453 std::map<MeshItemType, std::size_t> const total_number_of_tuples = {
454 {MeshItemType::Cell, count_tuples(MeshItemType::Cell)},
455 {MeshItemType::Node, count_tuples(MeshItemType::Node)},
456 {MeshItemType::IntegrationPoint,
457 count_tuples(MeshItemType::IntegrationPoint)}};
458
459 DBUG(
460 "total number of tuples after partitioning defined for cells is {:d} "
461 "and for nodes {:d} and for integration points {:d}.",
462 total_number_of_tuples.at(MeshItemType::Cell),
463 total_number_of_tuples.at(MeshItemType::Node),
464 total_number_of_tuples.at(MeshItemType::IntegrationPoint));
465
466 // 1 create new PV
467 // 2 resize the PV with total_number_of_tuples
468 // 3 copy the values according to the partition info
470 properties,
471 [&](auto type, auto const property)
472 {
474 mesh->getElements(), partitioned_properties, properties,
475 partitions,
476 dynamic_cast<PropertyVector<decltype(type)> const*>(property),
477 total_number_of_tuples);
478 });
479
480 addVtkGhostTypeProperty(partitioned_properties,
481 partitions,
482 total_number_of_tuples.at(MeshItemType::Cell));
483
484 return partitioned_properties;
485}
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
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)
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 applyToPropertyVectors(Properties const &properties, Function f)
std::size_t numberOfMeshItems(MeshLib::MeshItemType const item_type) const

References addVtkGhostTypeProperty(), MeshLib::applyToPropertyVectors(), MeshLib::Cell, copyPropertyVector(), DBUG(), MeshLib::IntegrationPoint, MeshLib::Node, 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 37 of file Metis.cpp.

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

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 82 of file Metis.cpp.

84{
85 const std::string npartitions_str = std::to_string(number_of_partitions);
86
87 std::remove((file_name_base + ".mesh.npart." + npartitions_str).c_str());
88 std::remove((file_name_base + ".mesh.epart." + npartitions_str).c_str());
89}

Referenced by main().

◆ reorderNodesIntoBaseAndHigherOrderNodes()

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

Definition at line 590 of file NodeWiseMeshPartitioner.cpp.

592{
593 std::vector<MeshLib::Node const*> higher_order_nodes;
594 // after splitIntoBaseAndHigherOrderNodes() partition.nodes contains only
595 // base nodes
596 std::tie(partition.nodes, higher_order_nodes) =
598 partition.number_of_regular_base_nodes = partition.nodes.size();
599 std::copy(begin(higher_order_nodes), end(higher_order_nodes),
600 std::back_inserter(partition.nodes));
601 partition.number_of_regular_nodes = partition.nodes.size();
602}
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 604 of file NodeWiseMeshPartitioner.cpp.

606{
607 for (auto& partition : partitions)
608 {
610 }
611}
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 272 of file NodeWiseMeshPartitioner.cpp.

274{
275 auto const& opt_ip_meta_data_all =
277 for (auto const& [name, property] : properties)
278 {
279 auto const item_type = property->getMeshItemType();
280
282 {
283 continue;
284 }
285
286 // For special field data such as OGS_VERSION, IntegrationPointMetaData,
287 // etc., which are not "real" integration points:
288 if (property->getPropertyName().find("_ip") == std::string::npos)
289 {
290 continue;
291 }
292
293 auto const& ip_meta_data =
295 opt_ip_meta_data_all, property->getPropertyName());
296 auto countIntegrationPoints =
297 [&](std::vector<const MeshLib::Element*> const& elements)
298 {
299 std::size_t counter = 0;
300 for (auto const element : elements)
301 {
302 int const number_of_integration_points =
304 ip_meta_data, *element);
305 counter += number_of_integration_points;
306 }
307 return counter;
308 };
309
310 for (auto& p : partitions)
311 {
312 p.number_of_integration_points =
313 countIntegrationPoints(p.regular_elements) +
314 countIntegrationPoints(p.ghost_elements);
315 }
316 return;
317 }
318}

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

615{
616 auto const number_of_mesh_base_nodes = mesh.computeNumberOfBaseNodes();
617 auto const number_of_mesh_all_nodes = mesh.getNumberOfNodes();
618 for (auto& partition : partitions)
619 {
620 partition.number_of_regular_nodes = partition.nodes.size();
621 partition.number_of_mesh_base_nodes = number_of_mesh_base_nodes;
622 partition.number_of_mesh_all_nodes = number_of_mesh_all_nodes;
623 }
624}

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

101{
102 // Space for resulting vectors.
103 std::vector<MeshLib::Node const*> base_nodes;
104 // if linear mesh, then one reallocation, no realloc for higher order
105 // elements meshes.
106 base_nodes.reserve(nodes.size() / 2);
107 std::vector<MeshLib::Node const*> higher_order_nodes;
108 // if linear mesh, then wasted space, good estimate for quadratic
109 // order mesh, and realloc needed for higher order element meshes.
110 higher_order_nodes.reserve(nodes.size() / 2);
111
112 // Split the nodes into base nodes and extra nodes.
113 std::partition_copy(
114 begin(nodes), end(nodes), std::back_inserter(base_nodes),
115 std::back_inserter(higher_order_nodes),
116 [&](MeshLib::Node const* const n)
117 { return isBaseNode(*n, mesh.getElementsConnectedToNode(*n)); });
118
119 return {base_nodes, higher_order_nodes};
120}

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 226 of file ComputeNaturalCoordsAlgorithm.h.

228{
229 INFO("converting points");
230 auto const n_pts = result.natural_coords.rows();
231 if (n_pts == 0)
232 {
233 OGS_FATAL(
234 "No point was found in the mesh. Please check whether all anchors "
235 "are within the model region.");
236 }
237 else if (n_pts == 1)
238 {
239 OGS_FATAL(
240 "Only one point was found in the mesh. Please check whether all "
241 "anchors are within the model region.");
242 }
243 else if (n_pts % 2 != 0)
244 {
245 // number should be even if multiplicity is ignored
246 OGS_FATAL(
247 "Number of points is not even. Anchors are believed to consist of "
248 "a start and an end point.");
249 }
250
251 vtkNew<vtkUnstructuredGrid> grid;
252
253 // Points ------------------------------------------------------------------
254 vtkNew<vtkPoints> points;
255 points->SetDataTypeToDouble();
256 points->SetNumberOfPoints(n_pts);
257
258 auto const& css = result.real_coords;
259 for (Eigen::Index i = 0; i < css.rows(); ++i)
260 {
261 points->SetPoint(i, css(i, 0), css(i, 1), css(i, 2));
262
263 if ((i % 2) == 1)
264 {
265 vtkNew<vtkLine> line;
266 line->GetPointIds()->SetId(0, i - 1);
267 line->GetPointIds()->SetId(1, i);
268 grid->InsertNextCell(line->GetCellType(), line->GetPointIds());
269 }
270 }
271
272 grid->SetPoints(points);
273
274 // Point data --------------------------------------------------------------
275 addPointData<double>(grid, "natural_coordinates", result.natural_coords);
276 addPointData<std::size_t>(grid, "bulk_element_ids",
277 result.bulk_element_ids.cast<std::size_t>());
278 addPointData<std::size_t>(grid, "point_cloud_node_ids",
279 result.point_cloud_node_ids.cast<std::size_t>());
280 addCellData<double>(grid, "initial_anchor_stress",
281 result.initial_anchor_stress);
282 addCellData<double>(grid, "maximum_anchor_stress",
283 result.maximum_anchor_stress);
284 addCellData<double>(grid, "residual_anchor_stress",
285 result.residual_anchor_stress);
286 addCellData<double>(grid, "anchor_cross_sectional_area",
287 result.anchor_cross_sectional_area);
288 addCellData<double>(grid, "anchor_stiffness", result.anchor_stiffness);
289 return grid;
290}
void addPointData(vtkUnstructuredGrid *grid, std::string const &name, Eigen::MatrixX< T > const &data)
void addCellData(vtkUnstructuredGrid *grid, std::string const &name, Eigen::MatrixX< T > const &data)

References addCellData(), addPointData(), ApplicationUtils::ComputeNaturalCoordsResult::anchor_cross_sectional_area, ApplicationUtils::ComputeNaturalCoordsResult::anchor_stiffness, ApplicationUtils::ComputeNaturalCoordsResult::bulk_element_ids, INFO(), ApplicationUtils::ComputeNaturalCoordsResult::initial_anchor_stress, ApplicationUtils::ComputeNaturalCoordsResult::maximum_anchor_stress, ApplicationUtils::ComputeNaturalCoordsResult::natural_coords, OGS_FATAL, ApplicationUtils::ComputeNaturalCoordsResult::point_cloud_node_ids, ApplicationUtils::ComputeNaturalCoordsResult::real_coords, and ApplicationUtils::ComputeNaturalCoordsResult::residual_anchor_stress.

Referenced by main().

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

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

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

13{
14 std::ofstream os(file_name, std::ios::trunc);
15 if (!os.is_open())
16 {
17 OGS_FATAL("Error: cannot open file {:s}.", file_name.data());
18 }
19
20 if (!os.good())
21 {
22 OGS_FATAL("Error: Cannot write in file {:s}.", file_name.data());
23 }
24
25 os << elements.size() << " \n";
26 for (const auto* elem : elements)
27 {
28 os << getNodeIndex(*elem, 0) + 1;
29 for (unsigned j = 1; j < elem->getNumberOfNodes(); j++)
30 {
31 os << " " << getNodeIndex(*elem, j) + 1;
32 }
33 os << "\n";
34 }
35}
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition Element.cpp:226

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

1214{
1215 auto const file_name = file_name_base + "_partitioned_msh_nod" +
1216 std::to_string(partitions.size()) + ".bin";
1217 std::ofstream os(file_name, std::ios::binary);
1218 if (!os)
1219 {
1220 OGS_FATAL("Could not open file '{:s}' for output.", file_name);
1221 }
1222
1223 for (const auto& partition : partitions)
1224 {
1225 partition.writeNodes(os, global_node_ids);
1226 }
1227}

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

948{
949 auto const number_of_properties =
950 partitioned_properties.size(mesh_item_type);
951 if (number_of_properties == 0)
952 {
953 return;
954 }
955
956 auto const file_name_infix = toString(mesh_item_type);
957
958 auto const file_name_cfg = file_name_base + "_partitioned_" +
959 file_name_infix + "_properties_cfg" +
960 std::to_string(partitions.size()) + ".bin";
961 std::ofstream out(file_name_cfg, std::ios::binary);
962 if (!out)
963 {
964 OGS_FATAL("Could not open file '{:s}' for output.", file_name_cfg);
965 }
966
967 auto const file_name_val = file_name_base + "_partitioned_" +
968 file_name_infix + "_properties_val" +
969 std::to_string(partitions.size()) + ".bin";
970 std::ofstream out_val(file_name_val, std::ios::binary);
971 if (!out_val)
972 {
973 OGS_FATAL("Could not open file '{:s}' for output.", file_name_val);
974 }
975
976 BaseLib::writeValueBinary(out, number_of_properties);
977
979 partitioned_properties,
980 [&](auto type, auto const& property)
981 {
983 dynamic_cast<MeshLib::PropertyVector<decltype(type)> const*>(
984 property),
985 mesh_item_type, out_val, out);
986 });
987
988 unsigned long offset = 0;
989 for (const auto& partition : partitions)
990 {
991 MeshLib::IO::PropertyVectorPartitionMetaData pvpmd{
992 offset, static_cast<unsigned long>(
993 partition.numberOfMeshItems(mesh_item_type))};
994 DBUG(
995 "Write meta data for node-based PropertyVector: global offset "
996 "{:d}, number of tuples {:d}",
997 pvpmd.offset, pvpmd.number_of_tuples);
999 offset += pvpmd.number_of_tuples;
1000 }
1001}
bool writePropertyVector(MeshLib::PropertyVector< T > const *const pv, MeshLib::MeshItemType const mesh_item_type, std::ostream &out_val, std::ostream &out_meta)
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 MeshLib::applyToPropertyVectors(), DBUG(), MeshLib::IO::PropertyVectorPartitionMetaData::number_of_tuples, MeshLib::IO::PropertyVectorPartitionMetaData::offset, OGS_FATAL, MeshLib::Properties::size(), MeshLib::toString(), 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 919 of file NodeWiseMeshPartitioner.cpp.

922{
923 if (pv == nullptr)
924 {
925 return false;
926 }
927 // skip property of different mesh item type. Return true, because this
928 // operation was successful.
929 if (pv->getMeshItemType() != mesh_item_type)
930 {
931 return true;
932 }
933
934 MeshLib::IO::PropertyVectorMetaData pvmd;
935 pvmd.property_name = pv->getPropertyName();
939 writePropertyVectorValues(out_val, *pv);
941 return true;
942}
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< 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 912 of file NodeWiseMeshPartitioner.cpp.

914{
915 os.write(reinterpret_cast<const char*>(pv.data()), pv.size() * sizeof(T));
916}
constexpr const PROP_VAL_TYPE * data() const

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

Referenced by writePropertyVector().

Variable Documentation

◆ SolverByElementTypeRegistry< SolverInterface, SolverImplementationTplTpl >::solvers_

template<typename SolverInterface, template< typename > class SolverImplementationTplTpl>
const std::unordered_map<std::type_index, std::unique_ptr<SolverInterface> > ApplicationUtils::SolverByElementTypeRegistry< SolverInterface, SolverImplementationTplTpl >::solvers_
Initial value:
{
SolverByElementTypeRegistry<SolverInterface,
SolverImplementationTplTpl>::initSolvers()}

Definition at line 76 of file SolverByElementTypeRegistry.h.

76 {
77 SolverByElementTypeRegistry<SolverInterface,
78 SolverImplementationTplTpl>::initSolvers()};