OGS
OverwriteMeshFieldDataByMaterialIDs.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <cstddef>
7#include <vector>
8
9#include "BaseLib/Error.h"
10#include "BaseLib/Logging.h"
13#include "MeshLib/Mesh.h"
16
17namespace MeshToolsLib
18{
19namespace
20{
26{
29 std::size_t slot_begin;
30 std::size_t slot_end;
31};
32
37std::vector<WriteGroup> collectWriteGroups(
38 InitialConditionDataSet const& initial_condition,
40 MeshLib::Properties const& properties)
41{
42 auto const& mesh = *initial_condition.mesh;
43 auto const& element_ids =
44 initial_condition.element_ids_for_selected_materials;
45
46 std::vector<WriteGroup> groups;
47
48 switch (initial_condition.mesh_item_type)
49 {
51 {
52 auto const element_ip_data_offsets =
54 pv, properties);
55 // getIntegrationPointDataOffsetsOfMeshElements() returns an empty
56 // vector for a property whose name does not contain "_ip" (it is
57 // then not treated as integration-point data). Indexing it by
58 // element id below would be an out-of-bounds access.
59 if (element_ip_data_offsets.empty())
60 {
62 "overwrite_mesh_data: integration-point property '{:s}' "
63 "carries no integration-point data offsets. Only fields "
64 "whose name contains '_ip' are treated as "
65 "integration-point data.",
66 initial_condition.variable_name);
67 }
68 auto const n = pv.getNumberOfGlobalComponents();
69 groups.reserve(element_ids.size());
70 for (auto const element_id : element_ids)
71 {
72 // A parameter is evaluated once per element at the centroid and
73 // written to all of the element's integration points (a single
74 // write group spanning them). This is exact for the intended
75 // constant-per-material use case. Do not turn this into a
76 // per-integration-point evaluation without also reproducing the
77 // exact integration rule and point ordering used by the process
78 // local assembler that wrote this field: computing the points
79 // in a different order would associate values with the wrong
80 // slots.
82 pos.setElementID(element_id);
84 MeshLib::getCenterOfGravity(*mesh.getElement(element_id)));
85 // The offsets are flat (already multiplied by the number of
86 // components); divide to obtain slot (integration point)
87 // indices.
88 groups.push_back({pos, element_ip_data_offsets[element_id] / n,
89 element_ip_data_offsets[element_id + 1] / n});
90 }
91 break;
92 }
94 {
95 groups.reserve(element_ids.size());
96 for (auto const element_id : element_ids)
97 {
99 pos.setElementID(element_id);
100 pos.setCoordinates(
101 MeshLib::getCenterOfGravity(*mesh.getElement(element_id)));
102 groups.push_back({pos, element_id, element_id + 1});
103 }
104 break;
105 }
107 {
108 for (auto const element_id : element_ids)
109 {
110 for (auto const* node : mesh.getElement(element_id)->nodes())
111 {
112 std::size_t const node_id = node->getID();
113 // Evaluate the parameter at the node position, not the
114 // element centre.
115 groups.push_back(
116 {ParameterLib::SpatialPosition{node_id, {}, *node},
117 node_id, node_id + 1});
118 }
119 }
120 break;
121 }
122 default:
123 OGS_FATAL(
124 "The mesh item type of the initial condition for property "
125 "'{:s}' is not supported. Only integration point, cell, and "
126 "node data are supported.",
127 initial_condition.variable_name);
128 }
129
130 return groups;
131}
132} // namespace
133
135 std::vector<InitialConditionDataSet>& data_initial_conditions)
136{
137 // First pass: snapshot the original field data for every non-parameter
138 // (i.e. take_original) condition before any writes happen, so that a later
139 // take_original can restore the original values even if an earlier set
140 // overwrote overlapping slots.
141 for (auto& initial_condition : data_initial_conditions)
142 {
143 auto const& property_name = initial_condition.variable_name;
144 MeshLib::Properties& properties =
145 initial_condition.mesh->getProperties();
146
147 if (!properties.hasPropertyVector<double>(
148 property_name, initial_condition.mesh_item_type))
149 {
150 OGS_FATAL(
151 "overwrite_mesh_data: property '{:s}' of the requested mesh "
152 "item type was not found on the mesh.",
153 property_name);
154 }
155
156 // With a parameter the values are computed, so no snapshot is needed.
157 if (initial_condition.parameter)
158 {
159 continue;
160 }
161
162 if (!initial_condition.property_copy)
163 {
164 auto* pv = properties.getPropertyVector<double>(property_name);
165 initial_condition.property_copy.reset(
166 static_cast<MeshLib::PropertyVector<double> const*>(
167 pv->clone({})));
168 DBUG("created property copy for: {}", property_name);
169 }
170 }
171
172 // Second pass: overwrite the selected slots for each condition.
173 for (auto const& initial_condition : data_initial_conditions)
174 {
175 MeshLib::Properties& properties =
176 initial_condition.mesh->getProperties();
177 auto& pv = *properties.getPropertyVector<double>(
178 initial_condition.variable_name);
179 auto const n_components = pv.getNumberOfGlobalComponents();
180
181 auto const groups =
182 collectWriteGroups(initial_condition, pv, properties);
183
184 bool const has_parameter = initial_condition.parameter != nullptr;
185 // Either a parameter provides the values or a snapshot was taken in the
186 // first pass; one of the two must hold. Without a snapshot copy_data
187 // below is null and would be dereferenced.
188 if (!has_parameter && !initial_condition.property_copy)
189 {
190 OGS_FATAL(
191 "overwrite_mesh_data: neither a parameter nor an original-data "
192 "snapshot is available for property '{:s}'. This is an "
193 "internal "
194 "inconsistency.",
195 initial_condition.variable_name);
196 }
197 auto const* const copy_data =
198 has_parameter ? nullptr
199 : static_cast<double const*>(
200 initial_condition.property_copy->data());
201
202 for (auto const& group : groups)
203 {
204 std::vector<double> param_values;
205 if (has_parameter)
206 {
207 param_values = (*initial_condition.parameter)(0.0, group.pos);
208 // The parameter is looked up with num_components == 0 (the
209 // component count is only known here), so validate it now:
210 // reading n_components values from a shorter parameter result
211 // would be an out-of-bounds access.
212 if (static_cast<int>(param_values.size()) != n_components)
213 {
214 OGS_FATAL(
215 "overwrite_mesh_data: the parameter used to set "
216 "property '{:s}' returns {:d} component(s), but the "
217 "property has {:d} component(s).",
218 initial_condition.variable_name, param_values.size(),
219 n_components);
220 }
221 }
222
223 for (std::size_t slot = group.slot_begin; slot < group.slot_end;
224 ++slot)
225 {
226 double const* const source =
227 has_parameter ? param_values.data()
228 : copy_data + slot * n_components;
229 for (int comp = 0; comp < n_components; ++comp)
230 {
231 pv[slot * n_components + comp] = source[comp];
232 }
233 }
234 }
235 }
236}
237} // namespace MeshToolsLib
#define OGS_FATAL(...)
Definition Error.h:10
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
bool hasPropertyVector(std::string_view name) const
PropertyVector< T > const * getPropertyVector(std::string_view name) const
int getNumberOfGlobalComponents() const
void setCoordinates(MathLib::Point3d const &coordinates)
void setElementID(std::size_t element_id)
MathLib::Point3d getCenterOfGravity(Element const &element)
Calculates the center of gravity for the mesh element.
Definition Element.cpp:131
std::vector< WriteGroup > collectWriteGroups(InitialConditionDataSet const &initial_condition, MeshLib::PropertyVector< double > const &pv, MeshLib::Properties const &properties)
void overwriteMeshFieldDataByMaterialIDs(std::vector< InitialConditionDataSet > &data_initial_conditions)
std::vector< std::size_t > getIntegrationPointDataOffsetsOfMeshElements(std::vector< MeshLib::Element * > const &mesh_elements, MeshLib::PropertyVectorBase const &pv, MeshLib::Properties const &properties)
ParameterLib::SpatialPosition pos
Position at which a parameter is evaluated for this group.