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 &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 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::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 &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:10
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 388 of file NodeWiseMeshPartitioner.cpp.

391{
392 auto* vtk_ghost_type =
393 partitioned_properties.createNewPropertyVector<unsigned char>(
395 total_number_of_cells, 1);
396 if (vtk_ghost_type == nullptr)
397 {
398 OGS_FATAL("Could not create '{}' cell data array.",
400 }
401
402 if (vtk_ghost_type->size() != total_number_of_cells)
403 {
404 OGS_FATAL("Size mismatch: '{}' has size {}, expected {}.",
405 MeshLib::vtkGhostTypeString, vtk_ghost_type->size(),
406 total_number_of_cells);
407 }
408
409 // A cell that crosses partition boundaries is contained in every partition
410 // it touches. The first occurrence in partition iteration order is kept as
411 // a regular cell; every later occurrence is flagged as a duplicate so that
412 // merging tools (e.g. PVTU2VTU) keep a single copy.
413 // Cell ids are dense in [0, number of global cells), and the total number
414 // of cells over all partitions counts every shared cell at least once, so
415 // it is a valid upper bound for the largest cell id.
416 std::vector<bool> cell_was_visited(total_number_of_cells, false);
417 std::size_t offset = 0;
418 for (auto const& partition : partitions)
419 {
420 for (std::size_t i = 0; i < partition.elements.size(); ++i)
421 {
422 auto const cell_id = partition.elements[i]->getID();
423 if (cell_was_visited[cell_id])
424 {
425 (*vtk_ghost_type)[offset + i] |=
426 vtkDataSetAttributes::DUPLICATECELL;
427 }
428 else
429 {
430 cell_was_visited[cell_id] = true;
431 }
432 }
433 offset += partition.elements.size();
434 }
435}
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 492 of file NodeWiseMeshPartitioner.cpp.

495{
496 auto const& opt_ip_meta_data_all =
498 for (auto const& [name, property] : properties)
499 {
500 auto const item_type = property->getMeshItemType();
501
503 {
504 continue;
505 }
506
507 // For special field data such as OGS_VERSION, IntegrationPointMetaData,
508 // etc., which are not "real" integration points:
509 if (property->getPropertyName().find("_ip") == std::string::npos)
510 {
511 continue;
512 }
513
514 std::size_t number_of_total_integration_points = 0;
515 auto const ip_meta_data =
517 opt_ip_meta_data_all, property->getPropertyName());
518 for (auto const element : global_mesh_elements)
519 {
520 int const number_of_integration_points =
522 *element);
523 number_of_total_integration_points += number_of_integration_points;
524 }
525
526 const auto pv =
527 dynamic_cast<MeshLib::PropertyVector<double> const*>(property);
528 std::size_t const component_number = pv->getNumberOfGlobalComponents();
529 if (pv->size() != number_of_total_integration_points * component_number)
530 {
531 OGS_FATAL(
532 "The property vector's size {:d} for integration point data "
533 "{:s} does not match its actual size {:d}. The field data in "
534 "the vtu file are wrong.",
535 pv->size(), name,
536 number_of_total_integration_points * component_number);
537 }
538 }
539}
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:292

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

545{
546 auto node_partition_ids = ranges::views::transform(
547 [&](MeshLib::Element const* const element)
548 {
549 auto node_lookup = ranges::views::transform(
550 [&](std::size_t const i)
551 { return node_partition_map[bulk_node_ids[i]]; });
552
553 return element->nodes() | MeshLib::views::ids | node_lookup |
554 ranges::to<std::vector>;
555 });
556
557 return elements | node_partition_ids | ranges::to<std::vector>;
558}
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:223

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

Referenced by partitionMesh().

◆ computePartitionOffsets()

PartitionOffsets ApplicationUtils::computePartitionOffsets ( Partition const & partition)

Definition at line 996 of file NodeWiseMeshPartitioner.cpp.

997{
998 return {static_cast<long>(partition.nodes.size()),
999 static_cast<long>(
1000 partition.elements.size() +
1001 getNumberOfIntegerVariablesOfElements(partition.elements))};
1002}
NodeWiseMeshPartitioner::IntegerType getNumberOfIntegerVariablesOfElements(std::vector< const MeshLib::Element * > const &elements)

References ApplicationUtils::Partition::elements, getNumberOfIntegerVariablesOfElements(), and ApplicationUtils::Partition::nodes.

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.

Definition at line 192 of file NodeWiseMeshPartitioner.cpp.

197{
198 std::size_t const n_elements(p.elements.size());
199 auto const n_components = pv.getNumberOfGlobalComponents();
200 for (std::size_t i = 0; i < n_elements; ++i)
201 {
202 const auto id = p.elements[i]->getID();
203 std::copy_n(&pv[n_components * id], n_components,
204 &partitioned_pv[offset + n_components * i]);
205 }
206 return n_components * n_elements;
207}
int getNumberOfGlobalComponents() const

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

Referenced by copyPropertyVector().

◆ copyFieldPropertyDataToPartitions()

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

Copies the data from the property vector pv belonging to the given Partition p to the property vector partitioned_pv. partitioned_pv is ordered by partition.

Definition at line 213 of file NodeWiseMeshPartitioner.cpp.

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

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

Referenced by copyPropertyVector().

◆ copyNodePropertyVectorValues()

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

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

Definition at line 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 308 of file NodeWiseMeshPartitioner.cpp.

315{
316 if (pv == nullptr)
317 {
318 return false;
319 }
320 auto const item_type = pv->getMeshItemType();
321
322 std::size_t partitioned_pv_size = total_number_of_tuples.at(item_type) *
324
325 std::vector<std::size_t> element_ip_data_offsets;
327 {
328 // Special field data such as OGS_VERSION, IntegrationPointMetaData,
329 // etc., which are not "real" integration points, are copied "as is"
330 // (i.e. fully) for every partition.
331 if (pv->getPropertyName().find("_ip") == std::string::npos)
332 {
333 partitioned_pv_size = pv->size() * partitions.size();
334 }
335
336 element_ip_data_offsets =
338 global_mesh_elements, *pv, properties);
339 }
340
341 auto partitioned_pv = partitioned_properties.createNewPropertyVector<T>(
342 pv->getPropertyName(), pv->getMeshItemType(),
344 if (partitioned_pv == nullptr)
345 {
346 OGS_FATAL(
347 "Could not create partitioned property vector {:s} for {} data "
348 "array.",
350 }
351 partitioned_pv->resize(partitioned_pv_size);
352
353 auto copy_property_vector_values =
354 [&](Partition const& p, std::size_t offset)
355 {
357 {
358 return copyFieldPropertyDataToPartitions(properties, p, offset,
359 element_ip_data_offsets,
360 *pv, *partitioned_pv);
361 }
362
363 if (item_type == MeshLib::MeshItemType::Node)
364 {
365 return copyNodePropertyVectorValues(p, offset, *pv,
366 *partitioned_pv);
367 }
368 if (item_type == MeshLib::MeshItemType::Cell)
369 {
370 return copyCellPropertyVectorValues(p, offset, *pv,
371 *partitioned_pv);
372 }
373
374 OGS_FATAL(
375 "Copying of property vector values for mesh item type {:s} is not "
376 "implemented.",
377 toString(item_type));
378 };
379
380 std::size_t position_offset(0);
381 for (auto p : partitions)
382 {
383 position_offset += copy_property_vector_values(p, position_offset);
384 }
385 return true;
386}
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 637 of file NodeWiseMeshPartitioner.cpp.

641{
642 for (std::size_t part_id = 0; part_id < partitions.size(); part_id++)
643 {
644 auto& partition = partitions[part_id];
645 std::vector<MeshLib::Node*> base_ghost_nodes;
646 std::vector<MeshLib::Node*> higher_order_ghost_nodes;
647 std::tie(base_ghost_nodes, higher_order_ghost_nodes) =
648 findGhostNodesInPartition(part_id, mesh.getNodes(),
649 partition.elements, nodes_partition_ids,
650 mesh, node_id_mapping);
651
652 std::copy(begin(base_ghost_nodes), end(base_ghost_nodes),
653 std::back_inserter(partition.nodes));
654
655 partition.number_of_base_nodes =
656 partition.number_of_regular_base_nodes + base_ghost_nodes.size();
657
658 std::copy(begin(higher_order_ghost_nodes),
659 end(higher_order_ghost_nodes),
660 std::back_inserter(partition.nodes));
661 }
662}
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 &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 609 of file NodeWiseMeshPartitioner.cpp.

613{
614 for (auto const& element : mesh.getElements())
615 {
616 auto const element_id = element->getID();
617 auto node_partition_ids = partition_ids_per_element[element_id];
618 // make partition ids unique
619 std::sort(node_partition_ids.begin(), node_partition_ids.end());
620 auto last =
621 std::unique(node_partition_ids.begin(), node_partition_ids.end());
622 node_partition_ids.erase(last, node_partition_ids.end());
623
624 // Add the element to every partition it touches. Elements whose nodes
625 // span multiple partitions are simply contained in each of these
626 // partitions; they are no longer distinguished as ghost elements.
627 for (auto const partition_id : node_partition_ids)
628 {
629 partitions[partition_id].elements.push_back(element);
630 }
631 }
632}

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

565{
566 for (auto const* const node : nodes)
567 {
568 partitions[nodes_partition_ids[bulk_node_ids[node->getID()]]]
569 .nodes.push_back(node);
570 }
571}

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

1083{
1084 std::unordered_map<std::size_t, long> local_ids;
1085 local_ids.reserve(nodes.size());
1086
1087 long local_node_id = 0;
1088 for (const auto* node : nodes)
1089 {
1090 local_ids[node->getID()] = local_node_id++;
1091 }
1092 return local_ids;
1093}

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 & elements,
std::vector< std::size_t > const & partition_ids,
MeshLib::Mesh const & mesh,
std::span< std::size_t const > const node_id_mapping )

Finds ghost nodes and non-linear element ghost nodes by walking over the partition's elements. A ghost node is a node referenced by one of the partition's elements but owned by another partition.

Definition at line 127 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* elem : elements)
139 {
140 for (unsigned i = 0; i < elem->getNumberOfNodes(); i++)
141 {
142 auto const& n = 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 1060 of file NodeWiseMeshPartitioner.cpp.

1065{
1066 constexpr unsigned mat_id =
1067 0; // TODO: Material ID to be set from the mesh data
1068 const long nn = elem.getNumberOfNodes();
1069 elem_info[counter++] = mat_id;
1070 elem_info[counter++] = static_cast<long>(elem.getCellType());
1071 elem_info[counter++] = nn;
1072
1073 for (long i = 0; i < nn; i++)
1074 {
1075 auto const& n = *elem.getNode(i);
1076 elem_info[counter++] = local_node_ids.at(n.getID());
1077 }
1078}
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 1004 of file NodeWiseMeshPartitioner.cpp.

1006{
1007 return {
1008 static_cast<long>(oldConfig.node_rank_offset +
1009 offsets.node * sizeof(MeshLib::IO::NodeData)),
1010 // Offset the ending entry of the element integer variables of
1011 // the elements of this partition in the vector of elem_info.
1012 static_cast<long>(oldConfig.element_rank_offset +
1013 offsets.elements * sizeof(long)),
1014
1015 // The ghost element section is empty, so this offset never advances.
1016 // It is still part of the binary format and therefore written as 0.
1017 0L};
1018}
struct NodeData used for parallel reading and also partitioning
Definition NodeData.h:12

References ApplicationUtils::ConfigOffsets::element_rank_offset, ApplicationUtils::PartitionOffsets::elements, ApplicationUtils::PartitionOffsets::node, and ApplicationUtils::ConfigOffsets::node_rank_offset.

Referenced by writeConfigData().

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

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

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

668{
669 BaseLib::RunTime run_timer;
670 run_timer.start();
671 auto const partition_ids_per_element = computePartitionIDPerElement(
672 nodes_partition_ids, mesh.getElements(), bulk_node_ids);
673 INFO("partitionMesh(): Partition IDs per element computed in {:g} s",
674 run_timer.elapsed());
675
676 run_timer.start();
677 distributeNodesToPartitions(partitions, nodes_partition_ids,
678 mesh.getNodes(), bulk_node_ids);
679 INFO("partitionMesh(): distribute nodes to partitions took {:g} s",
680 run_timer.elapsed());
681
682 run_timer.start();
684 INFO(
685 "partitionMesh(): sorting [base nodes | higher order nodes] took {:g} "
686 "s",
687 run_timer.elapsed());
688
689 run_timer.start();
690 setNumberOfNodesInPartitions(partitions, mesh);
691 INFO(
692 "partitionMesh(): setting number of nodes and of all mesh base nodes "
693 "took {:g} s",
694 run_timer.elapsed());
695
696 run_timer.start();
697 distributeElementsIntoPartitions(partitions, mesh,
698 partition_ids_per_element);
699 INFO("partitionMesh(): distribute elements into partitions took {:g} s",
700 run_timer.elapsed());
701
702 run_timer.start();
704 partitions, mesh, nodes_partition_ids, bulk_node_ids);
705 INFO("partitionMesh(): determine / append ghost nodes took {:g} s",
706 run_timer.elapsed());
707}
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 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(), 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 438 of file NodeWiseMeshPartitioner.cpp.

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

575{
576 std::vector<MeshLib::Node const*> higher_order_nodes;
577 // after splitIntoBaseAndHigherOrderNodes() partition.nodes contains only
578 // base nodes
579 std::tie(partition.nodes, higher_order_nodes) =
581 partition.number_of_regular_base_nodes = partition.nodes.size();
582 std::copy(begin(higher_order_nodes), end(higher_order_nodes),
583 std::back_inserter(partition.nodes));
584 partition.number_of_regular_nodes = partition.nodes.size();
585}
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 587 of file NodeWiseMeshPartitioner.cpp.

589{
590 for (auto& partition : partitions)
591 {
593 }
594}
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 261 of file NodeWiseMeshPartitioner.cpp.

263{
264 auto const& opt_ip_meta_data_all =
266 for (auto const& [name, property] : properties)
267 {
268 auto const item_type = property->getMeshItemType();
269
271 {
272 continue;
273 }
274
275 // For special field data such as OGS_VERSION, IntegrationPointMetaData,
276 // etc., which are not "real" integration points:
277 if (property->getPropertyName().find("_ip") == std::string::npos)
278 {
279 continue;
280 }
281
282 auto const& ip_meta_data =
284 opt_ip_meta_data_all, property->getPropertyName());
285 auto countIntegrationPoints =
286 [&](std::vector<const MeshLib::Element*> const& elements)
287 {
288 std::size_t counter = 0;
289 for (auto const element : elements)
290 {
291 int const number_of_integration_points =
293 ip_meta_data, *element);
294 counter += number_of_integration_points;
295 }
296 return counter;
297 };
298
299 for (auto& p : partitions)
300 {
301 p.number_of_integration_points = countIntegrationPoints(p.elements);
302 }
303 return;
304 }
305}

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

598{
599 auto const number_of_mesh_base_nodes = mesh.computeNumberOfBaseNodes();
600 auto const number_of_mesh_all_nodes = mesh.getNumberOfNodes();
601 for (auto& partition : partitions)
602 {
603 partition.number_of_regular_nodes = partition.nodes.size();
604 partition.number_of_mesh_base_nodes = number_of_mesh_base_nodes;
605 partition.number_of_mesh_all_nodes = number_of_mesh_all_nodes;
606 }
607}

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

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

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::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
For each partition the number of its elements plus the number of all of their element integer variables.

Definition at line 1023 of file NodeWiseMeshPartitioner.cpp.

1025{
1026 auto const file_name_cfg = file_name_base + "_partitioned_msh_cfg" +
1027 std::to_string(partitions.size()) + ".bin";
1028 std::ofstream of_bin_cfg(file_name_cfg, std::ios::binary);
1029 if (!of_bin_cfg)
1030 {
1031 OGS_FATAL("Could not open file '{:s}' for output.", file_name_cfg);
1032 }
1033
1034 std::vector<long> partitions_element_offsets;
1035 partitions_element_offsets.reserve(partitions.size());
1036
1037 ConfigOffsets config_offsets = {0, 0, 0}; // 0 for first partition.
1038 for (const auto& partition : partitions)
1039 {
1040 partition.writeConfig(of_bin_cfg);
1041
1042 config_offsets.writeConfig(of_bin_cfg);
1043 auto const& partition_offsets = computePartitionOffsets(partition);
1044 config_offsets =
1045 incrementConfigOffsets(config_offsets, partition_offsets);
1046
1047 partitions_element_offsets.push_back(partition_offsets.elements);
1048 }
1049
1050 return partitions_element_offsets;
1051}
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 & element_offsets )

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

Parameters
file_name_baseThe prefix of the file name.
partitionsPartitions vector.
element_offsetsPer-partition sizes of the element-info vectors, i.e. the number of elements plus the number of their element integer variables.

Definition at line 1101 of file NodeWiseMeshPartitioner.cpp.

1104{
1105 const std::string npartitions_str = std::to_string(partitions.size());
1106
1107 auto const file_name_ele =
1108 file_name_base + "_partitioned_msh_ele" + npartitions_str + ".bin";
1109 std::ofstream element_info_os(file_name_ele, std::ios::binary);
1110 if (!element_info_os)
1111 {
1112 OGS_FATAL("Could not open file '{:s}' for output.", file_name_ele);
1113 }
1114
1115 // Ghost elements are no longer used. The ghost element file is still
1116 // created, but left empty, to keep the binary file format compatible.
1117 auto const file_name_ele_g =
1118 file_name_base + "_partitioned_msh_ele_g" + npartitions_str + ".bin";
1119 std::ofstream ghost_element_info_os(file_name_ele_g, std::ios::binary);
1120 if (!ghost_element_info_os)
1121 {
1122 OGS_FATAL("Could not open file '{:s}' for output.", file_name_ele_g);
1123 }
1124
1125 for (std::size_t i = 0; i < partitions.size(); i++)
1126 {
1127 const auto& partition = partitions[i];
1128 auto const local_node_ids = enumerateLocalNodeIds(partition.nodes);
1129
1130 auto writeElementData =
1131 [&local_node_ids](
1132 std::vector<MeshLib::Element const*> const& elements,
1133 long const element_offsets,
1134 std::ofstream& output_stream)
1135 {
1136 long counter = elements.size();
1137 std::vector<long> ele_info(element_offsets);
1138
1139 for (std::size_t j = 0; j < elements.size(); j++)
1140 {
1141 const auto* elem = elements[j];
1142 ele_info[j] = counter;
1143 getElementIntegerVariables(*elem, local_node_ids, ele_info,
1144 counter);
1145 }
1146 // Write vector data of elements
1147 output_stream.write(reinterpret_cast<const char*>(ele_info.data()),
1148 ele_info.size() * sizeof(long));
1149 };
1150
1151 writeElementData(partition.elements, element_offsets[i],
1152 element_info_os);
1153 }
1154}
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 1160 of file NodeWiseMeshPartitioner.cpp.

1163{
1164 auto const file_name = file_name_base + "_partitioned_msh_nod" +
1165 std::to_string(partitions.size()) + ".bin";
1166 std::ofstream os(file_name, std::ios::binary);
1167 if (!os)
1168 {
1169 OGS_FATAL("Could not open file '{:s}' for output.", file_name);
1170 }
1171
1172 for (const auto& partition : partitions)
1173 {
1174 partition.writeNodes(os, global_node_ids);
1175 }
1176}

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

917{
918 auto const number_of_properties =
919 partitioned_properties.size(mesh_item_type);
920 if (number_of_properties == 0)
921 {
922 return;
923 }
924
925 auto const file_name_infix = toString(mesh_item_type);
926
927 auto const file_name_cfg = file_name_base + "_partitioned_" +
928 file_name_infix + "_properties_cfg" +
929 std::to_string(partitions.size()) + ".bin";
930 std::ofstream out(file_name_cfg, std::ios::binary);
931 if (!out)
932 {
933 OGS_FATAL("Could not open file '{:s}' for output.", file_name_cfg);
934 }
935
936 auto const file_name_val = file_name_base + "_partitioned_" +
937 file_name_infix + "_properties_val" +
938 std::to_string(partitions.size()) + ".bin";
939 std::ofstream out_val(file_name_val, std::ios::binary);
940 if (!out_val)
941 {
942 OGS_FATAL("Could not open file '{:s}' for output.", file_name_val);
943 }
944
945 BaseLib::writeValueBinary(out, number_of_properties);
946
948 partitioned_properties,
949 [&](auto type, auto const& property)
950 {
952 dynamic_cast<MeshLib::PropertyVector<decltype(type)> const*>(
953 property),
954 mesh_item_type, out_val, out);
955 });
956
957 unsigned long offset = 0;
958 for (const auto& partition : partitions)
959 {
960 MeshLib::IO::PropertyVectorPartitionMetaData pvpmd{
961 offset, static_cast<unsigned long>(
962 partition.numberOfMeshItems(mesh_item_type))};
963 DBUG(
964 "Write meta data for node-based PropertyVector: global offset "
965 "{:d}, number of tuples {:d}",
966 pvpmd.offset, pvpmd.number_of_tuples);
968 offset += pvpmd.number_of_tuples;
969 }
970}
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 888 of file NodeWiseMeshPartitioner.cpp.

891{
892 if (pv == nullptr)
893 {
894 return false;
895 }
896 // skip property of different mesh item type. Return true, because this
897 // operation was successful.
898 if (pv->getMeshItemType() != mesh_item_type)
899 {
900 return true;
901 }
902
903 MeshLib::IO::PropertyVectorMetaData pvmd;
904 pvmd.property_name = pv->getPropertyName();
908 writePropertyVectorValues(out_val, *pv);
910 return true;
911}
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 881 of file NodeWiseMeshPartitioner.cpp.

883{
884 os.write(reinterpret_cast<const char*>(pv.data()), pv.size() * sizeof(T));
885}
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()};