IOSS 2.0
Loading...
Searching...
No Matches
Ioss_Decomposition.h
Go to the documentation of this file.
1/*
2 * Copyright(C) 1999-2024 National Technology & Engineering Solutions
3 * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
4 * NTESS, the U.S. Government retains certain rights in this software.
5 *
6 * See packages/seacas/LICENSE for details
7 */
8#pragma once
9
10#include "ioss_export.h"
11
12#include "Ioss_CodeTypes.h"
13#include "Ioss_Map.h"
14#include "Ioss_ParallelUtils.h"
16#include <algorithm>
17#include <cassert>
18#include <map>
19#include <string>
20#include <vector>
21
22#include "Ioss_ParallelUtils.h"
23#include "Ioss_Utils.h"
24
25#if !defined(NO_PARMETIS_SUPPORT)
26#include <parmetis.h>
27#endif
28
29#if !defined(NO_ZOLTAN_SUPPORT)
30#undef MPICPP
31#include <zoltan_cpp.h>
32#endif
33
34#define DC_USE_VECTOR
35#if defined DC_USE_HOPSCOTCH
36#include <hopscotch_map.h>
37#elif defined DC_USE_ROBIN
38#include <robin_map.h>
39#endif
40
41namespace Ioss {
42 IOSS_EXPORT const std::vector<std::string> &valid_decomp_methods();
43
44 class IOSS_EXPORT BlockDecompositionData
45 {
46 public:
48
49 IOSS_NODISCARD const std::string &name() const { return name_; }
50 IOSS_NODISCARD int zone() const { return zone_; }
51 IOSS_NODISCARD int section() const { return section_; }
52 IOSS_NODISCARD int64_t id() const { return id_; }
53 IOSS_NODISCARD size_t file_count() const { return fileCount; }
54 IOSS_NODISCARD size_t ioss_count() const { return iossCount; }
55 IOSS_NODISCARD size_t global_count() const { return globalCount; }
56
57 std::string name_{};
58 int zone_{0};
59 int section_{0};
60
61 size_t fileSectionOffset{0}; // In partial read, where start
62 int64_t id_{0};
63 size_t fileCount{0};
64 size_t iossCount{0};
65 size_t globalCount{0};
66
67 size_t zoneNodeOffset{0};
68 std::string topologyType{"unknown"};
69 int nodesPerEntity{0};
70 int attributeCount{0};
71
72 // maps from file-block data to ioss-block data
73 // The local_map.size() elements starting at localIossOffset are local.
74 // ioss[localIossOffset+i] = file[local_map[i]];
75 size_t localIossOffset{0};
76 std::vector<int> localMap;
77
78 // Maps from file-block data to export list.
79 // export[i] = file[export_map[i]
80 std::vector<int> exportMap;
81 std::vector<int> exportCount;
82 std::vector<int> exportIndex;
83
84 // Maps from import data to ioss-block data.
85 // ioss[import_map[i] = local_map[i];
86 std::vector<int> importMap;
87 std::vector<int> importCount;
88 std::vector<int> importIndex;
89 };
90
91 class IOSS_EXPORT SetDecompositionData
92 {
93 public:
97
99 {
100 if (setComm_ != Ioss::ParallelUtils::comm_null()) {
101 MPI_Comm_free(&setComm_);
102 }
103 }
104
105 IOSS_NODISCARD const std::string &name() const { return name_; }
106 IOSS_NODISCARD const std::string &ss_name() const
107 {
108 return ss_name_.empty() ? name_ : ss_name_;
109 }
110 IOSS_NODISCARD int64_t id() const { return id_; }
111 IOSS_NODISCARD int zone() const { return zone_; }
112 IOSS_NODISCARD int section() const { return section_; }
113 IOSS_NODISCARD size_t file_count() const { return fileCount; }
114 IOSS_NODISCARD size_t ioss_count() const { return entitylist_map.size(); }
115 IOSS_NODISCARD size_t df_count() const { return distributionFactorCount; }
116
117 // contains global entity-list positions for all entities in this set on this processor.
118 std::vector<size_t> entitylist_map;
119 std::vector<bool> hasEntities; // T/F if this set exists on processor p
120
121 std::string name_{};
122 std::string ss_name_{};
123 int64_t id_{0};
124 int zone_{0}; // Zone of the element block that this set is on
125 int section_{0};
126 size_t fileCount{0}; // Number of nodes in nodelist for file decomposition
127 int root_{0}; // Lowest number processor that has nodes for this nodest
128 std::string topologyType{};
129 size_t parentBlockIndex{0};
130
131 int distributionFactorValsPerEntity{-1}; // number of df / element or node. -1 if nonconstant.
132 size_t distributionFactorCount{0};
133 double distributionFactorValue{
134 0.0}; // If distributionFactorConstant == true, the constant value
136 bool distributionFactorConstant{false}; // T if all distribution factors the same value.
137 };
138
139 class IOSS_EXPORT ElementBlockBatchOffset
140 {
141 public:
142 explicit ElementBlockBatchOffset(const std::vector<BlockDecompositionData> &data) : m_data(data)
143 {
144 }
145
149
150 IOSS_NODISCARD size_t get_ioss_element_size(const std::vector<int64_t> &blockSubsetIndex) const;
151
152 IOSS_NODISCARD std::vector<size_t>
153 get_ioss_offset(const std::vector<int64_t> &blockSubsetIndex,
154 const std::vector<int> &blockComponentCount) const;
155
156 IOSS_NODISCARD std::vector<size_t>
157 get_import_offset(const std::vector<int64_t> &blockSubsetIndex,
158 const std::vector<int> &blockComponentCount) const;
159
160 IOSS_NODISCARD size_t
161 get_connectivity_ioss_offset_size(const std::vector<int64_t> &blockSubsetIndex) const;
162
163 IOSS_NODISCARD std::vector<int>
164 get_connectivity_ioss_component_count(const std::vector<int64_t> &blockSubsetIndex) const;
165
166 private:
167 const std::vector<BlockDecompositionData> &m_data;
168
169 IOSS_NODISCARD size_t get_ioss_offset_size(const std::vector<int64_t> &blockSubsetIndex,
170 const std::vector<int> &blockComponentCount) const;
171
172 IOSS_NODISCARD std::vector<size_t>
173 get_connectivity_ioss_offset(const std::vector<int64_t> &blockSubsetIndex) const;
174
175 IOSS_NODISCARD std::vector<size_t>
176 get_connectivity_import_offset(const std::vector<int64_t> &blockSubsetIndex) const;
177 };
178
179 template <typename INT> class Decomposition
180 {
181 public:
183 Decomposition(Decomposition const &) = default;
187
190 IOSS_NODISCARD size_t ioss_node_count() const { return nodeGTL.size(); }
192 {
193 return localElementMap.size() + importElementMap.size();
194 }
195 IOSS_NODISCARD size_t file_node_count() const { return m_nodeCount; }
199
201 {
202 return (m_method == "RCB" || m_method == "RIB" || m_method == "HSFC" ||
203 m_method == "GEOM_KWAY" || m_method == "KWAY_GEOM" || m_method == "METIS_SFC");
204 }
205
206 void generate_entity_distributions(size_t global_node_count, size_t global_element_count);
207
208 // T/F if node with global index node owned by this processors ioss-decomp.
209 IOSS_NODISCARD bool i_own_node(size_t global_index) const
210 {
211 // global_index is 1-based index into global list of nodes [1..global_node_count]
212 return std::binary_search(nodeGTL.begin(), nodeGTL.end(), global_index);
213 }
214
215 // T/F if element with global index elem owned by this processors ioss-decomp.
216 IOSS_NODISCARD bool i_own_elem(size_t global_index) const
217 {
218 // global_index is 1-based index into global list of elements [1..global_element_count]
219#if defined(DC_USE_VECTOR)
220 return std::binary_search(
221 elemGTL.begin(), elemGTL.end(), std::pair<INT, INT>{global_index, 0},
222 [](const std::pair<INT, INT> &lhs, const std::pair<INT, INT> &val) -> bool {
223 return lhs.first < val.first;
224 });
225#else
226 return elemGTL.find(global_index) != elemGTL.end();
227#endif
228 }
229
230 IOSS_NODISCARD size_t node_global_to_local(size_t global_index) const
231 {
232 // global_index is 1-based index into global list of nodes [1..global_node_count]
233 // return value is 1-based index into local list of nodes on this
234 // processor (ioss-decomposition)
235 // Note that for 'int', equivalence and equality are the same, so
236 // lower_bound is OK here (EffectiveSTL, Item 19)
237 typename std::vector<INT>::const_iterator I =
238 lower_bound(nodeGTL.begin(), nodeGTL.end(), global_index);
239 assert(I != nodeGTL.end());
240 return std::distance(nodeGTL.begin(), I) + 1; // Convert to 1-based index.
241 }
242
243 IOSS_NODISCARD size_t elem_global_to_local(size_t global_index) const
244 {
245 // global_index is 1-based index into global list of elements [1..global_node_count]
246 // return value is 1-based index into local list of elements on this
247 // processor (ioss-decomposition)
248#if defined(DC_USE_VECTOR)
249 auto I = lower_bound(
250 elemGTL.begin(), elemGTL.end(), global_index,
251 [](const std::pair<INT, INT> &lhs, INT val) -> bool { return lhs.first < val; });
252 assert(I != elemGTL.end() && I->first == (INT)global_index);
253#else
254 auto I = elemGTL.find(global_index);
255#endif
256 assert(I != elemGTL.end());
257 assert(I->first == (INT)global_index);
258 return I->second;
259 }
260
261 void show_progress(const std::string &message) const
262 {
263 if (m_showProgress) {
265 pu.progress(message);
266 }
267 }
268
269 // Zero out some large arrays usually not needed after decomposition
271 void decompose_model(
272#if !defined(NO_ZOLTAN_SUPPORT)
273 Zoltan &zz,
274#endif
275 std::vector<BlockDecompositionData> &element_blocks);
276
277 void simple_decompose();
279 void guided_decompose();
280
281 void calculate_element_centroids(const std::vector<double> &x, const std::vector<double> &y,
282 const std::vector<double> &z);
283
284#if !defined(NO_ZOLTAN_SUPPORT)
285 void zoltan_decompose(Zoltan &zz);
286
287 void get_local_element_list(const ZOLTAN_ID_PTR &export_global_ids, size_t export_count);
288#endif
289
290#if !defined(NO_PARMETIS_SUPPORT)
291 void metis_decompose(idx_t *pointer, idx_t *adjacency,
292 std::vector<BlockDecompositionData> &el_blocks);
293
294 void internal_metis_decompose(std::vector<BlockDecompositionData> &el_blocks,
295 idx_t *element_dist, idx_t *pointer, idx_t *adjacency,
296 idx_t *elem_partition);
297#endif
298
299 void get_node_entity_proc_data(INT *entity_proc, const Ioss::MapContainer &node_map,
300 bool do_map) const
301 {
302 show_progress(__func__);
303 size_t j = 0;
304 if (do_map) {
305 for (size_t i = 0; i < m_nodeCommMap.size(); i += 2) {
306 INT local_id = m_nodeCommMap[i];
307 entity_proc[j++] = node_map[local_id];
308 entity_proc[j++] = m_nodeCommMap[i + 1];
309 }
310 }
311 else {
312 for (size_t i = 0; i < m_nodeCommMap.size(); i += 2) {
313 entity_proc[j++] = m_nodeCommMap[i + 0];
314 entity_proc[j++] = m_nodeCommMap[i + 1];
315 }
316 }
317 }
318
319 void get_element_block_communication(std::vector<BlockDecompositionData> &el_blocks);
321 void get_local_node_list();
323
324 // The following function is used if reading all element data on a
325 // processor instead of just an element blocks worth...
326 template <typename T>
327 void communicate_element_data(T *file_data, T *ioss_data, size_t comp_count) const
328 {
329 show_progress(__func__);
330 if (m_method == "LINEAR") {
331 assert(m_importPreLocalElemIndex == 0);
332 assert(exportElementMap.size() == 0);
333 assert(importElementMap.size() == 0);
334 // For "LINEAR" decomposition method, the `file_data` is the
335 // same as `ioss_data` Transfer all local data from file_data
336 // to ioss_data...
337 auto size = localElementMap.size() * comp_count;
338 std::copy(file_data, file_data + size, ioss_data);
339 return;
340 }
341
342 // Transfer the file-decomposition based data in 'file_data' to
343 // the ioss-decomposition based data in 'ioss_data'
344 std::vector<T> export_data(exportElementMap.size() * comp_count);
345 std::vector<T> import_data(importElementMap.size() * comp_count);
346
347 if (comp_count == 1) {
348 for (size_t i = 0; i < exportElementMap.size(); i++) {
349 size_t index = exportElementMap[i] - m_elementOffset;
350 export_data[i] = file_data[index];
351 }
352
353 // Transfer all local data from file_data to ioss_data...
354 for (size_t i = 0; i < localElementMap.size(); i++) {
355 size_t index = localElementMap[i];
356 ioss_data[m_importPreLocalElemIndex + i] = file_data[index];
357 }
358
359 // Get my imported data and send my exported data...
360 Ioss::MY_Alltoallv(export_data, exportElementCount, exportElementIndex, import_data,
362 show_progress("\tCommunication 1a finished");
363
364 // Copy the imported data into ioss_data...
365 // Some comes before the local data...
366 for (size_t i = 0; i < m_importPreLocalElemIndex; i++) {
367 ioss_data[i] = import_data[i];
368 }
369
370 // Some comes after the local data...
371 size_t offset = m_importPreLocalElemIndex + localElementMap.size();
372 for (size_t i = 0; i < importElementMap.size() - m_importPreLocalElemIndex; i++) {
373 ioss_data[offset + i] = import_data[m_importPreLocalElemIndex + i];
374 }
375 }
376 else {
377 for (size_t i = 0; i < exportElementMap.size(); i++) {
378 size_t index = exportElementMap[i] - m_elementOffset;
379 for (size_t j = 0; j < comp_count; j++) {
380 export_data[comp_count * i + j] = file_data[comp_count * index + j];
381 }
382 }
383
384 // Transfer all local data from file_data to ioss_data...
385 for (size_t i = 0; i < localElementMap.size(); i++) {
386 size_t index = localElementMap[i];
387 for (size_t j = 0; j < comp_count; j++) {
388 ioss_data[comp_count * (m_importPreLocalElemIndex + i) + j] =
389 file_data[comp_count * index + j];
390 }
391 }
392
393 std::vector<INT> export_count(exportElementCount.begin(), exportElementCount.end());
394 std::vector<INT> export_disp(exportElementIndex.begin(), exportElementIndex.end());
395 std::vector<INT> import_count(importElementCount.begin(), importElementCount.end());
396 std::vector<INT> import_disp(importElementIndex.begin(), importElementIndex.end());
397
398 for (int i = 0; i < m_processorCount; i++) {
399 export_count[i] *= comp_count;
400 export_disp[i] *= comp_count;
401 import_count[i] *= comp_count;
402 import_disp[i] *= comp_count;
403 }
404
405 // Get my imported data and send my exported data...
406 Ioss::MY_Alltoallv(export_data, export_count, export_disp, import_data, import_count,
407 import_disp, m_comm);
408 show_progress("\tCommunication 1b finished");
409
410 // Copy the imported data into ioss_data...
411 // Some comes before the local data...
412 for (size_t i = 0; i < m_importPreLocalElemIndex; i++) {
413 for (size_t j = 0; j < comp_count; j++) {
414 ioss_data[comp_count * i + j] = import_data[comp_count * i + j];
415 }
416 }
417
418 // Some comes after the local data...
419 size_t offset = m_importPreLocalElemIndex + localElementMap.size();
420 for (size_t i = 0; i < importElementMap.size() - m_importPreLocalElemIndex; i++) {
421 for (size_t j = 0; j < comp_count; j++) {
422 ioss_data[comp_count * (offset + i) + j] =
423 import_data[comp_count * (m_importPreLocalElemIndex + i) + j];
424 }
425 }
426 }
427 }
428
429 template <typename T>
430 void communicate_set_data(T *file_data, T *ioss_data, const SetDecompositionData &set,
431 size_t comp_count) const
432 {
433 show_progress(__func__);
434 std::vector<T> recv_data;
435
436 size_t size = set.file_count() * comp_count;
437 if (size == 0) {
438 return;
439 }
440
442 recv_data.resize(size);
443 if (m_processor == set.root_) {
444 std::copy(file_data, file_data + size, recv_data.begin());
445 }
446 // NOTE: This broadcast uses a split communicator, so possibly
447 // not all processors participating.
449 pu.broadcast(recv_data);
450 }
451 if (comp_count == 1) {
452 if (set.root_ == m_processor) {
453 for (size_t i = 0; i < set.ioss_count(); i++) {
454 size_t index = set.entitylist_map[i];
455 ioss_data[i] = file_data[index];
456 }
457 }
458 else {
459 // Receiving data from root...
460 for (size_t i = 0; i < set.ioss_count(); i++) {
461 size_t index = set.entitylist_map[i];
462 ioss_data[i] = recv_data[index];
463 }
464 }
465 }
466 else {
467 if (set.root_ == m_processor) {
468 for (size_t i = 0; i < set.ioss_count(); i++) {
469 size_t index = set.entitylist_map[i];
470 for (size_t j = 0; j < comp_count; j++) {
471 ioss_data[comp_count * i + j] = file_data[comp_count * index + j];
472 }
473 }
474 }
475 else {
476 // Receiving data from root...
477 for (size_t i = 0; i < set.ioss_count(); i++) {
478 size_t index = set.entitylist_map[i];
479 for (size_t j = 0; j < comp_count; j++) {
480 ioss_data[comp_count * i + j] = recv_data[comp_count * index + j];
481 }
482 }
483 }
484 }
485 }
486
487 template <typename T, typename U>
488 void communicate_block_data(T *file_data, U *ioss_data, const BlockDecompositionData &block,
489 size_t comp_count) const
490 {
491 show_progress(__func__);
492 if (m_method == "LINEAR") {
493 assert(block.localIossOffset == 0);
494 assert(block.exportMap.empty());
495 assert(block.importMap.empty());
496 // For "LINEAR" decomposition method, the `file_data` is the
497 // same as `ioss_data` Transfer all local data from file_data
498 // to ioss_data...
499 auto size = block.localMap.size() * comp_count;
500 std::copy(file_data, file_data + size, ioss_data);
501 return;
502 }
503
504 std::vector<U> exports;
505 exports.reserve(comp_count * block.exportMap.size());
506 std::vector<U> imports(comp_count * block.importMap.size());
507
508 if (comp_count == 1) {
509 for (int i : block.exportMap) {
510 exports.push_back(file_data[i]);
511 }
512
513 // Get my imported data and send my exported data...
514 Ioss::MY_Alltoallv(exports, block.exportCount, block.exportIndex, imports,
515 block.importCount, block.importIndex, m_comm);
516
517 // Map local and imported data to ioss_data.
518 for (size_t i = 0; i < block.localMap.size(); i++) {
519 ioss_data[i + block.localIossOffset] = file_data[block.localMap[i]];
520 }
521
522 for (size_t i = 0; i < block.importMap.size(); i++) {
523 ioss_data[block.importMap[i]] = imports[i];
524 }
525 }
526 else {
527 for (int i : block.exportMap) {
528 for (size_t j = 0; j < comp_count; j++) {
529 exports.push_back(file_data[i * comp_count + j]);
530 }
531 }
532
533 std::vector<int> export_count(block.exportCount.begin(), block.exportCount.end());
534 std::vector<int> export_disp(block.exportIndex.begin(), block.exportIndex.end());
535 std::vector<int> import_count(block.importCount.begin(), block.importCount.end());
536 std::vector<int> import_disp(block.importIndex.begin(), block.importIndex.end());
537
538 for (int i = 0; i < m_processorCount; i++) {
539 export_count[i] *= comp_count;
540 export_disp[i] *= comp_count;
541 import_count[i] *= comp_count;
542 import_disp[i] *= comp_count;
543 }
544
545 // Get my imported data and send my exported data...
546 Ioss::MY_Alltoallv(exports, export_count, export_disp, imports, import_count, import_disp,
547 m_comm);
548 show_progress("\tCommunication 1 finished");
549
550 // Map local and imported data to ioss_data.
551 for (size_t i = 0; i < block.localMap.size(); i++) {
552 for (size_t j = 0; j < comp_count; j++) {
553 ioss_data[(i + block.localIossOffset) * comp_count + j] =
554 file_data[block.localMap[i] * comp_count + j];
555 }
556 }
557
558 for (size_t i = 0; i < block.importMap.size(); i++) {
559 for (size_t j = 0; j < comp_count; j++) {
560 ioss_data[block.importMap[i] * comp_count + j] = imports[i * comp_count + j];
561 }
562 }
563 }
564 }
565
566 template <typename T, typename U>
568 T *file_data, U *ioss_data, const std::vector<BlockDecompositionData> &blocks,
569 const std::vector<int64_t> &blockSubsetIndex, const std::vector<size_t> &fileOffset,
570 const std::vector<int> &blockComponentCount) const
571 {
572 size_t export_size = 0;
573 size_t import_size = 0;
574
575 for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) {
576 int64_t blk_seq = blockSubsetIndex[bsi];
577 const Ioss::BlockDecompositionData &blk = blocks[blk_seq];
578
579 size_t comp_count = blockComponentCount[bsi];
580 export_size += blk.exportMap.size() * comp_count;
581 import_size += blk.importMap.size() * comp_count;
582 }
583
584 std::vector<U> exports;
585 exports.reserve(export_size);
586
588 int nProc = util_.parallel_size();
589
590 for (int proc = 0; proc < nProc; proc++) {
591 for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) {
592 int64_t blk_seq = blockSubsetIndex[bsi];
593 const Ioss::BlockDecompositionData &blk = blocks[blk_seq];
594 size_t comp_count = blockComponentCount[bsi];
595 size_t fileDataOffset = fileOffset[bsi];
596
597 for (int n = 0; n < blk.exportCount[proc]; n++) {
598 int exportIndex = blk.exportIndex[proc] + n;
599 int i = blk.exportMap[exportIndex];
600
601 for (size_t j = 0; j < comp_count; j++) {
602 size_t fileIndex = fileDataOffset + i * comp_count + j;
603 exports.push_back(file_data[fileIndex]);
604 }
605 }
606 }
607 }
608
609 std::vector<int64_t> export_count(nProc, 0);
610 std::vector<int64_t> export_disp(nProc, 0);
611 std::vector<int64_t> import_count(nProc, 0);
612 std::vector<int64_t> import_disp(nProc, 0);
613
614 for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) {
615 int64_t blk_seq = blockSubsetIndex[bsi];
616 const Ioss::BlockDecompositionData &blk = blocks[blk_seq];
617 size_t comp_count = blockComponentCount[bsi];
618
619 int proc = 0;
620 for (int i : blk.exportCount) {
621 export_count[proc++] += comp_count * i;
622 }
623
624 proc = 0;
625 for (int i : blk.importCount) {
626 import_count[proc++] += comp_count * i;
627 }
628 }
629
630 std::copy(export_count.begin(), export_count.end(), export_disp.begin());
631 std::copy(import_count.begin(), import_count.end(), import_disp.begin());
632
633 Ioss::Utils::generate_index(export_disp);
634 Ioss::Utils::generate_index(import_disp);
635
636 std::vector<U> imports(import_size);
637 Ioss::MY_Alltoallv(exports, export_count, export_disp, imports, import_count, import_disp,
638 m_comm);
639 show_progress("\tCommunication 1 finished");
640
641 Ioss::ElementBlockBatchOffset batchOffset(blocks);
642 std::vector<size_t> iossOffset =
643 batchOffset.get_ioss_offset(blockSubsetIndex, blockComponentCount);
644 std::vector<size_t> importOffset =
645 batchOffset.get_import_offset(blockSubsetIndex, blockComponentCount);
646
647 // Map local and imported data to ioss_data.
648 for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) {
649 int64_t blk_seq = blockSubsetIndex[bsi];
650 const Ioss::BlockDecompositionData &block = blocks[blk_seq];
651 size_t comp_count = blockComponentCount[bsi];
652
653 for (size_t i = 0; i < block.localMap.size(); i++) {
654 for (size_t j = 0; j < comp_count; j++) {
655 size_t fileIndex = fileOffset[bsi] + block.localMap[i] * comp_count + j;
656 size_t iossIndex = iossOffset[bsi] + (i + block.localIossOffset) * comp_count + j;
657 ioss_data[iossIndex] = file_data[fileIndex];
658 }
659 }
660
661 for (size_t i = 0; i < block.importMap.size(); i++) {
662 for (size_t j = 0; j < comp_count; j++) {
663 size_t importIndex = importOffset[bsi] + i * comp_count + j;
664
665 size_t dataOffset = iossOffset[bsi];
666 size_t iossIndex = dataOffset + block.importMap[i] * comp_count + j;
667
668 ioss_data[iossIndex] = imports[importIndex];
669 }
670 }
671 }
672
673 return iossOffset;
674 }
675
676 template <typename T, typename U>
678 T *file_data, U *ioss_data, const std::vector<BlockDecompositionData> &blocks,
679 const std::vector<int64_t> &blockSubsetIndex, const std::vector<size_t> &fileOffset,
680 const std::vector<int> &blockComponentCount) const
681 {
682 show_progress(__func__);
683 if (m_method == "LINEAR") {
684 // For "LINEAR" decomposition method, the `file_data` is the
685 // same as `ioss_data` Transfer all local data from file_data
686 // to ioss_data...
687 auto size = fileOffset[blockSubsetIndex.size()];
688 std::copy(file_data, file_data + size, ioss_data);
689
690 Ioss::ElementBlockBatchOffset batchOffset(blocks);
691 return batchOffset.get_ioss_offset(blockSubsetIndex, blockComponentCount);
692 ;
693 }
694
695 auto retval = do_communicate_entity_data(file_data, ioss_data, blocks, blockSubsetIndex,
696 fileOffset, blockComponentCount);
697
698 return retval;
699 }
700
701 template <typename T>
702 void communicate_node_data(T *file_data, T *ioss_data, size_t comp_count) const
703 {
704 show_progress(__func__);
705 // Transfer the file-decomposition based data in 'file_data' to
706 // the ioss-decomposition based data in 'ioss_data'
707 std::vector<T> export_data(exportNodeMap.size() * comp_count);
708 std::vector<T> import_data(importNodeMap.size() * comp_count);
709
710 if (comp_count == 1) {
711 for (size_t i = 0; i < exportNodeMap.size(); i++) {
712 size_t index = exportNodeMap[i] - m_nodeOffset;
713 assert(index < m_nodeCount);
714 export_data[i] = file_data[index];
715 }
716
717 // Transfer all local data from file_data to ioss_data...
718 for (size_t i = 0; i < localNodeMap.size(); i++) {
719 size_t index = localNodeMap[i] - m_nodeOffset;
720 assert(index < m_nodeCount);
721 ioss_data[m_importPreLocalNodeIndex + i] = file_data[index];
722 }
723
724 // Get my imported data and send my exported data...
725 Ioss::MY_Alltoallv(export_data, exportNodeCount, exportNodeIndex, import_data,
727 show_progress("\tCommunication 1a finished");
728
729 // Copy the imported data into ioss_data...
730 for (size_t i = 0; i < importNodeMap.size(); i++) {
731 size_t index = importNodeMap[i];
732 assert(index < ioss_node_count());
733 ioss_data[index] = import_data[i];
734 }
735 }
736 else { // Comp_count > 1
737 for (size_t i = 0; i < exportNodeMap.size(); i++) {
738 size_t index = exportNodeMap[i] - m_nodeOffset;
739 assert(index < m_nodeCount);
740 for (size_t j = 0; j < comp_count; j++) {
741 export_data[comp_count * i + j] = file_data[comp_count * index + j];
742 }
743 }
744
745 // Transfer all local data from file_data to ioss_data...
746 for (size_t i = 0; i < localNodeMap.size(); i++) {
747 size_t index = localNodeMap[i] - m_nodeOffset;
748 assert(index < m_nodeCount);
749 for (size_t j = 0; j < comp_count; j++) {
750 ioss_data[comp_count * (m_importPreLocalNodeIndex + i) + j] =
751 file_data[comp_count * index + j];
752 }
753 }
754
755 std::vector<INT> export_count(exportNodeCount.begin(), exportNodeCount.end());
756 std::vector<INT> export_disp(exportNodeIndex.begin(), exportNodeIndex.end());
757 std::vector<INT> import_count(importNodeCount.begin(), importNodeCount.end());
758 std::vector<INT> import_disp(importNodeIndex.begin(), importNodeIndex.end());
759
760 for (int i = 0; i < m_processorCount; i++) {
761 export_count[i] *= comp_count;
762 export_disp[i] *= comp_count;
763 import_count[i] *= comp_count;
764 import_disp[i] *= comp_count;
765 }
766
767 // Get my imported data and send my exported data...
768 Ioss::MY_Alltoallv(export_data, export_count, export_disp, import_data, import_count,
769 import_disp, m_comm);
770 show_progress("\tCommunication 1b finished");
771
772 // Copy the imported data into ioss_data...
773 for (size_t i = 0; i < importNodeMap.size(); i++) {
774 size_t index = importNodeMap[i];
775 assert(index < ioss_node_count());
776 for (size_t j = 0; j < comp_count; j++) {
777 ioss_data[comp_count * index + j] = import_data[comp_count * i + j];
778 }
779 }
780 }
781 }
782
787 std::string m_method{};
788 std::string m_decompExtra{};
789
790 // Values for the file decomposition
794 size_t m_elementCount{0};
797
799 size_t m_nodeCount{0};
800 size_t m_nodeOffset{0};
802
804 bool m_showProgress{false};
805 bool m_showHWM{false};
806
807 std::vector<INT> m_elementToProc; // Used by "MAP" scheme...
808 std::vector<double> m_centroids;
809 std::vector<INT> m_pointer; // Index into adjacency, processor list for each element...
810 std::vector<INT> m_adjacency; // Size is sum of element connectivity sizes
811
812 std::vector<INT> m_nodeCommMap; // node/processor pair of the
813 // nodes I communicate with. Stored node#,proc,node#,proc, ...
814
815 // The global element at index 'I' (0-based) is on block B in the
816 // file decomposition.
817 // if m_fileBlockIndex[B] <= I && m_fileBlockIndex[B+1] < I
818 std::vector<size_t> m_fileBlockIndex;
819
820 private:
821 // This processor "manages" the elements on the exodus mesh file from
822 // m_elementOffset to m_elementOffset+m_elementCount (0-based). This is
823 // 'file' data
824 //
825 // This processor also appears to the Ioss clients to own other
826 // element and node data based on the decomposition. This is the
827 // 'ioss' data.
828 //
829 // The indices in `localElementMap` are the elements that are
830 // common to both the 'file' data and the 'ioss' data.
831 // `localElementMap[i]` contains the location in 'file' data for
832 // the 'ioss' data at location `i+m_importPreLocalElemIndex`
833 //
834 // local_element_map[i]+m_elementOffset is the 0-based global index
835 //
836 // The indices in 'import_element_map' map the data received via
837 // mpi communication from other processors into 'ioss' data.
838 // if 'ind=import_element_map[i]', then ioss[ind] = comm_recv[i]
839 // Note that this is the reverse direction of the
840 // local_element_map mapping.
841 //
842 // The indices in 'export_element_map' are used to pull from
843 // 'file' data into the comm_send vector. if 'ind =
844 // export_element_map[i]', then 'comm_send[i] = file[ind]' for i =
845 // 0..#exported_elements
846 //
847 // local_element_map.size() + import_element_map.size() ==
848 // #ioss elements on this processor.
849 //
850 // local_element_map.size() + export_element_map.size() ==
851 // #file elements on this processor.
852 //
853 // export_element_map and import_element_map are sorted.
854 // The primary key is processor order followed by global id.
855 // The processor association is via 'export_proc_disp' and
856 // 'import_proc_disp' Both are of size '#processors+1' and
857 // the elements for processor p range from [X_proc_disp[p] to
858 // X_proc_disp[p+1])
859
860 std::vector<INT> localElementMap;
861
862 std::vector<INT> importElementMap;
863 std::vector<INT> importElementCount;
864 std::vector<INT> importElementIndex;
865
866 // The list of my `file decomp` elements that will be exported to some other rank.
867 std::vector<INT> exportElementMap;
868 // The number of elements that I will export to each other rank.
869 std::vector<INT> exportElementCount;
870 // The index into `exportElementMap` for the elements that will be exported to each rank.
871 std::vector<INT> exportElementIndex;
872
873 std::vector<INT> nodeIndex;
874
875 std::vector<INT> exportNodeMap;
876 std::vector<INT> exportNodeCount;
877 std::vector<INT> exportNodeIndex;
878
879 // Where to put each imported nodes data in the list of all data...
880 std::vector<INT> importNodeMap;
881 std::vector<INT> importNodeCount;
882 std::vector<INT> importNodeIndex;
883
884 std::vector<INT> localNodeMap;
885
886 std::vector<INT> m_elementDist;
887 std::vector<INT> m_nodeDist;
888
889 // Note that nodeGTL is a sorted vector.
890 std::vector<INT> nodeGTL; // Convert from global index to local index (1-based)
891
892#if defined DC_USE_HOPSCOTCH
893 tsl::hopscotch_pg_map<INT, INT> elemGTL; // Convert from global index to local index (1-based)
894#elif defined DC_USE_ROBIN
895 tsl::robin_pg_map<INT, INT> elemGTL; // Convert from global index to local index (1-based)
896#elif defined DC_USE_VECTOR
897 std::vector<std::pair<INT, INT>> elemGTL; // Convert from global index to local index (1-based)
898#else
899 // This is the original method that was used in IOSS prior to using hopscotch or robin map.
900 std::map<INT, INT> elemGTL; // Convert from global index to local index (1-based)
901#endif
902 };
903} // namespace Ioss
#define IOSS_NODISCARD
Definition Ioss_CodeTypes.h:54
int Ioss_MPI_Comm
Definition Ioss_CodeTypes.h:63
Definition Ioss_Decomposition.h:45
IOSS_NODISCARD size_t file_count() const
Definition Ioss_Decomposition.h:53
IOSS_NODISCARD int64_t id() const
Definition Ioss_Decomposition.h:52
IOSS_NODISCARD int zone() const
Definition Ioss_Decomposition.h:50
IOSS_NODISCARD const std::string & name() const
Definition Ioss_Decomposition.h:49
std::vector< int > localMap
Definition Ioss_Decomposition.h:76
IOSS_NODISCARD size_t global_count() const
Definition Ioss_Decomposition.h:55
std::vector< int > exportCount
Definition Ioss_Decomposition.h:81
IOSS_NODISCARD size_t ioss_count() const
Definition Ioss_Decomposition.h:54
IOSS_NODISCARD int section() const
Definition Ioss_Decomposition.h:51
size_t localIossOffset
Definition Ioss_Decomposition.h:75
std::vector< int > importIndex
Definition Ioss_Decomposition.h:88
std::vector< int > importMap
Definition Ioss_Decomposition.h:86
std::vector< int > exportIndex
Definition Ioss_Decomposition.h:82
std::vector< int > importCount
Definition Ioss_Decomposition.h:87
std::vector< int > exportMap
Definition Ioss_Decomposition.h:80
Definition Ioss_Decomposition.h:180
IOSS_NODISCARD size_t global_elem_count() const
Definition Ioss_Decomposition.h:189
void metis_decompose(idx_t *pointer, idx_t *adjacency, std::vector< BlockDecompositionData > &el_blocks)
Definition Ioss_Decomposition.C:867
std::vector< INT > localElementMap
Definition Ioss_Decomposition.h:860
std::vector< INT > importNodeCount
Definition Ioss_Decomposition.h:881
std::vector< INT > exportElementMap
Definition Ioss_Decomposition.h:867
IOSS_NODISCARD size_t elem_global_to_local(size_t global_index) const
Definition Ioss_Decomposition.h:243
std::string m_method
Definition Ioss_Decomposition.h:787
void build_global_to_local_elem_map()
Definition Ioss_Decomposition.C:1258
IOSS_NODISCARD std::vector< size_t > communicate_entity_data(T *file_data, U *ioss_data, const std::vector< BlockDecompositionData > &blocks, const std::vector< int64_t > &blockSubsetIndex, const std::vector< size_t > &fileOffset, const std::vector< int > &blockComponentCount) const
Definition Ioss_Decomposition.h:677
std::vector< INT > exportNodeMap
Definition Ioss_Decomposition.h:875
std::vector< double > m_centroids
Definition Ioss_Decomposition.h:808
void communicate_element_data(T *file_data, T *ioss_data, size_t comp_count) const
Definition Ioss_Decomposition.h:327
bool m_retainFreeNodes
Definition Ioss_Decomposition.h:803
void guided_decompose()
Definition Ioss_Decomposition.C:666
std::vector< INT > importNodeIndex
Definition Ioss_Decomposition.h:882
std::vector< INT > m_elementDist
Definition Ioss_Decomposition.h:886
std::vector< INT > exportNodeCount
Definition Ioss_Decomposition.h:876
IOSS_NODISCARD std::vector< size_t > do_communicate_entity_data(T *file_data, U *ioss_data, const std::vector< BlockDecompositionData > &blocks, const std::vector< int64_t > &blockSubsetIndex, const std::vector< size_t > &fileOffset, const std::vector< int > &blockComponentCount) const
Definition Ioss_Decomposition.h:567
std::vector< INT > nodeGTL
Definition Ioss_Decomposition.h:890
Ioss_MPI_Comm m_comm
Definition Ioss_Decomposition.h:783
bool m_showHWM
Definition Ioss_Decomposition.h:805
IOSS_NODISCARD size_t ioss_elem_count() const
Definition Ioss_Decomposition.h:191
void internal_metis_decompose(std::vector< BlockDecompositionData > &el_blocks, idx_t *element_dist, idx_t *pointer, idx_t *adjacency, idx_t *elem_partition)
Definition Ioss_Decomposition.C:981
std::vector< INT > m_nodeCommMap
Definition Ioss_Decomposition.h:812
std::vector< size_t > m_fileBlockIndex
Definition Ioss_Decomposition.h:818
size_t m_elementOffset
Definition Ioss_Decomposition.h:795
std::vector< INT > exportNodeIndex
Definition Ioss_Decomposition.h:877
void simple_node_decompose()
Definition Ioss_Decomposition.C:832
void get_element_block_communication(std::vector< BlockDecompositionData > &el_blocks)
Definition Ioss_Decomposition.C:328
void show_progress(const std::string &message) const
Definition Ioss_Decomposition.h:261
void get_node_entity_proc_data(INT *entity_proc, const Ioss::MapContainer &node_map, bool do_map) const
Definition Ioss_Decomposition.h:299
IOSS_NODISCARD size_t ioss_node_count() const
Definition Ioss_Decomposition.h:190
int m_processor
Definition Ioss_Decomposition.h:785
void get_local_element_list(const ZOLTAN_ID_PTR &export_global_ids, size_t export_count)
Definition Ioss_Decomposition.C:1220
std::vector< INT > m_elementToProc
Definition Ioss_Decomposition.h:807
int m_commonNodeCount
Definition Ioss_Decomposition.h:792
IOSS_NODISCARD bool i_own_elem(size_t global_index) const
Definition Ioss_Decomposition.h:216
size_t m_nodeOffset
Definition Ioss_Decomposition.h:800
void communicate_node_data(T *file_data, T *ioss_data, size_t comp_count) const
Definition Ioss_Decomposition.h:702
Decomposition(const Ioss::PropertyManager &props, Ioss_MPI_Comm comm)
Definition Ioss_Decomposition.C:284
size_t m_globalElementCount
Definition Ioss_Decomposition.h:793
void simple_decompose()
Definition Ioss_Decomposition.C:812
void decompose_model(Zoltan &zz, std::vector< BlockDecompositionData > &element_blocks)
Definition Ioss_Decomposition.C:410
std::vector< INT > m_nodeDist
Definition Ioss_Decomposition.h:887
size_t m_importPreLocalElemIndex
Definition Ioss_Decomposition.h:796
std::vector< INT > importElementMap
Definition Ioss_Decomposition.h:862
IOSS_NODISCARD size_t node_global_to_local(size_t global_index) const
Definition Ioss_Decomposition.h:230
IOSS_NODISCARD size_t file_elem_offset() const
Definition Ioss_Decomposition.h:198
Decomposition & operator=(Decomposition const &)=default
void generate_entity_distributions(size_t global_node_count, size_t global_element_count)
Definition Ioss_Decomposition.C:314
void communicate_block_data(T *file_data, U *ioss_data, const BlockDecompositionData &block, size_t comp_count) const
Definition Ioss_Decomposition.h:488
Decomposition(Decomposition const &)=default
IOSS_NODISCARD size_t file_node_count() const
Definition Ioss_Decomposition.h:195
std::vector< INT > m_adjacency
Definition Ioss_Decomposition.h:810
IOSS_NODISCARD bool needs_centroids() const
Definition Ioss_Decomposition.h:200
bool m_showProgress
Definition Ioss_Decomposition.h:804
void communicate_set_data(T *file_data, T *ioss_data, const SetDecompositionData &set, size_t comp_count) const
Definition Ioss_Decomposition.h:430
std::vector< INT > importElementCount
Definition Ioss_Decomposition.h:863
IOSS_NODISCARD size_t file_elem_count() const
Definition Ioss_Decomposition.h:196
Ioss::ParallelUtils m_pu
Definition Ioss_Decomposition.h:784
size_t m_importPreLocalNodeIndex
Definition Ioss_Decomposition.h:801
std::vector< INT > exportElementIndex
Definition Ioss_Decomposition.h:871
std::string m_decompExtra
Definition Ioss_Decomposition.h:788
Decomposition(Decomposition &&)=default
std::vector< INT > nodeIndex
Definition Ioss_Decomposition.h:873
size_t m_nodeCount
Definition Ioss_Decomposition.h:799
std::vector< INT > m_pointer
Definition Ioss_Decomposition.h:809
std::vector< INT > localNodeMap
Definition Ioss_Decomposition.h:884
IOSS_NODISCARD bool i_own_node(size_t global_index) const
Definition Ioss_Decomposition.h:209
std::vector< std::pair< INT, INT > > elemGTL
Definition Ioss_Decomposition.h:897
std::vector< INT > exportElementCount
Definition Ioss_Decomposition.h:869
void zoltan_decompose(Zoltan &zz)
Definition Ioss_Decomposition.C:1083
IOSS_NODISCARD size_t file_node_offset() const
Definition Ioss_Decomposition.h:197
void calculate_element_centroids(const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &z)
Definition Ioss_Decomposition.C:499
Decomposition & operator=(Decomposition &&)=default
int m_processorCount
Definition Ioss_Decomposition.h:786
void get_local_node_list()
Definition Ioss_Decomposition.C:1301
size_t m_globalNodeCount
Definition Ioss_Decomposition.h:798
std::vector< INT > importElementIndex
Definition Ioss_Decomposition.h:864
int m_spatialDimension
Definition Ioss_Decomposition.h:791
IOSS_NODISCARD size_t global_node_count() const
Definition Ioss_Decomposition.h:188
std::vector< INT > importNodeMap
Definition Ioss_Decomposition.h:880
void get_shared_node_list()
Definition Ioss_Decomposition.C:1509
size_t m_elementCount
Definition Ioss_Decomposition.h:794
Definition Ioss_Decomposition.h:140
IOSS_NODISCARD std::vector< size_t > get_import_offset(const std::vector< int64_t > &blockSubsetIndex, const std::vector< int > &blockComponentCount) const
Definition Ioss_Decomposition.C:222
IOSS_NODISCARD std::vector< size_t > get_ioss_offset(const std::vector< int64_t > &blockSubsetIndex, const std::vector< int > &blockComponentCount) const
Definition Ioss_Decomposition.C:200
const std::vector< BlockDecompositionData > & m_data
Definition Ioss_Decomposition.h:167
ElementBlockBatchOffset(const ElementBlockBatchOffset &)=delete
ElementBlockBatchOffset(ElementBlockBatchOffset &&)=delete
ElementBlockBatchOffset(const std::vector< BlockDecompositionData > &data)
Definition Ioss_Decomposition.h:142
Definition Ioss_ParallelUtils.h:31
IOSS_NODISCARD int parallel_size() const
Definition Ioss_ParallelUtils.C:206
static IOSS_NODISCARD constexpr Ioss_MPI_Comm comm_null()
Definition Ioss_ParallelUtils.h:49
void broadcast(T &my_value, int root=0) const
void progress(const std::string &output) const
Definition Ioss_ParallelUtils.C:601
A collection of Ioss::Property objects.
Definition Ioss_PropertyManager.h:36
Definition Ioss_Decomposition.h:92
IOSS_NODISCARD size_t ioss_count() const
Definition Ioss_Decomposition.h:114
IOSS_NODISCARD const std::string & ss_name() const
Definition Ioss_Decomposition.h:106
IOSS_NODISCARD size_t df_count() const
Definition Ioss_Decomposition.h:115
int root_
Definition Ioss_Decomposition.h:127
IOSS_NODISCARD int section() const
Definition Ioss_Decomposition.h:112
IOSS_NODISCARD int zone() const
Definition Ioss_Decomposition.h:111
IOSS_NODISCARD const std::string & name() const
Definition Ioss_Decomposition.h:105
std::vector< size_t > entitylist_map
Definition Ioss_Decomposition.h:118
IOSS_NODISCARD int64_t id() const
Definition Ioss_Decomposition.h:110
~SetDecompositionData()
Definition Ioss_Decomposition.h:98
IOSS_NODISCARD size_t file_count() const
Definition Ioss_Decomposition.h:113
std::vector< bool > hasEntities
Definition Ioss_Decomposition.h:119
SetDecompositionData(SetDecompositionData &&)=default
SetDecompositionData(const SetDecompositionData &)=delete
Ioss_MPI_Comm setComm_
Definition Ioss_Decomposition.h:135
static void generate_index(std::vector< T > &index)
Definition Ioss_Utils.h:180
Definition hopscotch_map.h:82
Definition robin_map.h:90
The main namespace for the Ioss library.
Definition Ioad_DatabaseIO.C:40
std::vector< int64_t > MapContainer
Definition Ioss_Map.h:29
IOSS_EXPORT const std::vector< std::string > & valid_decomp_methods()
Definition Ioss_Decomposition.C:141