10 MoFEMErrorCode MatPartitioningApply_Parmetis_MoFEM(MatPartitioning part,
24 : cOre(const_cast<
MoFEM::
Core &>(core)), dEbug(false) {}
27 Range &ents, std::map<int, Range> *received_ents,
int verb) {
29 ParallelComm *pcomm = ParallelComm::get_pcomm(
33 auto get_pstatus = [&](
const auto ent) {
34 unsigned char pstatus;
37 "can not get pstatus");
41 auto get_sharing_procs = [&](
const auto ent,
const auto pstatus) {
42 std::vector<int> sharing_procs(MAX_SHARING_PROCS, -1);
43 if (pstatus & PSTATUS_MULTISHARED) {
46 pcomm->sharedps_tag(), &ent, 1, &sharing_procs[0]),
47 "can not ger sharing_procs_ptr");
48 }
else if (pstatus & PSTATUS_SHARED) {
51 1, &sharing_procs[0]),
52 "can not get sharing proc");
57 auto get_sharing_handles = [&](
const auto ent,
const auto pstatus) {
58 std::vector<EntityHandle> sharing_handles(MAX_SHARING_PROCS, 0);
59 if (pstatus & PSTATUS_MULTISHARED) {
62 pcomm->sharedhs_tag(), &ent, 1, &sharing_handles[0]),
63 "get shared handles");
64 }
else if (pstatus & PSTATUS_SHARED) {
67 1, &sharing_handles[0]),
68 "get sharing handle");
70 return sharing_handles;
74 std::vector<std::vector<EntityHandle>> sbuffer(m_field.
get_comm_size());
76 for (
auto ent : ents) {
78 auto pstatus = get_pstatus(ent);
80 auto sharing_procs = get_sharing_procs(ent, pstatus);
81 auto sharing_handles = get_sharing_handles(ent, pstatus);
84 MOFEM_LOG(
"SYNC", Sev::noisy) <<
"pstatus " << std::bitset<8>(pstatus);
87 for (
int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
89 if (sharing_procs[proc] == -1)
91 "sharing processor not set");
96 const auto handle_on_sharing_proc = sharing_handles[proc];
98 sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
100 MOFEM_LOG_C(
"SYNC", Sev::noisy,
"send %lu (%lu) to %d at %d\n", ent,
101 handle_on_sharing_proc, sharing_procs[proc],
105 if (!(pstatus & PSTATUS_MULTISHARED))
115 std::vector<int> sbuffer_lengths(
117 const size_t block_size =
122 if (!sbuffer[proc].empty()) {
124 sbuffer_lengths[proc] = sbuffer[proc].size() * block_size;
129 sbuffer_lengths[proc] = 0;
141 CHKERR PetscGatherNumberOfMessages(comm, NULL, &sbuffer_lengths[0], &nrecvs);
147 CHKERR PetscGatherMessageLengths(comm, nsends, nrecvs, &sbuffer_lengths[0],
155 CHKERR PetscCommGetNewTag(comm, &tag);
160 MPI_Request *r_waits;
164 CHKERR PetscPostIrecvInt(comm, tag, nrecvs, onodes, olengths, &rbuf,
167 MPI_Request *s_waits;
168 CHKERR PetscMalloc1(nsends, &s_waits);
171 for (
int proc = 0, kk = 0; proc < m_field.
get_comm_size(); proc++) {
172 if (!sbuffer_lengths[proc])
174 CHKERR MPI_Isend(&(sbuffer[proc])[0],
175 sbuffer_lengths[proc],
177 tag, comm, s_waits + kk);
183 CHKERR MPI_Waitall(nrecvs, r_waits, &status[0]);
187 CHKERR MPI_Waitall(nsends, s_waits, &status[0]);
190 MOFEM_LOG_C(
"SYNC", Sev::verbose,
"Rank %d nb. before ents %u\n",
196 for (
int kk = 0; kk < nrecvs; kk++) {
198 int len = olengths[kk];
199 int *data_from_proc = rbuf[kk];
201 for (
int ee = 0; ee < len;) {
207 (*received_ents)[onodes[kk]].insert(ent);
213 MOFEM_LOG_C(
"SYNC", Sev::noisy,
"received %lu from %d at %d\n", ent,
223 MOFEM_LOG_C(
"SYNC", Sev::verbose,
"Rank %d nb. after ents %u",
229 CHKERR PetscFree(s_waits);
230 CHKERR PetscFree(rbuf[0]);
232 CHKERR PetscFree(r_waits);
234 CHKERR PetscFree(olengths);
235 CHKERR PetscCommDestroy(&comm);
250 CHKERR m_field.
get_moab().get_entities_by_handle(idm, ents,
false);
259 ParallelComm *pcomm = ParallelComm::get_pcomm(
265 CHKERR pcomm->filter_pstatus(shared, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
267 CHKERR pcomm->filter_pstatus(shared, PSTATUS_SHARED | PSTATUS_MULTISHARED,
268 PSTATUS_OR, -1,
nullptr);
273 auto get_pstatus = [&](
const auto ent) {
274 unsigned char pstatus;
277 "can not get pstatus");
281 auto get_sharing_procs = [&](
const auto ent,
const auto pstatus) {
282 std::vector<int> sharing_procs(MAX_SHARING_PROCS, -1);
283 if (pstatus & PSTATUS_MULTISHARED) {
286 pcomm->sharedps_tag(), &ent, 1, &sharing_procs[0]),
287 "can not ger sharing_procs_ptr");
288 }
else if (pstatus & PSTATUS_SHARED) {
291 1, &sharing_procs[0]),
292 "can not get sharing proc");
294 return sharing_procs;
297 auto get_sharing_handles = [&](
const auto ent,
const auto pstatus) {
298 std::vector<EntityHandle> sharing_handles(MAX_SHARING_PROCS, 0);
299 if (pstatus & PSTATUS_MULTISHARED) {
302 pcomm->sharedhs_tag(), &ent, 1, &sharing_handles[0]),
303 "get shared handles");
304 }
else if (pstatus & PSTATUS_SHARED) {
307 1, &sharing_handles[0]),
308 "get sharing handle");
310 return sharing_handles;
313 auto get_parent_and_bit = [&](
const auto ent) {
316 m_field.
get_moab().tag_get_data(th_RefParentHandle, &ent, 1, &parent),
320 m_field.
get_moab().tag_get_data(th_RefBitLevel, &ent, 1, &
bit),
322 return std::make_pair(parent,
bit);
325 auto set_parent = [&](
const auto ent,
const auto parent) {
326 return m_field.
get_moab().tag_set_data(th_RefParentHandle, &ent, 1,
330 auto set_bit = [&](
const auto ent,
const auto bit) {
331 return m_field.
get_moab().tag_set_data(th_RefBitLevel, &ent, 1, &
bit);
335 std::vector<std::vector<unsigned long long>> sbuffer(m_field.
get_comm_size());
337 for (
auto ent : shared) {
339 auto pstatus = get_pstatus(ent);
340 auto sharing_procs = get_sharing_procs(ent, pstatus);
341 auto sharing_handles = get_sharing_handles(ent, pstatus);
342 auto [parent,
bit] = get_parent_and_bit(ent);
345 MOFEM_LOG(
"SYNC", Sev::noisy) <<
"pstatus " << std::bitset<8>(pstatus);
348 auto pstatus_parent = get_pstatus(parent);
349 auto sharing_procs_parent = get_sharing_procs(parent, pstatus_parent);
350 auto sharing_handles_parent = get_sharing_handles(parent, pstatus_parent);
352 for (
int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
354 if (sharing_procs[proc] == -1)
356 "sharing processor not set");
360 auto it = std::find(sharing_procs_parent.begin(),
361 sharing_procs_parent.end(), sharing_procs[proc]);
362 if (it == sharing_procs_parent.end()) {
365 "Sharing proc for parent entity can not be found proc = %u",
366 sharing_procs[proc]);
369 auto handle_on_sharing_proc = sharing_handles[proc];
370 auto parent_handle_on_sharing_proc =
371 sharing_handles_parent[std::distance(sharing_procs_parent.begin(),
373 sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
374 sbuffer[sharing_procs[proc]].push_back(parent_handle_on_sharing_proc);
376 sbuffer[sharing_procs[proc]].push_back(
bit.to_ullong());
377 }
catch (std::exception &ex) {
378 MOFEM_LOG(
"SELF", Sev::warning) << ex.what();
380 <<
"On " << ent <<
" "
382 MOFEM_LOG(
"SELF", Sev::warning) <<
"For bit ref " <<
bit;
385 MOFEM_LOG_C(
"SYNC", Sev::noisy,
"send %lu (%lu) to %d at %d\n", ent,
386 handle_on_sharing_proc, sharing_procs[proc],
389 if (!(pstatus & PSTATUS_MULTISHARED))
394 for (
int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
396 if (sharing_procs[proc] == -1)
398 "sharing processor not set");
401 auto handle_on_sharing_proc = sharing_handles[proc];
402 sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
403 sbuffer[sharing_procs[proc]].push_back(parent);
406 sbuffer[sharing_procs[proc]].push_back(
bit.to_ullong());
407 }
catch (std::exception &ex) {
408 MOFEM_LOG(
"SELF", Sev::warning) << ex.what();
410 <<
"On " << ent <<
" "
412 MOFEM_LOG(
"SELF", Sev::warning) <<
"For bit ref " <<
bit;
416 MOFEM_LOG_C(
"SYNC", Sev::noisy,
"send %lu (%lu) to %d at %d\n", ent,
417 handle_on_sharing_proc, sharing_procs[proc],
420 if (!(pstatus & PSTATUS_MULTISHARED))
428 std::vector<int> sbuffer_lengths(
431 const size_t block_size =
sizeof(
unsigned long long) /
sizeof(
int);
434 if (!sbuffer[proc].empty()) {
436 sbuffer_lengths[proc] = sbuffer[proc].size() * block_size;
441 sbuffer_lengths[proc] = 0;
453 CHKERR PetscGatherNumberOfMessages(comm, NULL, &sbuffer_lengths[0], &nrecvs);
459 CHKERR PetscGatherMessageLengths(comm, nsends, nrecvs, &sbuffer_lengths[0],
467 CHKERR PetscCommGetNewTag(comm, &tag);
472 MPI_Request *r_waits;
476 CHKERR PetscPostIrecvInt(comm, tag, nrecvs, onodes, olengths, &rbuf,
479 MPI_Request *s_waits;
480 CHKERR PetscMalloc1(nsends, &s_waits);
483 for (
int proc = 0, kk = 0; proc < m_field.
get_comm_size(); proc++) {
484 if (!sbuffer_lengths[proc])
486 CHKERR MPI_Isend(&(sbuffer[proc])[0],
487 sbuffer_lengths[proc],
489 tag, comm, s_waits + kk);
495 CHKERR MPI_Waitall(nrecvs, r_waits, &status[0]);
499 CHKERR MPI_Waitall(nsends, s_waits, &status[0]);
503 "Rank %d nb. shared to synchronise parents ents %u\n",
508 for (
int kk = 0; kk < nrecvs; kk++) {
510 int len = olengths[kk];
511 int *data_from_proc = rbuf[kk];
513 for (
int ee = 0; ee < len;) {
516 unsigned long long uulong_bit;
519 bcopy(&data_from_proc[ee], &parent,
sizeof(
EntityHandle));
521 bcopy(&data_from_proc[ee], &uulong_bit,
sizeof(
unsigned long long));
524 CHKERR set_parent(ent, parent);
528 MOFEM_LOG_C(
"SYNC", Sev::noisy,
"received %lu (%lu) from %d at %d\n",
536 CHKERR PetscFree(s_waits);
537 CHKERR PetscFree(rbuf[0]);
539 CHKERR PetscFree(r_waits);
541 CHKERR PetscFree(olengths);
542 CHKERR PetscCommDestroy(&comm);
551 const Problem *problem_ptr,
const std::string &fe_name,
int verb) {
554 ParallelComm *pcomm = ParallelComm::get_pcomm(
556 std::vector<int> shprocs(MAX_SHARING_PROCS, 0);
557 std::vector<EntityHandle> shhandles(MAX_SHARING_PROCS, 0);
559 Tag th_gid = m_field.
get_moab().globalId_tag();
564 CHKERR PetscLayoutGetRange(layout, &gid, &last_gid);
565 CHKERR PetscLayoutDestroy(&layout);
575 0, (*fe_miit)->getFEUId()));
579 get_id_for_max_type<MBENTITYSET>(), (*fe_miit)->getFEUId()));
580 for (; fit != hi_fe_it; ++fit) {
582 auto ent = (*fit)->getEnt();
583 auto part = (*fit)->getPart();
586 CHKERR m_field.
get_moab().tag_set_data(pcomm->part_tag(), &ent, 1, &part);
587 if (part == pcomm->rank()) {
594 if (pcomm->size() > 1) {
596 unsigned char pstatus = 0;
597 if (pcomm->rank() != part) {
598 pstatus = PSTATUS_NOT_OWNED;
599 pstatus |= PSTATUS_GHOST;
602 if (pcomm->size() > 2) {
603 pstatus |= PSTATUS_SHARED;
604 pstatus |= PSTATUS_MULTISHARED;
606 pstatus |= PSTATUS_SHARED;
610 for (
size_t rr = 0; rr < pcomm->size(); ++rr) {
611 if (rr != pcomm->rank()) {
612 shhandles[rrr] = ent;
617 for (; rrr != pcomm->size(); ++rrr)
620 if (pstatus & PSTATUS_SHARED) {
621 CHKERR m_field.
get_moab().tag_set_data(pcomm->sharedp_tag(), &ent, 1,
623 CHKERR m_field.
get_moab().tag_set_data(pcomm->sharedh_tag(), &ent, 1,
627 if (pstatus & PSTATUS_MULTISHARED) {
628 CHKERR m_field.
get_moab().tag_set_data(pcomm->sharedps_tag(), &ent, 1,
630 CHKERR m_field.
get_moab().tag_set_data(pcomm->sharedhs_tag(), &ent, 1,
633 CHKERR m_field.
get_moab().tag_set_data(pcomm->pstatus_tag(), &ent, 1,
639 CHKERR pcomm->exchange_tags(th_gid, ents);
644 const std::string name,
const std::string &fe_name,
int verb) {
655 const int num_entities,
656 const int owner_proc,
int verb) {
662 ParallelComm *pcomm = ParallelComm::get_pcomm(
665 Range all_ents_range;
666 all_ents_range.insert_list(entities, entities + num_entities);
668 auto get_tag = [&]() {
669 const int negone = -1;
671 m_field.
get_moab().tag_get_handle(
"TMP_GLOBAL_ID_TAG_NAME", 1,
673 MB_TAG_CREAT | MB_TAG_SPARSE, &negone);
677 auto delete_tag = [&](
auto &&th_gid) {
683 auto resolve_shared_ents = [&](
auto &&th_gid,
auto &all_ents_range) {
684 auto set_gid = [&](
auto &th_gid) {
685 std::vector<int> gids(num_entities);
686 for (
size_t g = 0;
g != all_ents_range.size(); ++
g)
694 auto get_skin_ents = [&](
auto &all_ents_range) {
695 std::array<Range, 4> proc_ents_skin;
696 proc_ents_skin[3] = all_ents_range.subset_by_dimension(3);
697 proc_ents_skin[2] = all_ents_range.subset_by_dimension(2);
698 proc_ents_skin[1] = all_ents_range.subset_by_dimension(1);
699 proc_ents_skin[0] = all_ents_range.subset_by_dimension(0);
700 return proc_ents_skin;
703 auto resolve_dim = [&](
auto &all_ents_range) {
704 for (
int resolve_dim = 3; resolve_dim >= 0; --resolve_dim) {
705 if (all_ents_range.num_of_dimension(resolve_dim))
711 auto get_proc_ent = [&](
auto &all_ents_range) {
714 proc_ent = all_ents_range;
718 auto resolve_shared_ents = [&](
auto &&proc_ents,
auto &&skin_ents) {
719 return pcomm->resolve_shared_ents(
720 0, proc_ents, resolve_dim(all_ents_range),
721 resolve_dim(all_ents_range), skin_ents.data(), set_gid(th_gid));
724 CHKERR resolve_shared_ents(get_proc_ent(all_ents_range),
725 get_skin_ents(all_ents_range));
730 CHKERR delete_tag(resolve_shared_ents(get_tag(), all_ents_range));
738 CHKERR pcomm->get_owner_handle(e, moab_owner_proc, moab_owner_handle);
740 unsigned char pstatus = 0;
742 CHKERR m_field.
get_moab().tag_get_data(pcomm->pstatus_tag(), &e, 1,
745 std::vector<int> shprocs(MAX_SHARING_PROCS, 0);
746 std::vector<EntityHandle> shhandles(MAX_SHARING_PROCS, 0);
748 CHKERR m_field.
get_moab().tag_get_data(pcomm->sharedp_tag(), &e, 1,
750 CHKERR m_field.
get_moab().tag_get_data(pcomm->sharedh_tag(), &e, 1,
752 if (pstatus & PSTATUS_MULTISHARED) {
753 CHKERR m_field.
get_moab().tag_get_data(pcomm->sharedps_tag(), &e, 1,
755 CHKERR m_field.
get_moab().tag_get_data(pcomm->sharedhs_tag(), &e, 1,
759 std::ostringstream ss;
762 if (!(pstatus & PSTATUS_NOT_OWNED))
764 if (pstatus & PSTATUS_SHARED)
765 ss <<
"PSTATUS_SHARED ";
766 if (pstatus & PSTATUS_MULTISHARED)
767 ss <<
"PSTATUS_MULTISHARED ";
769 ss <<
"owner " << moab_owner_proc <<
" (" << owner_proc <<
") ";
773 ss << shprocs[
r] <<
" ";
777 ss << shhandles[
r] <<
" ";
780 MOFEM_LOG(
"SYNC", Sev::noisy) << ss.str();
786 for (
auto e : all_ents_range)
795 const int owner_proc,
800 const int num_ents = entities.size();
801 std::vector<EntityHandle> vec_ents(num_ents);
802 std::copy(entities.begin(), entities.end(), vec_ents.begin());
811 const int owner_proc,
int verb) {
816 std::vector<EntityHandle> field_ents;
817 CHKERR m_field.
get_moab().get_entities_by_handle(field_meshset, field_ents,
831 Range exchange_ents_data_verts, exchange_ents_data;
840 for (
auto it = lo; it != hi; ++it)
843 ((*it)->getPStatus()) &&
845 (*it)->getNbDofsOnEnt()
848 if ((*it)->getEntType() == MBVERTEX)
849 exchange_ents_data_verts.insert((*it)->getEnt());
851 exchange_ents_data.insert((*it)->getEnt());
855 ParallelComm *pcomm = ParallelComm::get_pcomm(
858 auto exchange = [&](
const Range &ents, Tag
th) {
861 std::vector<Tag> tags;
863 CHKERR pcomm->exchange_tags(tags, tags, ents);
868 CHKERR exchange(exchange_ents_data_verts, field_ptr->th_FieldDataVerts);
869 CHKERR exchange(exchange_ents_data, field_ptr->th_FieldData);
876 const int adj_dim,
const int n_parts,
877 Tag *th_vertex_weights, Tag *th_edge_weights,
878 Tag *th_part_weights,
int verb,
const bool debug) {
883 int rstart, rend, nb_elems;
887 CHKERR PetscLayoutSetBlockSize(layout, 1);
888 CHKERR PetscLayoutSetSize(layout, ents.size());
889 CHKERR PetscLayoutSetUp(layout);
890 CHKERR PetscLayoutGetSize(layout, &nb_elems);
891 CHKERR PetscLayoutGetRange(layout, &rstart, &rend);
892 CHKERR PetscLayoutDestroy(&layout);
895 <<
"Finite elements in problem: row lower " << rstart <<
" row upper "
896 << rend <<
" nb. elems " << nb_elems <<
" ( " << ents.size() <<
" )";
901 std::vector<EntityHandle> weight_ents;
902 weight_ents.reserve(rend - rstart + 1);
906 std::vector<int> adj;
907 AdjBridge(
const EntityHandle ent, std::vector<int> &adj)
908 : ent(ent), adj(adj) {}
911 typedef multi_index_container<
915 hashed_unique<member<AdjBridge, EntityHandle, &AdjBridge::ent>>
920 auto get_it = [&](
auto i) {
921 auto it = ents.begin();
923 if (it == ents.end())
931 proc_ents.insert(get_it(rstart), get_it(rend));
932 if (proc_ents.size() != rend - rstart)
934 "Wrong number of elements in range %d != %d", proc_ents.size(),
939 proc_ents, adj_dim,
true, all_dim_ents, moab::Interface::UNION);
941 AdjBridgeMap adj_bridge_map;
942 auto hint = adj_bridge_map.begin();
943 std::vector<int> adj;
944 for (
auto ent : all_dim_ents) {
946 CHKERR m_field.
get_moab().get_adjacencies(&ent, 1, dim,
false, adj_ents);
947 adj_ents = intersect(adj_ents, ents);
949 adj.reserve(adj_ents.size());
950 for (
auto a : adj_ents)
951 adj.emplace_back(ents.index(
a));
952 hint = adj_bridge_map.emplace_hint(hint, ent, adj);
958 const int nb_loc_elements = rend - rstart;
959 std::vector<int>
i(nb_loc_elements + 1, 0),
j;
961 std::vector<int> row_adj;
962 Range::iterator fe_it;
965 for (fe_it = proc_ents.begin(), ii = rstart, jj = 0, max_row_size = 0;
966 fe_it != proc_ents.end(); ++fe_it, ++ii) {
970 "not yet implemented, don't know what to do for meshset "
975 CHKERR m_field.
get_moab().get_adjacencies(&*fe_it, 1, adj_dim,
false,
977 dim_ents = intersect(dim_ents, all_dim_ents);
980 for (
auto e : dim_ents) {
981 auto adj_it = adj_bridge_map.find(e);
982 if (adj_it != adj_bridge_map.end()) {
984 for (
const auto idx : adj_it->adj)
985 row_adj.push_back(idx);
992 std::sort(row_adj.begin(), row_adj.end());
993 auto end = std::unique(row_adj.begin(), row_adj.end());
995 size_t row_size = std::distance(row_adj.begin(), end);
996 max_row_size = std::max(max_row_size, row_size);
997 if (
j.capacity() < (nb_loc_elements - jj) * max_row_size)
998 j.reserve(nb_loc_elements * max_row_size);
1001 auto diag = ents.index(*fe_it);
1002 for (
auto it = row_adj.begin(); it != end; ++it)
1009 if (th_vertex_weights != NULL)
1010 weight_ents.push_back(*fe_it);
1016 CHKERR PetscMalloc(
i.size() *
sizeof(
int), &_i);
1017 CHKERR PetscMalloc(
j.size() *
sizeof(
int), &_j);
1018 copy(
i.begin(),
i.end(), _i);
1019 copy(
j.begin(),
j.end(), _j);
1023 int *vertex_weights = NULL;
1024 if (th_vertex_weights != NULL) {
1025 CHKERR PetscMalloc(weight_ents.size() *
sizeof(
int), &vertex_weights);
1027 &*weight_ents.begin(),
1028 weight_ents.size(), vertex_weights);
1034 CHKERR MatCreateMPIAdj(m_field.
get_comm(), rend - rstart, nb_elems, _i, _j,
1036 CHKERR MatSetOption(Adj, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE);
1040 CHKERR MatConvert(Adj, MATMPIAIJ, MAT_INITIAL_MATRIX, &
A);
1041 CHKERR MatView(
A, PETSC_VIEWER_DRAW_WORLD);
1048 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Start";
1050 MatPartitioning part;
1054 CHKERR MatPartitioningSetAdjacency(part, Adj);
1055 CHKERR MatPartitioningSetFromOptions(part);
1056 CHKERR MatPartitioningSetNParts(part, n_parts);
1057 if (th_vertex_weights != NULL) {
1058 CHKERR MatPartitioningSetVertexWeights(part, vertex_weights);
1061 PetscObjectTypeCompare((PetscObject)part, MATPARTITIONINGPARMETIS, &same);
1064 CHKERR MatPartitioningApply_Parmetis_MoFEM(part, &is);
1067 CHKERR MatPartitioningApply(part, &is);
1070 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"End";
1073 IS is_gather, is_num, is_gather_num;
1074 CHKERR ISAllGather(is, &is_gather);
1075 CHKERR ISPartitioningToNumbering(is, &is_num);
1076 CHKERR ISAllGather(is_num, &is_gather_num);
1078 const int *part_number, *gids;
1079 CHKERR ISGetIndices(is_gather, &part_number);
1080 CHKERR ISGetIndices(is_gather_num, &gids);
1083 ParallelComm *pcomm = ParallelComm::get_pcomm(
1085 Tag part_tag = pcomm->part_tag();
1086 CHKERR m_field.
get_moab().tag_set_data(part_tag, ents, part_number);
1087 Tag gid_tag = m_field.
get_moab().globalId_tag();
1089 std::map<int, Range> parts_ents;
1092 Range::iterator eit = ents.begin();
1093 for (
int ii = 0; eit != ents.end(); eit++, ii++) {
1094 parts_ents[part_number[ii]].insert(*eit);
1098 0, MBENTITYSET, &part_tag, NULL, 1, tagged_sets,
1099 moab::Interface::UNION);
1100 if (!tagged_sets.empty())
1101 CHKERR m_field.
get_moab().tag_delete_data(part_tag, tagged_sets);
1103 if (n_parts > (
int)tagged_sets.size()) {
1105 int num_new = n_parts - tagged_sets.size();
1106 for (
int i = 0;
i < num_new;
i++) {
1109 tagged_sets.insert(new_set);
1111 }
else if (n_parts < (
int)tagged_sets.size()) {
1113 int num_del = tagged_sets.size() - n_parts;
1114 for (
int i = 0;
i < num_del;
i++) {
1121 std::vector<int> dum_ids(n_parts);
1122 for (
int i = 0;
i < n_parts;
i++)
1129 for (
int pp = 0; pp != n_parts; pp++) {
1130 Range dim_ents = parts_ents[pp].subset_by_dimension(dim);
1131 for (
int dd = dim - 1;
dd >= 0;
dd--) {
1134 dim_ents,
dd,
false, adj_ents, moab::Interface::UNION);
1135 parts_ents[pp].merge(adj_ents);
1138 for (
int pp = 1; pp != n_parts; pp++) {
1139 for (
int ppp = 0; ppp != pp; ppp++) {
1140 parts_ents[pp] = subtract(parts_ents[pp], parts_ents[ppp]);
1144 for (
int pp = 0; pp != n_parts; pp++) {
1145 CHKERR m_field.
get_moab().add_entities(tagged_sets[pp], parts_ents[pp]);
1148 auto set_part = [&]() {
1150 for (EntityType
t = MBEDGE;
t != MBENTITYSET; ++
t) {
1151 for (
int pp = 0; pp != n_parts; pp++) {
1152 Range type_ents = parts_ents[pp].subset_by_type(
t);
1153 CHKERR m_field.
get_moab().tag_clear_data(part_tag, type_ents, &pp);
1159 auto set_gid = [&]() {
1161 for (
int d = 0;
d != 4; ++
d) {
1167 for (
int pp = 0; pp != n_parts; pp++) {
1168 Range type_ents = parts_ents[pp].subset_by_dimension(
d);
1170 auto eit = type_ents.begin();
1171 for (; eit != type_ents.end();) {
1173 gid_tag, eit, type_ents.end(), count, ptr);
1174 auto gid_tag_ptr =
static_cast<int *
>(ptr);
1175 for (; count > 0; --count) {
1194 for (
int rr = 0; rr != n_parts; rr++) {
1196 ss <<
"out_part_" << rr <<
".vtk";
1197 MOFEM_LOG(
"SELF", Sev::inform) <<
"Save debug part mesh " << ss.str();
1201 CHKERR m_field.
get_moab().write_file(ss.str().c_str(),
"VTK",
"",
1208 CHKERR ISRestoreIndices(is_gather, &part_number);
1209 CHKERR ISRestoreIndices(is_gather_num, &gids);
1210 CHKERR ISDestroy(&is_num);
1211 CHKERR ISDestroy(&is_gather_num);
1212 CHKERR ISDestroy(&is_gather);
1214 CHKERR MatPartitioningDestroy(&part);
1226 CHKERR moab.load_file(file_name, 0, options);
1227 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab,
MYPCOMM_INDEX);
1229 pcomm =
new ParallelComm(&moab, PETSC_COMM_WORLD);
1230 if (pcomm->size() == 1)
1233 Skinner skin(&moab);
1237 auto print_range_on_procs = [&](
const Range &range, std::string name) {
1238 MOFEM_LOG(
"SYNC",
sev) << name <<
" on proc [" << pcomm->rank()
1239 <<
"] : " << range.size();
1243 auto save_range_to_file = [&](
const Range range, std::string name =
"part") {
1246 int rr = pcomm->rank();
1248 ss <<
"out_" << name <<
"_" << rr <<
".vtk";
1249 MOFEM_LOG(
"SYNC",
sev) <<
"Save debug part mesh " << ss.str();
1251 CHKERR moab.create_meshset(MESHSET_SET, meshset);
1252 CHKERR moab.add_entities(meshset, range);
1254 CHKERR moab.write_file(ss.str().c_str(),
"VTK",
"", &meshset, 1);
1256 CHKERR moab.delete_entities(&meshset, 1);
1262 CHKERR skin.find_skin(0, e.subset_by_dimension(dim),
false, s);
1266 auto get_adj = [&](
auto ents,
auto dim) {
1268 CHKERR moab.get_adjacencies(ents, dim,
false, adj, moab::Interface::UNION);
1273 CHKERR moab.get_entities_by_handle(0, all_ents,
false);
1274 save_range_to_file(all_ents,
"all_ents");
1276 Tag part_tag = pcomm->part_tag();
1277 Range tagged_sets, proc_ents, off_proc_ents;
1279 CHKERR moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1280 tagged_sets, moab::Interface::UNION);
1281 print_range_on_procs(tagged_sets,
"tagged_sets");
1282 for (
auto &mit : tagged_sets) {
1284 CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1285 if (part == pcomm->rank()) {
1286 CHKERR moab.get_entities_by_handle(mit, proc_ents,
true);
1288 CHKERR moab.get_entities_by_handle(mit, off_proc_ents,
true);
1293 for (
auto &mit : tagged_sets) {
1295 CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1297 CHKERR moab.get_entities_by_handle(mit, ents,
true);
1298 CHKERR moab.tag_clear_data(part_tag, ents, &part);
1301 print_range_on_procs(proc_ents,
"proc_ents");
1302 save_range_to_file(proc_ents,
"proc_ents");
1304 auto get_proc_ents_skin = [&]() {
1305 std::array<Range, 4>
1307 auto all_skin =
get_skin(all_ents.subset_by_dimension(dim));
1308 auto proc_skin =
get_skin(proc_ents.subset_by_dimension(dim));
1310 proc_ents_skin[2] = subtract(proc_skin, all_skin);
1311 proc_ents_skin[1] = get_adj(proc_ents_skin[dim - 1], 1);
1314 proc_ents_skin[1] = subtract(proc_skin, all_skin);
1316 CHKERR moab.get_connectivity(proc_ents_skin[dim - 1], proc_ents_skin[0],
1318 return proc_ents_skin;
1321 auto add_post_proc_skin = [&](
auto &&proc_ents_skin) {
1324 Tag nsTag, ssTag, nsTag_data, ssTag_data, bhTag, bhTag_header;
1326 bhTag, bhTag_header,
QUIET);
1329 CHKERR moab.get_entities_by_type(0, MBENTITYSET, meshsets,
false);
1330 for (
auto m : meshsets) {
1335 auto p = cubit_meshsets_index.insert(block);
1340 CHKERR moab.get_entities_by_handle(
m, ents,
true);
1341 CHKERR moab.add_entities(p.first->getMeshset(), ents);
1342 CHKERR moab.delete_entities(&
m, 1);
1347 for (
auto &
m : cubit_meshsets_index) {
1352 std::vector<const CubitMeshSets *> vec_ptr;
1353 for (
auto &
m : cubit_meshsets_index) {
1354 vec_ptr.push_back(&
m);
1358 return proc_skin_fun(std::move(proc_ents_skin), std::move(vec_ptr));
1361 auto remove_off_proc_ents = [&](
auto &all_ents,
auto &off_proc_ents,
1362 auto &proc_ents_skin) {
1363 auto to_remove = off_proc_ents;
1364 for (
auto d = dim - 1;
d >= 0; --
d) {
1365 to_remove = subtract(to_remove, proc_ents_skin[
d]);
1369 CHKERR moab.get_entities_by_type(0, MBENTITYSET, meshsets,
true);
1370 for (
auto m : meshsets) {
1371 CHKERR moab.remove_entities(
m, to_remove);
1373 for (
int dd = dim;
dd > 0; --
dd) {
1374 CHKERR moab.delete_entities(to_remove.subset_by_dimension(
dd));
1378 auto proc_ents_skin = add_post_proc_skin(get_proc_ents_skin());
1379 for (
auto d = dim - 1;
d >= 0; --
d) {
1380 save_range_to_file(proc_ents_skin[
d],
"proc_ents_skin" + std::to_string(
d));
1383 if (pcomm->rank()) {
1384 remove_off_proc_ents(all_ents, off_proc_ents, proc_ents_skin);
1387 for (
auto d = dim - 1;
d >= 0; --
d) {
1388 print_range_on_procs(proc_ents_skin[
d],
1389 "proc_ents_skin by dim" + std::to_string(
d));
1392 CHKERR pcomm->resolve_shared_ents(0, proc_ents, dim, -1,
1393 proc_ents_skin.data());
1398 auto gid_tag = moab.globalId_tag();
1402 CHKERR moab.tag_get_handle(
"TestGather", 1, MB_TYPE_INTEGER, tag_handle,
1403 MB_TAG_DENSE | MB_TAG_CREAT, &def_val);
1405 if (pcomm->rank() > 0) {
1406 gather_ents = proc_ents.subset_by_dimension(3);
1407 std::vector<int> vals(gather_ents.size());
1408 std::for_each(vals.begin(), vals.end(), [](
auto &
v) { v = std::rand(); });
1409 CHKERR moab.tag_set_data(tag_handle, gather_ents, vals.data());
1410 CHKERR pcomm->gather_data(gather_ents, tag_handle, gid_tag, 0, 0);
1412 gather_ents = proc_ents.subset_by_dimension(3);
1413 CHKERR pcomm->gather_data(gather_ents, tag_handle, gid_tag, 0, 0);
1417 Range all_ents_after;
1418 CHKERR moab.get_entities_by_handle(0, all_ents_after);
1419 save_range_to_file(all_ents_after.subset_by_dimension(3),
1420 "all_ents_part_after");
1427 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab,
MYPCOMM_INDEX);
1429 pcomm =
new ParallelComm(&moab, PETSC_COMM_WORLD);
1430 if (pcomm->size() == 1) {
1433 "get_entities_by_handle failed");
1434 return subtract(ents, ents.subset_by_type(MBENTITYSET));
1439 auto get_proc_ents = [&]() {
1442 Tag part_tag = pcomm->part_tag();
1445 CHKERR moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1447 moab::Interface::UNION);
1448 for (
auto &mit : tagged_sets) {
1450 CHKERR moab.tag_get_data(part_tag, &mit, 1, &part_set);
1451 if (part_set == part) {
1452 CHKERR moab.get_entities_by_handle(mit, proc_ents,
true);
1457 "Part not found in partitioned mesh");
1468 int dim,
const int nb_coeffs,
Sev sev,
1478 Tag part_tag = pcomm->part_tag();
1479 Range tagged_sets, proc_ents, off_proc_ents;
1480 CHKERR moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1482 moab::Interface::UNION);
1485 for (
auto &mit : tagged_sets) {
1487 CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1488 if (part == pcomm->rank()) {
1489 CHKERR moab.get_entities_by_handle(mit, proc_ents,
true);
1491 CHKERR moab.get_entities_by_handle(mit, off_proc_ents,
true);
1495 std::map<int, Range> parts_ents;
1496 for (
auto &mit : tagged_sets) {
1498 CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1499 CHKERR moab.get_entities_by_handle(mit, parts_ents[part],
true);
1502 CHKERR moab.get_connectivity(parts_ents[pcomm->rank()],
v);
1504 for (; p != pcomm->rank(); ++p) {
1506 CHKERR moab.get_connectivity(parts_ents[p], vv);
1507 v = subtract(
v, vv);
1508 off_proc_ents.merge(vv);
1510 for (; p != pcomm->size(); ++p) {
1512 CHKERR moab.get_connectivity(parts_ents[p], vv);
1513 vv = subtract(vv,
v);
1514 off_proc_ents.merge(vv);
1519 r = proc_ents.subset_by_dimension(dim);
1520 auto o = off_proc_ents.subset_by_dimension(dim);
1522 auto set_ghosts = [&](
Range &ents) {
1523 auto gid_tag = moab.globalId_tag();
1524 std::vector<int> ghosts(ents.size());
1525 CHKERR moab.tag_get_data(gid_tag, ents, ghosts.data());
1526 std::vector<int> ghosts_nb(nb_coeffs * ents.size());
1527 for (
int i = 0;
i < ents.size(); ++
i)
1528 for (
int j = 0;
j < nb_coeffs; ++
j)
1529 ghosts_nb[
i * nb_coeffs +
j] = nb_coeffs * (ghosts[
i] - 1) +
j;
1533 std::vector<int> ghosts;
1534 if (pcomm->rank() == root_rank) {
1535 ghosts = set_ghosts(o);
1539 CHKERR moab.get_entities_by_dimension(0, dim, ents);
1540 ents = subtract(ents,
r);
1541 ghosts = set_ghosts(ents);
1545 auto create_vec = [&]() {
1548 ghosts.size(), ghosts.data());
1558 auto out = std::make_pair(std::make_pair(
r, ghost_ents), vec);
1563 auto check = [&](
auto &ents,
auto &id,
auto &idx) {
1566 for (
int i = 0;
i < ents.size(); ++
i) {
1567 for (
int j = 0;
j < nb_coeffs; ++
j) {
1568 if (idx[
i * nb_coeffs +
j] != nb_coeffs * (
id[
i] - 1) +
j) {
1571 <<
"indexes not equal: " << idx[
i * nb_coeffs +
j]
1572 <<
" != " << nb_coeffs * (idx[
i] - 1) +
j;
1583 CHKERR moab.tag_get_handle(
"TestGather", nb_coeffs, MB_TYPE_DOUBLE, tag,
1584 MB_TAG_SPARSE | MB_TAG_CREAT);
1585 auto gid_tag = moab.globalId_tag();
1586 std::vector<int> id(
r.size());
1587 CHKERR moab.tag_get_data(gid_tag,
r,
id.data());
1588 std::vector<double> idx(nb_coeffs *
r.size());
1589 for (
int i = 0;
i <
r.size(); ++
i) {
1590 for (
int j = 0;
j < nb_coeffs; ++
j) {
1591 idx[
i * nb_coeffs +
j] = nb_coeffs * (
id[
i] - 1) +
j;
1594 CHKERR moab.tag_set_data(tag,
r, idx.data());
1596 idx.resize(nb_coeffs *
r.size());
1597 CHKERR moab.tag_get_data(tag,
r, idx.data());
1599 id.resize(ghost_ents.size());
1600 CHKERR moab.tag_get_data(gid_tag, ghost_ents,
id.data());
1601 idx.resize(nb_coeffs * ghost_ents.size());
1602 CHKERR moab.tag_get_data(tag, ghost_ents, idx.data());
1604 CHKERR moab.tag_delete(tag);
1618 CHKERR VecGetLocalSize(vec.second, &local_size);
1620 CHKERR moab.tag_get_length(tag, nb_coeffs);
1621 if (vec.first.first.size() * nb_coeffs != local_size) {
1623 "Local size of vector does not match number of entities");
1626 auto set_vec_from_tags = [&]() {
1630 CHKERR VecGetArray(vec.second, &v_array);
1631 CHKERR moab.tag_get_data(tag, vec.first.first, v_array);
1632 CHKERR moab.tag_get_data(tag, vec.first.second, &v_array[local_size]);
1633 CHKERR VecRestoreArray(vec.second, &v_array);
1637 auto set_tags_from_vec = [&]() {
1640 CHKERR VecGetArray(vec.second, &v_array);
1641 CHKERR moab.tag_set_data(tag, vec.first.first, v_array);
1642 CHKERR moab.tag_set_data(tag, vec.first.second, &v_array[local_size]);
1643 CHKERR VecRestoreArray(vec.second, &v_array);
1647 CHKERR set_vec_from_tags();
1648 CHKERR update_gosts(vec.second);
1649 CHKERR set_tags_from_vec();