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>(
407 "vtkGhostType", MeshLib::MeshItemType::Cell, total_number_of_cells,
408 1);
409 if (vtk_ghost_type == nullptr)
410 {
411 OGS_FATAL("Could not create vtkGhostType cell data array.");
412 }
413
414 assert(vtk_ghost_type->size() == total_number_of_cells);
415 std::size_t offset = 0;
416 for (auto const& partition : partitions)
417 {
418 offset += partition.regular_elements.size();
419 for (std::size_t i = 0; i < partition.ghost_elements.size(); ++i)
420 {
421 if (partition.duplicate_ghost_cell[i])
422 {
423 (*vtk_ghost_type)[offset + i] |=
424 vtkDataSetAttributes::DUPLICATECELL;
425 }
426 }
427 offset += partition.ghost_elements.size();
428 }
429}
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)

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

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

561{
562 auto node_partition_ids = ranges::views::transform(
563 [&](MeshLib::Element const* const element)
564 {
565 auto node_lookup = ranges::views::transform(
566 [&](std::size_t const i)
567 { return node_partition_map[bulk_node_ids[i]]; });
568
569 return element->nodes() | MeshLib::views::ids | node_lookup |
570 ranges::to<std::vector>;
571 });
572
573 return elements | node_partition_ids | ranges::to<std::vector>;
574}
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:216

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

Referenced by partitionMesh().

◆ computePartitionOffsets()

PartitionOffsets ApplicationUtils::computePartitionOffsets ( Partition const & partition)

Definition at line 1027 of file NodeWiseMeshPartitioner.cpp.

1028{
1029 return {static_cast<long>(partition.nodes.size()),
1030 static_cast<long>(partition.regular_elements.size() +
1032 partition.regular_elements)),
1033 static_cast<long>(partition.ghost_elements.size() +
1035 partition.ghost_elements))};
1036}
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)
static constexpr char const * toString(const MeshItemType t)
Returns a char array for a specific MeshItemType.
Definition MeshEnums.h:25
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::span< std::size_t const > const node_id_mapping )

Definition at line 659 of file NodeWiseMeshPartitioner.cpp.

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

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

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

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

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

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

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

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

1040{
1041 return {
1042 static_cast<long>(oldConfig.node_rank_offset +
1043 offsets.node * sizeof(MeshLib::IO::NodeData)),
1044 // Offset the ending entry of the element integer variables of
1045 // the non-ghost elements of this partition in the vector of elem_info.
1046 static_cast<long>(oldConfig.element_rank_offset +
1047 offsets.regular_elements * sizeof(long)),
1048
1049 // Offset the ending entry of the element integer variables of
1050 // the ghost elements of this partition in the vector of elem_info.
1051 static_cast<long>(oldConfig.ghost_element_rank_offset +
1052 offsets.ghost_elements * sizeof(long))};
1053}
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 486 of file NodeWiseMeshPartitioner.cpp.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

913{
914 os.write(reinterpret_cast<const char*>(pv.data()), pv.size() * sizeof(T));
915}
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 78 of file SolverByElementTypeRegistry.h.

78 {
79 SolverByElementTypeRegistry<SolverInterface,
80 SolverImplementationTplTpl>::initSolvers()};