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 Ioss::NameList &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();
281
282 void calculate_element_centroids(const std::vector<double> &x, const std::vector<double> &y,
283 const std::vector<double> &z);
284
285#if !defined(NO_ZOLTAN_SUPPORT)
286 void zoltan_decompose(Zoltan &zz);
287
288 void get_local_element_list(const ZOLTAN_ID_PTR &export_global_ids, size_t export_count);
289#endif
290
291#if !defined(NO_PARMETIS_SUPPORT)
292 void metis_decompose(idx_t *pointer, idx_t *adjacency,
293 std::vector<BlockDecompositionData> &el_blocks);
294
295 void internal_metis_decompose(std::vector<BlockDecompositionData> &el_blocks,
296 idx_t *element_dist, idx_t *pointer, idx_t *adjacency,
297 idx_t *elem_partition);
298#endif
299
300 void get_node_entity_proc_data(INT *entity_proc, const Ioss::MapContainer &node_map,
301 bool do_map) const
302 {
303 show_progress(__func__);
304 size_t j = 0;
305 if (do_map) {
306 for (size_t i = 0; i < m_nodeCommMap.size(); i += 2) {
307 INT local_id = m_nodeCommMap[i];
308 entity_proc[j++] = node_map[local_id];
309 entity_proc[j++] = m_nodeCommMap[i + 1];
310 }
311 }
312 else {
313 for (size_t i = 0; i < m_nodeCommMap.size(); i += 2) {
314 entity_proc[j++] = m_nodeCommMap[i + 0];
315 entity_proc[j++] = m_nodeCommMap[i + 1];
316 }
317 }
318 }
319
320 void get_element_block_communication(std::vector<BlockDecompositionData> &el_blocks);
322 void get_local_node_list();
324
325 // The following function is used if reading all element data on a
326 // processor instead of just an element blocks worth...
327 template <typename T>
328 void communicate_element_data(T *file_data, T *ioss_data, size_t comp_count) const
329 {
330 show_progress(__func__);
331 if (m_method == "LINEAR") {
332 assert(m_importPreLocalElemIndex == 0);
333 assert(exportElementMap.size() == 0);
334 assert(importElementMap.size() == 0);
335 // For "LINEAR" decomposition method, the `file_data` is the
336 // same as `ioss_data` Transfer all local data from file_data
337 // to ioss_data...
338 auto size = localElementMap.size() * comp_count;
339 std::copy(file_data, file_data + size, ioss_data);
340 return;
341 }
342
343 // Transfer the file-decomposition based data in 'file_data' to
344 // the ioss-decomposition based data in 'ioss_data'
345 std::vector<T> export_data(exportElementMap.size() * comp_count);
346 std::vector<T> import_data(importElementMap.size() * comp_count);
347
348 if (comp_count == 1) {
349 for (size_t i = 0; i < exportElementMap.size(); i++) {
350 size_t index = exportElementMap[i] - m_elementOffset;
351 export_data[i] = file_data[index];
352 }
353
354 // Transfer all local data from file_data to ioss_data...
355 for (size_t i = 0; i < localElementMap.size(); i++) {
356 size_t index = localElementMap[i];
357 ioss_data[m_importPreLocalElemIndex + i] = file_data[index];
358 }
359
360 // Get my imported data and send my exported data...
361 Ioss::MY_Alltoallv(export_data, exportElementCount, exportElementIndex, import_data,
363 show_progress("\tCommunication 1a finished");
364
365 // Copy the imported data into ioss_data...
366 // Some comes before the local data...
367 for (size_t i = 0; i < m_importPreLocalElemIndex; i++) {
368 ioss_data[i] = import_data[i];
369 }
370
371 // Some comes after the local data...
372 size_t offset = m_importPreLocalElemIndex + localElementMap.size();
373 for (size_t i = 0; i < importElementMap.size() - m_importPreLocalElemIndex; i++) {
374 ioss_data[offset + i] = import_data[m_importPreLocalElemIndex + i];
375 }
376 }
377 else {
378 for (size_t i = 0; i < exportElementMap.size(); i++) {
379 size_t index = exportElementMap[i] - m_elementOffset;
380 for (size_t j = 0; j < comp_count; j++) {
381 export_data[comp_count * i + j] = file_data[comp_count * index + j];
382 }
383 }
384
385 // Transfer all local data from file_data to ioss_data...
386 for (size_t i = 0; i < localElementMap.size(); i++) {
387 size_t index = localElementMap[i];
388 for (size_t j = 0; j < comp_count; j++) {
389 ioss_data[comp_count * (m_importPreLocalElemIndex + i) + j] =
390 file_data[comp_count * index + j];
391 }
392 }
393
394 std::vector<INT> export_count(exportElementCount.begin(), exportElementCount.end());
395 std::vector<INT> export_disp(exportElementIndex.begin(), exportElementIndex.end());
396 std::vector<INT> import_count(importElementCount.begin(), importElementCount.end());
397 std::vector<INT> import_disp(importElementIndex.begin(), importElementIndex.end());
398
399 for (int i = 0; i < m_processorCount; i++) {
400 export_count[i] *= comp_count;
401 export_disp[i] *= comp_count;
402 import_count[i] *= comp_count;
403 import_disp[i] *= comp_count;
404 }
405
406 // Get my imported data and send my exported data...
407 Ioss::MY_Alltoallv(export_data, export_count, export_disp, import_data, import_count,
408 import_disp, m_comm);
409 show_progress("\tCommunication 1b finished");
410
411 // Copy the imported data into ioss_data...
412 // Some comes before the local data...
413 for (size_t i = 0; i < m_importPreLocalElemIndex; i++) {
414 for (size_t j = 0; j < comp_count; j++) {
415 ioss_data[comp_count * i + j] = import_data[comp_count * i + j];
416 }
417 }
418
419 // Some comes after the local data...
420 size_t offset = m_importPreLocalElemIndex + localElementMap.size();
421 for (size_t i = 0; i < importElementMap.size() - m_importPreLocalElemIndex; i++) {
422 for (size_t j = 0; j < comp_count; j++) {
423 ioss_data[comp_count * (offset + i) + j] =
424 import_data[comp_count * (m_importPreLocalElemIndex + i) + j];
425 }
426 }
427 }
428 }
429
430 template <typename T>
431 void communicate_set_data(T *file_data, T *ioss_data, const SetDecompositionData &set,
432 size_t comp_count) const
433 {
434 show_progress(__func__);
435 std::vector<T> recv_data;
436
437 size_t size = set.file_count() * comp_count;
438 if (size == 0) {
439 return;
440 }
441
443 recv_data.resize(size);
444 if (m_processor == set.root_) {
445 std::copy(file_data, file_data + size, recv_data.begin());
446 }
447 // NOTE: This broadcast uses a split communicator, so possibly
448 // not all processors participating.
450 pu.broadcast(recv_data);
451 }
452 if (comp_count == 1) {
453 if (set.root_ == m_processor) {
454 for (size_t i = 0; i < set.ioss_count(); i++) {
455 size_t index = set.entitylist_map[i];
456 ioss_data[i] = file_data[index];
457 }
458 }
459 else {
460 // Receiving data from root...
461 for (size_t i = 0; i < set.ioss_count(); i++) {
462 size_t index = set.entitylist_map[i];
463 ioss_data[i] = recv_data[index];
464 }
465 }
466 }
467 else {
468 if (set.root_ == m_processor) {
469 for (size_t i = 0; i < set.ioss_count(); i++) {
470 size_t index = set.entitylist_map[i];
471 for (size_t j = 0; j < comp_count; j++) {
472 ioss_data[comp_count * i + j] = file_data[comp_count * index + j];
473 }
474 }
475 }
476 else {
477 // Receiving data from root...
478 for (size_t i = 0; i < set.ioss_count(); i++) {
479 size_t index = set.entitylist_map[i];
480 for (size_t j = 0; j < comp_count; j++) {
481 ioss_data[comp_count * i + j] = recv_data[comp_count * index + j];
482 }
483 }
484 }
485 }
486 }
487
488 template <typename T, typename U>
489 void communicate_block_data(T *file_data, U *ioss_data, const BlockDecompositionData &block,
490 size_t comp_count) const
491 {
492 show_progress(__func__);
493 if (m_method == "LINEAR") {
494 assert(block.localIossOffset == 0);
495 assert(block.exportMap.empty());
496 assert(block.importMap.empty());
497 // For "LINEAR" decomposition method, the `file_data` is the
498 // same as `ioss_data` Transfer all local data from file_data
499 // to ioss_data...
500 auto size = block.localMap.size() * comp_count;
501 std::copy(file_data, file_data + size, ioss_data);
502 return;
503 }
504
505 std::vector<U> exports;
506 exports.reserve(comp_count * block.exportMap.size());
507 std::vector<U> imports(comp_count * block.importMap.size());
508
509 if (comp_count == 1) {
510 for (int i : block.exportMap) {
511 exports.push_back(file_data[i]);
512 }
513
514 // Get my imported data and send my exported data...
515 Ioss::MY_Alltoallv(exports, block.exportCount, block.exportIndex, imports,
516 block.importCount, block.importIndex, m_comm);
517
518 // Map local and imported data to ioss_data.
519 for (size_t i = 0; i < block.localMap.size(); i++) {
520 ioss_data[i + block.localIossOffset] = file_data[block.localMap[i]];
521 }
522
523 for (size_t i = 0; i < block.importMap.size(); i++) {
524 ioss_data[block.importMap[i]] = imports[i];
525 }
526 }
527 else {
528 for (int i : block.exportMap) {
529 for (size_t j = 0; j < comp_count; j++) {
530 exports.push_back(file_data[i * comp_count + j]);
531 }
532 }
533
534 std::vector<int> export_count(block.exportCount.begin(), block.exportCount.end());
535 std::vector<int> export_disp(block.exportIndex.begin(), block.exportIndex.end());
536 std::vector<int> import_count(block.importCount.begin(), block.importCount.end());
537 std::vector<int> import_disp(block.importIndex.begin(), block.importIndex.end());
538
539 for (int i = 0; i < m_processorCount; i++) {
540 export_count[i] *= comp_count;
541 export_disp[i] *= comp_count;
542 import_count[i] *= comp_count;
543 import_disp[i] *= comp_count;
544 }
545
546 // Get my imported data and send my exported data...
547 Ioss::MY_Alltoallv(exports, export_count, export_disp, imports, import_count, import_disp,
548 m_comm);
549 show_progress("\tCommunication 1 finished");
550
551 // Map local and imported data to ioss_data.
552 for (size_t i = 0; i < block.localMap.size(); i++) {
553 for (size_t j = 0; j < comp_count; j++) {
554 ioss_data[(i + block.localIossOffset) * comp_count + j] =
555 file_data[block.localMap[i] * comp_count + j];
556 }
557 }
558
559 for (size_t i = 0; i < block.importMap.size(); i++) {
560 for (size_t j = 0; j < comp_count; j++) {
561 ioss_data[block.importMap[i] * comp_count + j] = imports[i * comp_count + j];
562 }
563 }
564 }
565 }
566
567 template <typename T, typename U>
569 T *file_data, U *ioss_data, const std::vector<BlockDecompositionData> &blocks,
570 const std::vector<int64_t> &blockSubsetIndex, const std::vector<size_t> &fileOffset,
571 const std::vector<int> &blockComponentCount) const
572 {
573 size_t export_size = 0;
574 size_t import_size = 0;
575
576 for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) {
577 int64_t blk_seq = blockSubsetIndex[bsi];
578 const Ioss::BlockDecompositionData &blk = blocks[blk_seq];
579
580 size_t comp_count = blockComponentCount[bsi];
581 export_size += blk.exportMap.size() * comp_count;
582 import_size += blk.importMap.size() * comp_count;
583 }
584
585 std::vector<U> exports;
586 exports.reserve(export_size);
587
589 int nProc = util_.parallel_size();
590
591 for (int proc = 0; proc < nProc; proc++) {
592 for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) {
593 int64_t blk_seq = blockSubsetIndex[bsi];
594 const Ioss::BlockDecompositionData &blk = blocks[blk_seq];
595 size_t comp_count = blockComponentCount[bsi];
596 size_t fileDataOffset = fileOffset[bsi];
597
598 for (int n = 0; n < blk.exportCount[proc]; n++) {
599 int exportIndex = blk.exportIndex[proc] + n;
600 int i = blk.exportMap[exportIndex];
601
602 for (size_t j = 0; j < comp_count; j++) {
603 size_t fileIndex = fileDataOffset + i * comp_count + j;
604 exports.push_back(file_data[fileIndex]);
605 }
606 }
607 }
608 }
609
610 std::vector<int64_t> export_count(nProc, 0);
611 std::vector<int64_t> export_disp(nProc, 0);
612 std::vector<int64_t> import_count(nProc, 0);
613 std::vector<int64_t> import_disp(nProc, 0);
614
615 for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) {
616 int64_t blk_seq = blockSubsetIndex[bsi];
617 const Ioss::BlockDecompositionData &blk = blocks[blk_seq];
618 size_t comp_count = blockComponentCount[bsi];
619
620 int proc = 0;
621 for (int i : blk.exportCount) {
622 export_count[proc++] += comp_count * i;
623 }
624
625 proc = 0;
626 for (int i : blk.importCount) {
627 import_count[proc++] += comp_count * i;
628 }
629 }
630
631 std::copy(export_count.begin(), export_count.end(), export_disp.begin());
632 std::copy(import_count.begin(), import_count.end(), import_disp.begin());
633
634 Ioss::Utils::generate_index(export_disp);
635 Ioss::Utils::generate_index(import_disp);
636
637 std::vector<U> imports(import_size);
638 Ioss::MY_Alltoallv(exports, export_count, export_disp, imports, import_count, import_disp,
639 m_comm);
640 show_progress("\tCommunication 1 finished");
641
642 Ioss::ElementBlockBatchOffset batchOffset(blocks);
643 std::vector<size_t> iossOffset =
644 batchOffset.get_ioss_offset(blockSubsetIndex, blockComponentCount);
645 std::vector<size_t> importOffset =
646 batchOffset.get_import_offset(blockSubsetIndex, blockComponentCount);
647
648 // Map local and imported data to ioss_data.
649 for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) {
650 int64_t blk_seq = blockSubsetIndex[bsi];
651 const Ioss::BlockDecompositionData &block = blocks[blk_seq];
652 size_t comp_count = blockComponentCount[bsi];
653
654 for (size_t i = 0; i < block.localMap.size(); i++) {
655 for (size_t j = 0; j < comp_count; j++) {
656 size_t fileIndex = fileOffset[bsi] + block.localMap[i] * comp_count + j;
657 size_t iossIndex = iossOffset[bsi] + (i + block.localIossOffset) * comp_count + j;
658 ioss_data[iossIndex] = file_data[fileIndex];
659 }
660 }
661
662 for (size_t i = 0; i < block.importMap.size(); i++) {
663 for (size_t j = 0; j < comp_count; j++) {
664 size_t importIndex = importOffset[bsi] + i * comp_count + j;
665
666 size_t dataOffset = iossOffset[bsi];
667 size_t iossIndex = dataOffset + block.importMap[i] * comp_count + j;
668
669 ioss_data[iossIndex] = imports[importIndex];
670 }
671 }
672 }
673
674 return iossOffset;
675 }
676
677 template <typename T, typename U>
679 T *file_data, U *ioss_data, const std::vector<BlockDecompositionData> &blocks,
680 const std::vector<int64_t> &blockSubsetIndex, const std::vector<size_t> &fileOffset,
681 const std::vector<int> &blockComponentCount) const
682 {
683 show_progress(__func__);
684 if (m_method == "LINEAR") {
685 // For "LINEAR" decomposition method, the `file_data` is the
686 // same as `ioss_data` Transfer all local data from file_data
687 // to ioss_data...
688 auto size = fileOffset[blockSubsetIndex.size()];
689 std::copy(file_data, file_data + size, ioss_data);
690
691 Ioss::ElementBlockBatchOffset batchOffset(blocks);
692 return batchOffset.get_ioss_offset(blockSubsetIndex, blockComponentCount);
693 ;
694 }
695
696 auto retval = do_communicate_entity_data(file_data, ioss_data, blocks, blockSubsetIndex,
697 fileOffset, blockComponentCount);
698
699 return retval;
700 }
701
702 template <typename T>
703 void communicate_node_data(T *file_data, T *ioss_data, size_t comp_count) const
704 {
705 show_progress(__func__);
706 // Transfer the file-decomposition based data in 'file_data' to
707 // the ioss-decomposition based data in 'ioss_data'
708 std::vector<T> export_data(exportNodeMap.size() * comp_count);
709 std::vector<T> import_data(importNodeMap.size() * comp_count);
710
711 if (comp_count == 1) {
712 for (size_t i = 0; i < exportNodeMap.size(); i++) {
713 size_t index = exportNodeMap[i] - m_nodeOffset;
714 assert(index < m_nodeCount);
715 export_data[i] = file_data[index];
716 }
717
718 // Transfer all local data from file_data to ioss_data...
719 for (size_t i = 0; i < localNodeMap.size(); i++) {
720 size_t index = localNodeMap[i] - m_nodeOffset;
721 assert(index < m_nodeCount);
722 ioss_data[m_importPreLocalNodeIndex + i] = file_data[index];
723 }
724
725 // Get my imported data and send my exported data...
726 Ioss::MY_Alltoallv(export_data, exportNodeCount, exportNodeIndex, import_data,
728 show_progress("\tCommunication 1a finished");
729
730 // Copy the imported data into ioss_data...
731 for (size_t i = 0; i < importNodeMap.size(); i++) {
732 size_t index = importNodeMap[i];
733 assert(index < ioss_node_count());
734 ioss_data[index] = import_data[i];
735 }
736 }
737 else { // Comp_count > 1
738 for (size_t i = 0; i < exportNodeMap.size(); i++) {
739 size_t index = exportNodeMap[i] - m_nodeOffset;
740 assert(index < m_nodeCount);
741 for (size_t j = 0; j < comp_count; j++) {
742 export_data[comp_count * i + j] = file_data[comp_count * index + j];
743 }
744 }
745
746 // Transfer all local data from file_data to ioss_data...
747 for (size_t i = 0; i < localNodeMap.size(); i++) {
748 size_t index = localNodeMap[i] - m_nodeOffset;
749 assert(index < m_nodeCount);
750 for (size_t j = 0; j < comp_count; j++) {
751 ioss_data[comp_count * (m_importPreLocalNodeIndex + i) + j] =
752 file_data[comp_count * index + j];
753 }
754 }
755
756 std::vector<INT> export_count(exportNodeCount.begin(), exportNodeCount.end());
757 std::vector<INT> export_disp(exportNodeIndex.begin(), exportNodeIndex.end());
758 std::vector<INT> import_count(importNodeCount.begin(), importNodeCount.end());
759 std::vector<INT> import_disp(importNodeIndex.begin(), importNodeIndex.end());
760
761 for (int i = 0; i < m_processorCount; i++) {
762 export_count[i] *= comp_count;
763 export_disp[i] *= comp_count;
764 import_count[i] *= comp_count;
765 import_disp[i] *= comp_count;
766 }
767
768 // Get my imported data and send my exported data...
769 Ioss::MY_Alltoallv(export_data, export_count, export_disp, import_data, import_count,
770 import_disp, m_comm);
771 show_progress("\tCommunication 1b finished");
772
773 // Copy the imported data into ioss_data...
774 for (size_t i = 0; i < importNodeMap.size(); i++) {
775 size_t index = importNodeMap[i];
776 assert(index < ioss_node_count());
777 for (size_t j = 0; j < comp_count; j++) {
778 ioss_data[comp_count * index + j] = import_data[comp_count * i + j];
779 }
780 }
781 }
782 }
783
788 std::string m_method{};
789 std::string m_decompExtra{};
790
791 // Values for the file decomposition
795 size_t m_elementCount{0};
798
800 size_t m_nodeCount{0};
801 size_t m_nodeOffset{0};
803
805 bool m_lineDecomp{false};
806 bool m_showProgress{false};
807 bool m_showHWM{false};
808
809 std::vector<int> m_elementToProc; // Used by "MAP" scheme...
810 std::vector<double> m_centroids;
811 std::vector<float> m_weights;
812 std::vector<INT> m_pointer; // Index into adjacency, processor list for each element...
813 std::vector<INT> m_adjacency; // Size is sum of element connectivity sizes
814
815 std::vector<INT> m_nodeCommMap; // node/processor pair of the
816 // nodes I communicate with. Stored node#,proc,node#,proc, ...
817
818 // The global element at index 'I' (0-based) is on block B in the
819 // file decomposition.
820 // if m_fileBlockIndex[B] <= I && m_fileBlockIndex[B+1] < I
821 std::vector<size_t> m_fileBlockIndex;
822
823 private:
824 // This processor "manages" the elements on the exodus mesh file from
825 // m_elementOffset to m_elementOffset+m_elementCount (0-based). This is
826 // 'file' data
827 //
828 // This processor also appears to the Ioss clients to own other
829 // element and node data based on the decomposition. This is the
830 // 'ioss' data.
831 //
832 // The indices in `localElementMap` are the elements that are
833 // common to both the 'file' data and the 'ioss' data.
834 // `localElementMap[i]` contains the location in 'file' data for
835 // the 'ioss' data at location `i+m_importPreLocalElemIndex`
836 //
837 // local_element_map[i]+m_elementOffset is the 0-based global index
838 //
839 // The indices in 'import_element_map' map the data received via
840 // mpi communication from other processors into 'ioss' data.
841 // if 'ind=import_element_map[i]', then ioss[ind] = comm_recv[i]
842 // Note that this is the reverse direction of the
843 // local_element_map mapping.
844 //
845 // The indices in 'export_element_map' are used to pull from
846 // 'file' data into the comm_send vector. if 'ind =
847 // export_element_map[i]', then 'comm_send[i] = file[ind]' for i =
848 // 0..#exported_elements
849 //
850 // local_element_map.size() + import_element_map.size() ==
851 // #ioss elements on this processor.
852 //
853 // local_element_map.size() + export_element_map.size() ==
854 // #file elements on this processor.
855 //
856 // export_element_map and import_element_map are sorted.
857 // The primary key is processor order followed by global id.
858 // The processor association is via 'export_proc_disp' and
859 // 'import_proc_disp' Both are of size '#processors+1' and
860 // the elements for processor p range from [X_proc_disp[p] to
861 // X_proc_disp[p+1])
862
863 std::vector<INT> localElementMap;
864
865 std::vector<INT> importElementMap;
866 std::vector<INT> importElementCount;
867 std::vector<INT> importElementIndex;
868
869 // The list of my `file decomp` elements that will be exported to some other rank.
870 std::vector<INT> exportElementMap;
871 // The number of elements that I will export to each other rank.
872 std::vector<INT> exportElementCount;
873 // The index into `exportElementMap` for the elements that will be exported to each rank.
874 std::vector<INT> exportElementIndex;
875
876 std::vector<INT> nodeIndex;
877
878 std::vector<INT> exportNodeMap;
879 std::vector<INT> exportNodeCount;
880 std::vector<INT> exportNodeIndex;
881
882 // Where to put each imported nodes data in the list of all data...
883 std::vector<INT> importNodeMap;
884 std::vector<INT> importNodeCount;
885 std::vector<INT> importNodeIndex;
886
887 std::vector<INT> localNodeMap;
888
889 std::vector<INT> m_elementDist;
890 std::vector<INT> m_nodeDist;
891
892 // Note that nodeGTL is a sorted vector.
893 std::vector<INT> nodeGTL; // Convert from global index to local index (1-based)
894
895#if defined DC_USE_HOPSCOTCH
896 tsl::hopscotch_pg_map<INT, INT> elemGTL; // Convert from global index to local index (1-based)
897#elif defined DC_USE_ROBIN
898 tsl::robin_pg_map<INT, INT> elemGTL; // Convert from global index to local index (1-based)
899#elif defined DC_USE_VECTOR
900 std::vector<std::pair<INT, INT>> elemGTL; // Convert from global index to local index (1-based)
901#else
902 // This is the original method that was used in IOSS prior to using hopscotch or robin map.
903 std::map<INT, INT> elemGTL; // Convert from global index to local index (1-based)
904#endif
905 };
906} // namespace Ioss
#define IOSS_NODISCARD
Definition Ioss_CodeTypes.h:55
int Ioss_MPI_Comm
Definition Ioss_CodeTypes.h:64
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:879
std::vector< INT > localElementMap
Definition Ioss_Decomposition.h:863
std::vector< INT > importNodeCount
Definition Ioss_Decomposition.h:884
std::vector< INT > exportElementMap
Definition Ioss_Decomposition.h:870
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:788
void build_global_to_local_elem_map()
Definition Ioss_Decomposition.C:1271
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:678
std::vector< INT > exportNodeMap
Definition Ioss_Decomposition.h:878
std::vector< double > m_centroids
Definition Ioss_Decomposition.h:810
void communicate_element_data(T *file_data, T *ioss_data, size_t comp_count) const
Definition Ioss_Decomposition.h:328
bool m_retainFreeNodes
Definition Ioss_Decomposition.h:804
void guided_decompose()
Definition Ioss_Decomposition.C:684
std::vector< INT > importNodeIndex
Definition Ioss_Decomposition.h:885
std::vector< INT > m_elementDist
Definition Ioss_Decomposition.h:889
std::vector< INT > exportNodeCount
Definition Ioss_Decomposition.h:879
std::vector< int > m_elementToProc
Definition Ioss_Decomposition.h:809
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:568
std::vector< INT > nodeGTL
Definition Ioss_Decomposition.h:893
Ioss_MPI_Comm m_comm
Definition Ioss_Decomposition.h:784
bool m_showHWM
Definition Ioss_Decomposition.h:807
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:993
std::vector< INT > m_nodeCommMap
Definition Ioss_Decomposition.h:815
std::vector< size_t > m_fileBlockIndex
Definition Ioss_Decomposition.h:821
size_t m_elementOffset
Definition Ioss_Decomposition.h:796
std::vector< INT > exportNodeIndex
Definition Ioss_Decomposition.h:880
void simple_node_decompose()
Definition Ioss_Decomposition.C:844
void get_element_block_communication(std::vector< BlockDecompositionData > &el_blocks)
Definition Ioss_Decomposition.C:336
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:300
IOSS_NODISCARD size_t ioss_node_count() const
Definition Ioss_Decomposition.h:190
int m_processor
Definition Ioss_Decomposition.h:786
void get_local_element_list(const ZOLTAN_ID_PTR &export_global_ids, size_t export_count)
Definition Ioss_Decomposition.C:1233
int m_commonNodeCount
Definition Ioss_Decomposition.h:793
IOSS_NODISCARD bool i_own_elem(size_t global_index) const
Definition Ioss_Decomposition.h:216
size_t m_nodeOffset
Definition Ioss_Decomposition.h:801
void communicate_node_data(T *file_data, T *ioss_data, size_t comp_count) const
Definition Ioss_Decomposition.h:703
Decomposition(const Ioss::PropertyManager &props, Ioss_MPI_Comm comm)
Definition Ioss_Decomposition.C:285
size_t m_globalElementCount
Definition Ioss_Decomposition.h:794
void simple_decompose()
Definition Ioss_Decomposition.C:824
void decompose_model(Zoltan &zz, std::vector< BlockDecompositionData > &element_blocks)
Definition Ioss_Decomposition.C:418
std::vector< INT > m_nodeDist
Definition Ioss_Decomposition.h:890
size_t m_importPreLocalElemIndex
Definition Ioss_Decomposition.h:797
std::vector< INT > importElementMap
Definition Ioss_Decomposition.h:865
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:322
void communicate_block_data(T *file_data, U *ioss_data, const BlockDecompositionData &block, size_t comp_count) const
Definition Ioss_Decomposition.h:489
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:813
IOSS_NODISCARD bool needs_centroids() const
Definition Ioss_Decomposition.h:200
bool m_showProgress
Definition Ioss_Decomposition.h:806
void communicate_set_data(T *file_data, T *ioss_data, const SetDecompositionData &set, size_t comp_count) const
Definition Ioss_Decomposition.h:431
std::vector< INT > importElementCount
Definition Ioss_Decomposition.h:866
IOSS_NODISCARD size_t file_elem_count() const
Definition Ioss_Decomposition.h:196
Ioss::ParallelUtils m_pu
Definition Ioss_Decomposition.h:785
size_t m_importPreLocalNodeIndex
Definition Ioss_Decomposition.h:802
std::vector< INT > exportElementIndex
Definition Ioss_Decomposition.h:874
std::string m_decompExtra
Definition Ioss_Decomposition.h:789
Decomposition(Decomposition &&)=default
std::vector< INT > nodeIndex
Definition Ioss_Decomposition.h:876
size_t m_nodeCount
Definition Ioss_Decomposition.h:800
std::vector< INT > m_pointer
Definition Ioss_Decomposition.h:812
std::vector< INT > localNodeMap
Definition Ioss_Decomposition.h:887
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:900
bool m_lineDecomp
Definition Ioss_Decomposition.h:805
std::vector< INT > exportElementCount
Definition Ioss_Decomposition.h:872
void zoltan_decompose(Zoltan &zz)
Definition Ioss_Decomposition.C:1096
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:517
Decomposition & operator=(Decomposition &&)=default
int m_processorCount
Definition Ioss_Decomposition.h:787
void get_local_node_list()
Definition Ioss_Decomposition.C:1314
size_t m_globalNodeCount
Definition Ioss_Decomposition.h:799
std::vector< float > m_weights
Definition Ioss_Decomposition.h:811
std::vector< INT > importElementIndex
Definition Ioss_Decomposition.h:867
int m_spatialDimension
Definition Ioss_Decomposition.h:792
IOSS_NODISCARD size_t global_node_count() const
Definition Ioss_Decomposition.h:188
std::vector< INT > importNodeMap
Definition Ioss_Decomposition.h:883
void get_shared_node_list()
Definition Ioss_Decomposition.C:1522
size_t m_elementCount
Definition Ioss_Decomposition.h:795
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:223
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:201
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:32
IOSS_NODISCARD int parallel_size() const
Definition Ioss_ParallelUtils.C:206
static IOSS_NODISCARD constexpr Ioss_MPI_Comm comm_null()
Definition Ioss_ParallelUtils.h:50
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:177
Definition hopscotch_map.h:82
Definition robin_map.h:90
The main namespace for the Ioss library.
Definition Ioad_DatabaseIO.C:40
Ioss::NameList NameList
Definition Ioss_ChangeSetFactory.h:25
IOSS_EXPORT const Ioss::NameList & valid_decomp_methods()
Definition Ioss_Decomposition.C:142
std::vector< int64_t > MapContainer
Definition Ioss_Map.h:29