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