OGS
LocalToGlobalIndexMap.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 <algorithm>
7#include <numeric>
8#include <unordered_set>
9
10namespace NumLib
11{
12
14 int const component_id) const
15{
16 return _variable_component_offsets[variable_id] + component_id;
17}
18
19template <typename ElementIterator>
21 ElementIterator first, ElementIterator last,
22 std::vector<MeshLib::Node*> const& nodes, std::size_t const mesh_id,
23 const int comp_id, const int comp_id_write)
24{
25 std::unordered_set<MeshLib::Node*> const set_nodes(nodes.begin(),
26 nodes.end());
27
28 // For each element find the global indices for node/element
29 // components.
30 for (ElementIterator e = first; e != last; ++e)
31 {
32 LineIndex indices;
33 indices.reserve((*e)->getNumberOfNodes());
34
35 for (auto* n = (*e)->getNodes();
36 n < (*e)->getNodes() + (*e)->getNumberOfNodes();
37 ++n)
38 {
39 // Check if the element's node is in the given list of nodes.
40 if (set_nodes.find(*n) == set_nodes.end())
41 {
42 continue;
43 }
45 (*n)->getID());
46 indices.push_back(_mesh_component_map.getGlobalIndex(l, comp_id));
47 }
48
49 indices.shrink_to_fit();
50 _rows((*e)->getID(), comp_id_write) = std::move(indices);
51 }
52}
53
54template <typename ElementIterator>
56 ElementIterator first, ElementIterator last,
57 std::vector<MeshLib::Node*> const& nodes, std::size_t const mesh_id,
58 const int comp_id, const int comp_id_write)
59{
60 _rows.resize(std::distance(first, last), _mesh_subsets.size());
61
62 std::unordered_set<MeshLib::Node*> const set_nodes(nodes.begin(),
63 nodes.end());
64
65 // For each element find the global indices for node/element
66 // components.
67 std::size_t elem_id = 0;
68 for (ElementIterator e = first; e != last; ++e, ++elem_id)
69 {
70 LineIndex indices;
71 indices.reserve((*e)->getNumberOfNodes());
72
73 for (auto* n = (*e)->getNodes();
74 n < (*e)->getNodes() + (*e)->getNumberOfNodes();
75 ++n)
76 {
77 // Check if the element's node is in the given list of nodes.
78 if (set_nodes.find(*n) == set_nodes.end())
79 {
80 continue;
81 }
83 (*n)->getID());
84 auto const global_index =
85 _mesh_component_map.getGlobalIndex(l, comp_id);
86 if (global_index == std::numeric_limits<GlobalIndexType>::max())
87 {
88 continue;
89 }
90 indices.push_back(global_index);
91 }
92
93 indices.shrink_to_fit();
94 _rows(elem_id, comp_id_write) = std::move(indices);
95 }
96}
97
99 std::vector<MeshLib::MeshSubset>&& mesh_subsets,
100 NumLib::ComponentOrder const order)
101 : LocalToGlobalIndexMap(std::move(mesh_subsets),
102 std::vector<int>(mesh_subsets.size(), 1), order)
103{
104}
105
107 std::vector<MeshLib::MeshSubset>&& mesh_subsets,
108 std::vector<int> const& vec_var_n_components,
109 NumLib::ComponentOrder const order)
110 : _mesh_subsets(std::move(mesh_subsets)),
112 _variable_component_offsets(BaseLib::sizesToOffsets(vec_var_n_components))
113{
114 // For each element of that MeshSubset save a line of global indices.
115 for (int variable_id = 0;
116 variable_id < static_cast<int>(vec_var_n_components.size());
117 ++variable_id)
118 {
119 for (int component_id = 0;
120 component_id < static_cast<int>(vec_var_n_components[variable_id]);
121 ++component_id)
122 {
123 auto const global_component_id =
124 getGlobalComponent(variable_id, component_id);
125
126 auto const& ms = _mesh_subsets[global_component_id];
127 std::size_t const mesh_id = ms.getMeshID();
128
129 findGlobalIndices(ms.elementsBegin(), ms.elementsEnd(),
130 ms.getNodes(), mesh_id, global_component_id,
131 global_component_id);
132 }
133 }
134}
135
137 std::vector<MeshLib::MeshSubset>&& mesh_subsets,
138 std::vector<int> const& vec_var_n_components,
139 std::vector<std::vector<MeshLib::Element*> const*> const& vec_var_elements,
140 NumLib::ComponentOrder const order)
141 : _mesh_subsets(std::move(mesh_subsets)),
143 _variable_component_offsets(BaseLib::sizesToOffsets(vec_var_n_components))
144{
145 assert(vec_var_n_components.size() == vec_var_elements.size());
146
147 // For each element of that MeshSubset save a line of global indices.
148
149 // _rows should be resized based on an element ID
150 std::size_t max_elem_id = 0;
151 for (std::vector<MeshLib::Element*> const* elements : vec_var_elements)
152 {
153 for (auto e : *elements)
154 {
155 max_elem_id = std::max(max_elem_id, e->getID());
156 }
157 }
158 _rows.resize(max_elem_id + 1, _mesh_subsets.size());
159
160 for (int variable_id = 0;
161 variable_id < static_cast<int>(vec_var_n_components.size());
162 ++variable_id)
163 {
164 std::vector<MeshLib::Element*> const& var_elements =
165 *vec_var_elements[variable_id];
166 for (int component_id = 0;
167 component_id < static_cast<int>(vec_var_n_components[variable_id]);
168 ++component_id)
169 {
170 auto const global_component_id =
171 getGlobalComponent(variable_id, component_id);
172
173 auto const& ms = _mesh_subsets[global_component_id];
174 std::size_t const mesh_id = ms.getMeshID();
175
177 var_elements.cbegin(), var_elements.cend(), ms.getNodes(),
178 mesh_id, global_component_id, global_component_id);
179 }
180 }
181}
182
184 std::vector<MeshLib::MeshSubset>&& mesh_subsets,
185 std::vector<int> const& global_component_ids,
186 std::vector<int> const& variable_component_offsets,
187 std::vector<MeshLib::Element*> const& elements,
188 NumLib::MeshComponentMap&& mesh_component_map,
190 : _mesh_subsets(std::move(mesh_subsets)),
191 _mesh_component_map(std::move(mesh_component_map)),
192 _variable_component_offsets(variable_component_offsets)
193{
194 // Each subset in the mesh_subsets represents a single component.
195 if (_mesh_subsets.size() != global_component_ids.size())
196 {
197 OGS_FATAL(
198 "Number of mesh subsets is not equal to number of components. "
199 "There are {:d} mesh subsets and {:d} components.",
200 _mesh_subsets.size(), global_component_ids.size());
201 }
202
203 for (int i = 0; i < static_cast<int>(global_component_ids.size()); ++i)
204 {
205 auto const& ms = _mesh_subsets[i];
206
207 // For all MeshSubset in mesh_subsets and each element of that
208 // MeshSubset save a line of global indices.
209 std::size_t const mesh_id = ms.getMeshID();
210
211 findGlobalIndices(elements.cbegin(), elements.cend(), ms.getNodes(),
212 mesh_id, global_component_ids[i], i);
213 }
214}
215
216std::unique_ptr<LocalToGlobalIndexMap>
218 int const variable_id,
219 std::vector<int> const& component_ids,
220 MeshLib::MeshSubset&& new_mesh_subset) const
221{
222 DBUG("Construct reduced local to global index map.");
223
224 if (component_ids.empty())
225 {
226 OGS_FATAL("Expected non-empty vector of component ids.");
227 }
228
229 // Elements of the new_mesh_subset's mesh.
230 std::vector<MeshLib::Element*> const& elements =
231 new_mesh_subset.getMesh().getElements();
232
233 // Create a subset of the current mesh component map.
234 std::vector<int> global_component_ids;
235
236 transform(cbegin(component_ids), cend(component_ids),
237 back_inserter(global_component_ids),
238 [&](auto const component_id)
239 { return getGlobalComponent(variable_id, component_id); });
240
241 auto mesh_component_map =
242 _mesh_component_map.getSubset(_mesh_subsets, new_mesh_subset);
243
244 // Create copies of the new_mesh_subset for each of the global components.
245 // The last component is moved after the for-loop.
246 std::vector<MeshLib::MeshSubset> all_mesh_subsets;
247 for (int i = 0; i < static_cast<int>(global_component_ids.size()) - 1; ++i)
248 {
249 all_mesh_subsets.emplace_back(new_mesh_subset);
250 }
251 all_mesh_subsets.emplace_back(std::move(new_mesh_subset));
252
253 return std::make_unique<LocalToGlobalIndexMap>(
254 std::move(all_mesh_subsets), global_component_ids,
255 _variable_component_offsets, elements, std::move(mesh_component_map),
257}
258
259std::unique_ptr<LocalToGlobalIndexMap>
261 MeshLib::MeshSubset&& new_mesh_subset) const
262{
263 DBUG("Construct reduced local to global index map.");
264
265 // Create a subset of the current mesh component map.
266 std::vector<int> global_component_ids;
267
268 for (int i = 0; i < getNumberOfGlobalComponents(); ++i)
269 {
270 global_component_ids.push_back(i);
271 }
272
273 // Elements of the new_mesh_subset's mesh.
274 std::vector<MeshLib::Element*> const& elements =
275 new_mesh_subset.getMesh().getElements();
276
277 auto mesh_component_map =
278 _mesh_component_map.getSubset(_mesh_subsets, new_mesh_subset);
279
280 // Create copies of the new_mesh_subset for each of the global components.
281 // The last component is moved after the for-loop.
282 std::vector<MeshLib::MeshSubset> all_mesh_subsets;
283 for (int i = 0; i < static_cast<int>(global_component_ids.size()) - 1; ++i)
284 {
285 all_mesh_subsets.emplace_back(new_mesh_subset);
286 }
287 all_mesh_subsets.emplace_back(std::move(new_mesh_subset));
288
289 return std::make_unique<LocalToGlobalIndexMap>(
290 std::move(all_mesh_subsets), global_component_ids,
291 _variable_component_offsets, elements, std::move(mesh_component_map),
293}
294
296{
297 return _mesh_component_map.dofSizeWithGhosts();
298}
299
301{
302 return _mesh_component_map.dofSizeWithoutGhosts();
303}
304
306{
307 return static_cast<int>(_variable_component_offsets.size()) - 1;
308}
309
311{
312 assert(variable_id < getNumberOfVariables());
313 return _variable_component_offsets[variable_id + 1] -
314 _variable_component_offsets[variable_id];
315}
316
321
323{
324 return _rows.rows();
325}
326
328 std::size_t const mesh_item_id, const int global_component_id) const
329{
330 return RowColumnIndices(_rows(mesh_item_id, global_component_id),
331 _columns(mesh_item_id, global_component_id));
332}
333
335 std::size_t const mesh_item_id) const
336{
337 std::size_t ndof = 0;
338
339 for (Table::Index c = 0; c < _rows.cols(); ++c)
340 {
341 ndof += _rows(mesh_item_id, c).size();
342 }
343
344 return ndof;
345}
346
348 std::size_t const mesh_item_id) const
349{
350 std::size_t n = 0;
351 for (Table::Index c = 0; c < _rows.cols(); ++c)
352 {
353 if (!_rows(mesh_item_id, c).empty())
354 {
355 n++;
356 }
357 }
358 return n;
359}
360
362 std::size_t const mesh_item_id) const
363{
364 std::vector<int> vec;
365 for (int i = 0; i < getNumberOfVariables(); i++)
366 {
367 for (int j = 0; j < getNumberOfVariableComponents(i); j++)
368 {
369 auto comp_id = getGlobalComponent(i, j);
370 if (!_rows(mesh_item_id, comp_id).empty())
371 {
372 vec.push_back(i);
373 }
374 }
375 }
376 std::sort(vec.begin(), vec.end());
377 vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
378
379 return vec;
380}
381
383 MeshLib::Location const& l,
384 int const variable_id,
385 int const component_id) const
386{
387 auto const c = getGlobalComponent(variable_id, component_id);
388 return _mesh_component_map.getGlobalIndex(l, c);
389}
390
392 MeshLib::Location const& l, int const global_component_id) const
393{
394 return _mesh_component_map.getGlobalIndex(l, global_component_id);
395}
396
398std::vector<GlobalIndexType> LocalToGlobalIndexMap::getGlobalIndices(
399 const MeshLib::Location& l) const
400{
401 return _mesh_component_map.getGlobalIndices(l);
402}
403
405std::vector<GlobalIndexType> const& LocalToGlobalIndexMap::getGhostIndices()
406 const
407{
408 return _mesh_component_map.getGhostIndices();
409}
410
414 MeshLib::Location const& l, std::size_t const comp_id,
415 std::size_t const range_begin, std::size_t const range_end) const
416{
417 return _mesh_component_map.getLocalIndex(l, comp_id, range_begin,
418 range_end);
419}
420
422 int const variable_id, int const component_id) const
423{
424 return getMeshSubset(getGlobalComponent(variable_id, component_id));
425}
426
428 int const global_component_id) const
429{
430 return _mesh_subsets[global_component_id];
431}
432
433#ifndef NDEBUG
434std::ostream& operator<<(std::ostream& os, LocalToGlobalIndexMap const& map)
435{
436 std::size_t const max_lines = 10;
437 std::size_t lines_printed = 0;
438
439 os << "Rows of the local to global index map; " << map._rows.size()
440 << " rows\n";
441 for (std::size_t e = 0; e < map.size(); ++e)
442 {
443 os << "== e " << e << " ==\n";
444 for (int c = 0; c < map.getNumberOfGlobalComponents(); ++c)
445 {
446 auto const& line = map._rows(e, c);
447
448 os << "c" << c << " { ";
449 std::copy(line.cbegin(), line.cend(),
450 std::ostream_iterator<std::size_t>(os, " "));
451 os << " }\n";
452 }
453
454 if (lines_printed++ > max_lines)
455 {
456 os << "...\n";
457 break;
458 }
459 }
460
461 os << "Mesh component map:\n" << map._mesh_component_map;
462 return os;
463}
464#endif // NDEBUG
465
466} // namespace NumLib
#define OGS_FATAL(...)
Definition Error.h:19
GlobalMatrix::IndexType GlobalIndexType
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
A subset of nodes on a single mesh.
Definition MeshSubset.h:17
RowColumnIndices operator()(std::size_t const mesh_item_id, const int global_component_id) const
std::size_t getNumberOfElementDOF(std::size_t const mesh_item_id) const
LocalToGlobalIndexMap(std::vector< MeshLib::MeshSubset > &&mesh_subsets, NumLib::ComponentOrder const order)
std::vector< MeshLib::MeshSubset > _mesh_subsets
A vector of mesh subsets for each process variables' components.
int getGlobalComponent(int const variable_id, int const component_id) const
NumLib::MeshComponentMap _mesh_component_map
MathLib::RowColumnIndices< GlobalIndexType > RowColumnIndices
GlobalIndexType getGlobalIndex(MeshLib::Location const &l, int const variable_id, int const component_id) const
void findGlobalIndicesWithElementID(ElementIterator first, ElementIterator last, std::vector< MeshLib::Node * > const &nodes, std::size_t const mesh_id, const int comp_id, const int comp_id_write)
std::vector< int > const _variable_component_offsets
int getNumberOfVariableComponents(int variable_id) const
std::unique_ptr< LocalToGlobalIndexMap > deriveBoundaryConstrainedMap(int const variable_id, std::vector< int > const &component_ids, MeshLib::MeshSubset &&new_mesh_subset) const
MeshLib::MeshSubset const & getMeshSubset(int const variable_id, int const component_id) const
std::size_t getNumberOfElementComponents(std::size_t const mesh_item_id) const
void findGlobalIndices(ElementIterator first, ElementIterator last, std::vector< MeshLib::Node * > const &nodes, std::size_t const mesh_id, const int comp_id, const int comp_id_write)
GlobalIndexType getLocalIndex(MeshLib::Location const &l, std::size_t const comp_id, std::size_t const range_begin, std::size_t const range_end) const
std::vector< GlobalIndexType > const & getGhostIndices() const
Get ghost indices, forwarded from MeshComponentMap.
RowColumnIndices::LineIndex LineIndex
std::vector< GlobalIndexType > getGlobalIndices(const MeshLib::Location &l) const
Forwards the respective method from MeshComponentMap.
std::vector< int > getElementVariableIDs(std::size_t const mesh_item_id) const
Multidirectional mapping between mesh entities and degrees of freedom.
ComponentOrder
Ordering of components in global matrix/vector.
std::ostream & operator<<(std::ostream &os, LocalToGlobalIndexMap const &map)