6#include <range/v3/algorithm/equal.hpp>
7#include <range/v3/range/conversion.hpp>
8#include <unordered_map>
27 auto const& nodes = subdomain_mesh.
getNodes();
28 std::vector<MathLib::Point3dWithID*> subdomain_points{begin(nodes),
31 auto const& bulk_node_ids =
37 "Expected to find exactly one node in the bulk mesh for each node "
38 "of the subdomain; Found {:d} nodes in the bulk mesh out of {:d} "
39 "nodes in the subdomain.",
50 std::vector<std::size_t>
const& node_ids,
51 std::vector<std::vector<std::size_t>>
const& connected_element_ids_per_node)
64 auto const& smallest_elements =
65 connected_element_ids_per_node[*std::min_element(
66 begin(node_ids), end(node_ids),
67 [&connected_element_ids_per_node](std::size_t
const a,
70 return connected_element_ids_per_node[a].size() <
71 connected_element_ids_per_node[b].size();
74 std::vector<std::size_t> element_ids;
75 for (
auto const element_id : smallest_elements)
77 bool const shared_by_all = std::all_of(
78 begin(node_ids), end(node_ids),
79 [&connected_element_ids_per_node,
80 element_id](std::size_t
const node_id)
82 auto const& elements = connected_element_ids_per_node[node_id];
83 return std::find(begin(elements), end(elements), element_id) !=
88 element_ids.push_back(element_id);
94 std::sort(element_ids.begin(), element_ids.end(),
95 std::greater<std::size_t>());
109 std::vector<std::vector<std::size_t>> bulk_element_ids_map(
113 std::vector<std::vector<std::size_t>> connected_element_ids_per_node(
117 connected_element_ids_per_node[node_id] =
122 auto const& elements = subdomain_mesh.
getElements();
123#pragma omp parallel for
124 for (std::ptrdiff_t j = 0; j < std::ssize(elements); ++j)
126 auto*
const e = elements[j];
127 std::vector<std::size_t> element_node_ids(e->getNumberOfBaseNodes());
128 for (
unsigned n = 0; n < e->getNumberOfBaseNodes(); ++n)
132 std::vector<std::size_t> element_node_ids_bulk(
133 e->getNumberOfBaseNodes());
134 std::transform(begin(element_node_ids), end(element_node_ids),
135 begin(element_node_ids_bulk),
136 [&bulk_node_ids](std::size_t
const id)
137 {
return bulk_node_ids[id]; });
140 element_node_ids_bulk, connected_element_ids_per_node);
142 if (bulk_element_ids.empty())
144 ERR(
"No element could be found for the subdomain element {:d}. "
145 "Corresponding bulk mesh node ids are:",
147 for (
auto const i : element_node_ids_bulk)
152 "Expect at least one element to be found in the bulk mesh.");
155 bulk_element_ids_map[e->getID()] = std::move(bulk_element_ids);
158 return bulk_element_ids_map;
164 std::vector<std::size_t>
const& values,
168 const bool property_name_exists =
170 if (!properties.existsPropertyVector<std::size_t>(property_name,
173 if (property_name_exists)
175 if (!force_overwrite)
178 "A property named '{:s}' already exists on mesh '{:s}', "
179 "but it has a different mesh item type or number of "
180 "components. Use force overwrite to replace it.",
181 property_name, mesh.
getName());
185 "A property named '{:s}' exists on mesh '{:s}' with a "
186 "different mesh item type or number of components. "
188 property_name, mesh.
getName());
189 properties.removePropertyVector(property_name);
192 addPropertyToMesh<std::size_t>(mesh, property_name, mesh_item_type, 1,
200 auto& original_property =
201 *properties.getPropertyVector<std::size_t>(property_name);
202 if (ranges::equal(original_property, values))
205 "There is already a '{:s}' property present in the subdomain mesh "
206 "'{:s}' and it is equal to the newly computed values.",
207 property_name, mesh.
getName());
215 "There is already a '{:s}' property present in the subdomain mesh "
216 "'{:s}' and it is not equal to the newly computed values.",
220 if (!force_overwrite)
222 OGS_FATAL(
"The force overwrite flag was not specified, exiting.");
225 INFO(
"Overwriting '{:s}' property.", property_name);
226 original_property.assign(values);
235 bool const force_overwrite =
false)
239 auto const& bulk_node_ids =
240 identifySubdomainMeshNodes(subdomain_mesh, mesh_node_searcher);
241 INFO(
"identifySubdomainMesh(): identifySubdomainMeshNodes took {:g} s",
244 updateOrCheckExistingSubdomainProperty(
249 auto const& bulk_element_ids =
250 identifySubdomainMeshElements(subdomain_mesh, bulk_mesh);
251 INFO(
"identifySubdomainMesh(): identifySubdomainMeshElements took {:g} s",
259 bool const all_single_elements =
260 all_of(begin(bulk_element_ids), end(bulk_element_ids),
261 [](std::vector<std::size_t>
const& v) {
return v.size() == 1; });
262 if (all_single_elements)
266 std::vector<std::size_t> unique_bulk_element_ids;
267 unique_bulk_element_ids.reserve(bulk_element_ids.size());
268 transform(begin(bulk_element_ids), end(bulk_element_ids),
269 back_inserter(unique_bulk_element_ids),
270 [](std::vector<std::size_t>
const& v) {
return v[0]; });
272 updateOrCheckExistingSubdomainProperty(
283 std::vector<std::size_t> flat_bulk_element_ids;
284 flat_bulk_element_ids.reserve(2 * bulk_element_ids.size());
285 std::vector<std::size_t> number_of_bulk_element_ids;
286 number_of_bulk_element_ids.reserve(bulk_element_ids.size());
288 for (
auto const& v : bulk_element_ids)
297 number_of_bulk_element_ids.push_back(v.size());
298 flat_bulk_element_ids.insert(end(flat_bulk_element_ids), begin(v),
302 updateOrCheckExistingSubdomainProperty(
303 subdomain_mesh,
"number_bulk_elements", number_of_bulk_element_ids,
305 updateOrCheckExistingSubdomainProperty(
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
double elapsed() const
Get the elapsed time in seconds.
void start()
Start the timer.
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Properties & getProperties()
const std::string getName() const
Get name of the mesh.
std::size_t getNumberOfNodes() const
Get the number of nodes.
std::vector< Element const * > const & getElementsConnectedToNode(std::size_t node_id) const
std::size_t getNumberOfElements() const
Get the number of elements.
bool hasPropertyVector(std::string_view name) const
constexpr ranges::views::view_closure ids
For an element of a range view return its id.
constexpr std::string_view getBulkIDString(MeshItemType mesh_item_type)
std::size_t getNodeIndex(Element const &element, unsigned const idx)
PropertyVector< std::size_t > const * bulkNodeIDs(Mesh const &mesh)
std::vector< std::size_t > identifySubdomainMeshNodes(MeshLib::Mesh const &subdomain_mesh, MeshGeoToolsLib::MeshNodeSearcher const &mesh_node_searcher)
void updateOrCheckExistingSubdomainProperty(MeshLib::Mesh &mesh, std::string_view property_name, std::vector< std::size_t > const &values, MeshLib::MeshItemType const mesh_item_type, bool const force_overwrite)
Updates or checks the existing mesh's property with the given values.
std::vector< std::vector< std::size_t > > identifySubdomainMeshElements(MeshLib::Mesh const &subdomain_mesh, MeshLib::Mesh const &bulk_mesh)
std::vector< std::size_t > findElementsInMesh(std::vector< std::size_t > const &node_ids, std::vector< std::vector< std::size_t > > const &connected_element_ids_per_node)