v0.16.0
Loading...
Searching...
No Matches
CommInterface.cpp
Go to the documentation of this file.
1/** \file CommInterface.cpp
2 * \brief Functions for interprocess communications
3 * \mofem_comm
4 */
5
6namespace MoFEM {
7
9CommInterface::query_interface(boost::typeindex::type_index type_index,
10 UnknownInterface **iface) const {
12 *iface = const_cast<CommInterface *>(this);
14}
15
17 : cOre(const_cast<MoFEM::Core &>(core)), dEbug(false) {}
18
20 Range &ents, std::map<int, Range> *received_ents, int verb) {
21 MoFEM::Interface &m_field = cOre;
22 ParallelComm *pcomm = ParallelComm::get_pcomm(
23 &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
25
26 auto get_pstatus = [&](const auto ent) {
27 unsigned char pstatus;
28 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->pstatus_tag(), &ent,
29 1, &pstatus),
30 "can not get pstatus");
31 return pstatus;
32 };
33
34 auto get_sharing_procs = [&](const auto ent, const auto pstatus) {
35 std::vector<int> sharing_procs(MAX_SHARING_PROCS, -1);
36 if (pstatus & PSTATUS_MULTISHARED) {
37 // entity is multi shared
38 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(
39 pcomm->sharedps_tag(), &ent, 1, &sharing_procs[0]),
40 "can not ger sharing_procs_ptr");
41 } else if (pstatus & PSTATUS_SHARED) {
42 // shared
43 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->sharedp_tag(), &ent,
44 1, &sharing_procs[0]),
45 "can not get sharing proc");
46 }
47 return sharing_procs;
48 };
49
50 auto get_sharing_handles = [&](const auto ent, const auto pstatus) {
51 std::vector<EntityHandle> sharing_handles(MAX_SHARING_PROCS, 0);
52 if (pstatus & PSTATUS_MULTISHARED) {
53 // entity is multi shared
54 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(
55 pcomm->sharedhs_tag(), &ent, 1, &sharing_handles[0]),
56 "get shared handles");
57 } else if (pstatus & PSTATUS_SHARED) {
58 // shared
59 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->sharedh_tag(), &ent,
60 1, &sharing_handles[0]),
61 "get sharing handle");
62 }
63 return sharing_handles;
64 };
65
66 // make a buffer entities to send
67 std::vector<std::vector<EntityHandle>> sbuffer(m_field.get_comm_size());
68
69 for (auto ent : ents) {
70
71 auto pstatus = get_pstatus(ent);
72 if (pstatus) {
73 auto sharing_procs = get_sharing_procs(ent, pstatus);
74 auto sharing_handles = get_sharing_handles(ent, pstatus);
75
76 if (verb >= NOISY) {
77 MOFEM_LOG("SYNC", Sev::noisy) << "pstatus " << std::bitset<8>(pstatus);
78 }
79
80 for (int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
81 proc++) {
82 if (sharing_procs[proc] == -1)
83 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
84 "sharing processor not set");
85
86 if (sharing_procs[proc] == m_field.get_comm_rank())
87 continue;
88
89 const auto handle_on_sharing_proc = sharing_handles[proc];
90 // add entity to send, handle on the other side
91 sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
92 if (verb >= NOISY) {
93 MOFEM_LOG_C("SYNC", Sev::noisy, "send %lu (%lu) to %d at %d\n", ent,
94 handle_on_sharing_proc, sharing_procs[proc],
95 m_field.get_comm_rank());
96 }
97
98 if (!(pstatus & PSTATUS_MULTISHARED))
99 break;
100 }
101 }
102 }
103 if (verb >= NOISY) {
104 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
105 }
106
107 int nsends = 0; // number of messages to send
108 std::vector<int> sbuffer_lengths(
109 m_field.get_comm_size()); // length of the message to proc
110 const size_t block_size =
111 sizeof(EntityHandle) /
112 sizeof(int); // FIXME check if that works on given architecture!
113 for (int proc = 0; proc < m_field.get_comm_size(); proc++) {
114
115 if (!sbuffer[proc].empty()) {
116
117 sbuffer_lengths[proc] = sbuffer[proc].size() * block_size;
118 nsends++;
119
120 } else {
121
122 sbuffer_lengths[proc] = 0;
123 }
124 }
125
126 // Make sure it is a PETSc m_field.get_comm()
127 MPI_Comm comm;
128 CHKERR PetscCommDuplicate(m_field.get_comm(), &comm, NULL);
129
130 std::vector<MPI_Status> status(m_field.get_comm_size());
131
132 // Computes the number of messages a node expects to receive
133 int nrecvs; // number of messages received
134 CHKERR PetscGatherNumberOfMessages(comm, NULL, &sbuffer_lengths[0], &nrecvs);
135
136 // Computes info about messages that a MPI-node will receive, including
137 // (from-id,length) pairs for each message.
138 int *onodes; // list of node-ids from which messages are expected
139 int *olengths; // corresponding message lengths
140 CHKERR PetscGatherMessageLengths(comm, nsends, nrecvs, &sbuffer_lengths[0],
141 &onodes, &olengths);
142
143 // Gets a unique new tag from a PETSc communicator. All processors that share
144 // the communicator MUST call this routine EXACTLY the same number of times.
145 // This tag should only be used with the current objects communicator; do NOT
146 // use it with any other MPI communicator.
147 int tag;
148 CHKERR PetscCommGetNewTag(comm, &tag);
149
150 // Allocate a buffer sufficient to hold messages of size specified in
151 // olengths. And post Irecvs on these buffers using node info from onodes
152 int **rbuf; // must bee freed by user
153 MPI_Request *r_waits; // must bee freed by user
154 // rbuf has a pointers to messages. It has size of of nrecvs (number of
155 // messages) +1. In the first index a block is allocated,
156 // such that rbuf[i] = rbuf[i-1]+olengths[i-1].
157 CHKERR PetscPostIrecvInt(comm, tag, nrecvs, onodes, olengths, &rbuf,
158 &r_waits);
159
160 MPI_Request *s_waits; // status of sens messages
161 CHKERR PetscMalloc1(nsends, &s_waits);
162
163 // Send messages
164 for (int proc = 0, kk = 0; proc < m_field.get_comm_size(); proc++) {
165 if (!sbuffer_lengths[proc])
166 continue; // no message to send to this proc
167 CHKERR MPI_Isend(&(sbuffer[proc])[0], // buffer to send
168 sbuffer_lengths[proc], // message length
169 MPIU_INT, proc, // to proc
170 tag, comm, s_waits + kk);
171 kk++;
172 }
173
174 // Wait for received
175 if (nrecvs)
176 CHKERR MPI_Waitall(nrecvs, r_waits, &status[0]);
177
178 // Wait for send messages
179 if (nsends)
180 CHKERR MPI_Waitall(nsends, s_waits, &status[0]);
181
182 if (verb >= VERBOSE) {
183 MOFEM_LOG_C("SYNC", Sev::verbose, "Rank %d nb. before ents %zu\n",
184 m_field.get_comm_rank(), ents.size());
185 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
186 }
187
188 // synchronise range
189 for (int kk = 0; kk < nrecvs; kk++) {
190
191 int len = olengths[kk];
192 int *data_from_proc = rbuf[kk];
193
194 for (int ee = 0; ee < len;) {
195 EntityHandle ent;
196 bcopy(&data_from_proc[ee], &ent, sizeof(EntityHandle));
197 ents.insert(ent);
198
199 if (received_ents) {
200 (*received_ents)[onodes[kk]].insert(ent);
201 }
202
203 ee += block_size;
204
205 if (verb >= VERBOSE) {
206 MOFEM_LOG_C("SYNC", Sev::noisy, "received %lu from %d at %d\n", ent,
207 onodes[kk], m_field.get_comm_rank());
208 }
209 }
210 }
211 if (verb >= VERBOSE) {
212 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
213 }
214
215 if (verb >= VERBOSE) {
216 MOFEM_LOG_C("SYNC", Sev::verbose, "Rank %d nb. after ents %zu",
217 m_field.get_comm_rank(), ents.size());
218 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
219 }
220
221 // Cleaning
222 CHKERR PetscFree(s_waits);
223 CHKERR PetscFree(rbuf[0]);
224 CHKERR PetscFree(rbuf);
225 CHKERR PetscFree(r_waits);
226 CHKERR PetscFree(onodes);
227 CHKERR PetscFree(olengths);
228 CHKERR PetscCommDestroy(&comm);
229
231}
232
234 return synchroniseEntities(ents, nullptr, verb);
235}
236
238 int verb) {
239 MoFEM::Interface &m_field = cOre;
241 EntityHandle idm = m_field.get_field_meshset(name);
242 Range ents;
243 CHKERR m_field.get_moab().get_entities_by_handle(idm, ents, false);
244 CHKERR synchroniseEntities(ents, nullptr, verb);
245 CHKERR m_field.get_moab().add_entities(idm, ents);
247}
248
250 int verb) {
251 MoFEM::Interface &m_field = cOre;
252 ParallelComm *pcomm = ParallelComm::get_pcomm(
253 &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
254
256
257 Range shared = ents;
258 CHKERR pcomm->filter_pstatus(shared, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
259 nullptr);
260 CHKERR pcomm->filter_pstatus(shared, PSTATUS_SHARED | PSTATUS_MULTISHARED,
261 PSTATUS_OR, -1, nullptr);
262
263 auto th_RefParentHandle = cOre.get_th_RefParentHandle();
264 auto th_RefBitLevel = cOre.get_th_RefBitLevel();
265
266 auto get_pstatus = [&](const auto ent) {
267 unsigned char pstatus;
268 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->pstatus_tag(), &ent,
269 1, &pstatus),
270 "can not get pstatus");
271 return pstatus;
272 };
273
274 auto get_sharing_procs = [&](const auto ent, const auto pstatus) {
275 std::vector<int> sharing_procs(MAX_SHARING_PROCS, -1);
276 if (pstatus & PSTATUS_MULTISHARED) {
277 // entity is multi shared
278 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(
279 pcomm->sharedps_tag(), &ent, 1, &sharing_procs[0]),
280 "can not ger sharing_procs_ptr");
281 } else if (pstatus & PSTATUS_SHARED) {
282 // shared
283 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->sharedp_tag(), &ent,
284 1, &sharing_procs[0]),
285 "can not get sharing proc");
286 }
287 return sharing_procs;
288 };
289
290 auto get_sharing_handles = [&](const auto ent, const auto pstatus) {
291 std::vector<EntityHandle> sharing_handles(MAX_SHARING_PROCS, 0);
292 if (pstatus & PSTATUS_MULTISHARED) {
293 // entity is multi shared
294 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(
295 pcomm->sharedhs_tag(), &ent, 1, &sharing_handles[0]),
296 "get shared handles");
297 } else if (pstatus & PSTATUS_SHARED) {
298 // shared
299 CHK_MOAB_THROW(m_field.get_moab().tag_get_data(pcomm->sharedh_tag(), &ent,
300 1, &sharing_handles[0]),
301 "get sharing handle");
302 }
303 return sharing_handles;
304 };
305
306 auto get_parent_and_bit = [&](const auto ent) {
307 EntityHandle parent;
309 m_field.get_moab().tag_get_data(th_RefParentHandle, &ent, 1, &parent),
310 "get parent");
313 m_field.get_moab().tag_get_data(th_RefBitLevel, &ent, 1, &bit),
314 "get parent");
315 return std::make_pair(parent, bit);
316 };
317
318 auto set_parent = [&](const auto ent, const auto parent) {
319 return m_field.get_moab().tag_set_data(th_RefParentHandle, &ent, 1,
320 &parent);
321 };
322
323 auto set_bit = [&](const auto ent, const auto bit) {
324 return m_field.get_moab().tag_set_data(th_RefBitLevel, &ent, 1, &bit);
325 };
326
327 // make a buffer
328 std::vector<std::vector<unsigned long long>> sbuffer(m_field.get_comm_size());
329
330 for (auto ent : shared) {
331
332 auto pstatus = get_pstatus(ent);
333 auto sharing_procs = get_sharing_procs(ent, pstatus);
334 auto sharing_handles = get_sharing_handles(ent, pstatus);
335 auto [parent, bit] = get_parent_and_bit(ent);
336
337 if (verb >= NOISY)
338 MOFEM_LOG("SYNC", Sev::noisy) << "pstatus " << std::bitset<8>(pstatus);
339
340 if (parent) {
341 auto pstatus_parent = get_pstatus(parent);
342 auto sharing_procs_parent = get_sharing_procs(parent, pstatus_parent);
343 auto sharing_handles_parent = get_sharing_handles(parent, pstatus_parent);
344
345 for (int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
346 proc++) {
347 if (sharing_procs[proc] == -1)
348 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
349 "sharing processor not set");
350
351 if (sharing_procs[proc] != m_field.get_comm_rank()) {
352
353 auto it = std::find(sharing_procs_parent.begin(),
354 sharing_procs_parent.end(), sharing_procs[proc]);
355 if (it == sharing_procs_parent.end()) {
356 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
357 "Sharing proc for parent entity can not be found proc = %u",
358 sharing_procs[proc]);
359 }
360
361 auto handle_on_sharing_proc = sharing_handles[proc];
362 auto parent_handle_on_sharing_proc =
363 sharing_handles_parent[std::distance(sharing_procs_parent.begin(),
364 it)];
365 sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
366 sbuffer[sharing_procs[proc]].push_back(parent_handle_on_sharing_proc);
367 try {
368 sbuffer[sharing_procs[proc]].push_back(bit.to_ullong());
369 } catch (std::exception &ex) {
370 MOFEM_LOG("SELF", Sev::warning) << ex.what();
371 MOFEM_LOG("SELF", Sev::warning)
372 << "On " << ent << " "
373 << moab::CN::EntityTypeName(type_from_handle(ent));
374 MOFEM_LOG("SELF", Sev::warning) << "For bit ref " << bit;
375 }
376 if (verb >= NOISY)
377 MOFEM_LOG_C("SYNC", Sev::noisy, "send %lu (%lu) to %d at %d\n", ent,
378 handle_on_sharing_proc, sharing_procs[proc],
379 m_field.get_comm_rank());
380
381 if (!(pstatus & PSTATUS_MULTISHARED))
382 break;
383 }
384 }
385 } else {
386 for (int proc = 0; proc < MAX_SHARING_PROCS && -1 != sharing_procs[proc];
387 proc++) {
388 if (sharing_procs[proc] == -1)
389 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
390 "sharing processor not set");
391
392 if (sharing_procs[proc] != m_field.get_comm_rank()) {
393 auto handle_on_sharing_proc = sharing_handles[proc];
394 sbuffer[sharing_procs[proc]].push_back(handle_on_sharing_proc);
395 sbuffer[sharing_procs[proc]].push_back(parent);
396
397 try {
398 sbuffer[sharing_procs[proc]].push_back(bit.to_ullong());
399 } catch (std::exception &ex) {
400 MOFEM_LOG("SELF", Sev::warning) << ex.what();
401 MOFEM_LOG("SELF", Sev::warning)
402 << "On " << ent << " "
403 << moab::CN::EntityTypeName(type_from_handle(ent));
404 MOFEM_LOG("SELF", Sev::warning) << "For bit ref " << bit;
405 }
406
407 if (verb >= NOISY)
408 MOFEM_LOG_C("SYNC", Sev::noisy, "send %lu (%lu) to %d at %d\n", ent,
409 handle_on_sharing_proc, sharing_procs[proc],
410 m_field.get_comm_rank());
411
412 if (!(pstatus & PSTATUS_MULTISHARED))
413 break;
414 }
415 }
416 }
417 }
418
419 int nsends = 0; // number of messages to send
420 std::vector<int> sbuffer_lengths(
421 m_field.get_comm_size()); // length of the message to proc
422
423 const size_t block_size = sizeof(unsigned long long) / sizeof(int);
424 for (int proc = 0; proc < m_field.get_comm_size(); proc++) {
425
426 if (!sbuffer[proc].empty()) {
427
428 sbuffer_lengths[proc] = sbuffer[proc].size() * block_size;
429 nsends++;
430
431 } else {
432
433 sbuffer_lengths[proc] = 0;
434 }
435 }
436
437 // Make sure it is a PETSc m_field.get_comm()
438 MPI_Comm comm;
439 CHKERR PetscCommDuplicate(m_field.get_comm(), &comm, NULL);
440
441 std::vector<MPI_Status> status(m_field.get_comm_size());
442
443 // Computes the number of messages a node expects to receive
444 int nrecvs; // number of messages received
445 CHKERR PetscGatherNumberOfMessages(comm, NULL, &sbuffer_lengths[0], &nrecvs);
446
447 // Computes info about messages that a MPI-node will receive, including
448 // (from-id,length) pairs for each message.
449 int *onodes; // list of node-ids from which messages are expected
450 int *olengths; // corresponding message lengths
451 CHKERR PetscGatherMessageLengths(comm, nsends, nrecvs, &sbuffer_lengths[0],
452 &onodes, &olengths);
453
454 // Gets a unique new tag from a PETSc communicator. All processors that share
455 // the communicator MUST call this routine EXACTLY the same number of times.
456 // This tag should only be used with the current objects communicator; do NOT
457 // use it with any other MPI communicator.
458 int tag;
459 CHKERR PetscCommGetNewTag(comm, &tag);
460
461 // Allocate a buffer sufficient to hold messages of size specified in
462 // olengths. And post Irecvs on these buffers using node info from onodes
463 int **rbuf; // must bee freed by user
464 MPI_Request *r_waits; // must bee freed by user
465 // rbuf has a pointers to messages. It has size of of nrecvs (number of
466 // messages) +1. In the first index a block is allocated,
467 // such that rbuf[i] = rbuf[i-1]+olengths[i-1].
468 CHKERR PetscPostIrecvInt(comm, tag, nrecvs, onodes, olengths, &rbuf,
469 &r_waits);
470
471 MPI_Request *s_waits; // status of sens messages
472 CHKERR PetscMalloc1(nsends, &s_waits);
473
474 // Send messages
475 for (int proc = 0, kk = 0; proc < m_field.get_comm_size(); proc++) {
476 if (!sbuffer_lengths[proc])
477 continue; // no message to send to this proc
478 CHKERR MPI_Isend(&(sbuffer[proc])[0], // buffer to send
479 sbuffer_lengths[proc], // message length
480 MPIU_INT, proc, // to proc
481 tag, comm, s_waits + kk);
482 kk++;
483 }
484
485 // Wait for received
486 if (nrecvs)
487 CHKERR MPI_Waitall(nrecvs, r_waits, &status[0]);
488
489 // Wait for send messages
490 if (nsends)
491 CHKERR MPI_Waitall(nsends, s_waits, &status[0]);
492
493 if (verb >= VERBOSE) {
494 MOFEM_LOG_C("SYNC", Sev::verbose,
495 "Rank %d nb. shared to synchronise parents ents %zu\n",
496 m_field.get_comm_rank(), shared.size());
497 }
498
499 // synchronise range
500 for (int kk = 0; kk < nrecvs; kk++) {
501
502 int len = olengths[kk];
503 int *data_from_proc = rbuf[kk];
504
505 for (int ee = 0; ee < len;) {
506 EntityHandle ent;
507 EntityHandle parent;
508 unsigned long long uulong_bit;
509 bcopy(&data_from_proc[ee], &ent, sizeof(EntityHandle));
510 ee += block_size;
511 bcopy(&data_from_proc[ee], &parent, sizeof(EntityHandle));
512 ee += block_size;
513 bcopy(&data_from_proc[ee], &uulong_bit, sizeof(unsigned long long));
514 ee += block_size;
515
516 CHKERR set_parent(ent, parent);
517 CHKERR set_bit(ent, BitRefLevel(uulong_bit));
518
519 if (verb >= VERBOSE) {
520 MOFEM_LOG_C("SYNC", Sev::noisy, "received %lu (%lu) from %d at %d\n",
521 ent, parent, onodes[kk], m_field.get_comm_rank());
522 MOFEM_LOG("SYNC", Sev::noisy) << "Bit " << BitRefLevel(uulong_bit);
523 }
524 }
525 }
526
527 // Cleaning
528 CHKERR PetscFree(s_waits);
529 CHKERR PetscFree(rbuf[0]);
530 CHKERR PetscFree(rbuf);
531 CHKERR PetscFree(r_waits);
532 CHKERR PetscFree(onodes);
533 CHKERR PetscFree(olengths);
534 CHKERR PetscCommDestroy(&comm);
535
536 if (verb >= VERBOSE)
538
540}
541
543 const Problem *problem_ptr, const std::string &fe_name, int verb) {
544 MoFEM::Interface &m_field = cOre;
546 ParallelComm *pcomm = ParallelComm::get_pcomm(
547 &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
548 std::vector<int> shprocs(MAX_SHARING_PROCS, 0);
549 std::vector<EntityHandle> shhandles(MAX_SHARING_PROCS, 0);
550 Range ents;
551 Tag th_gid = m_field.get_moab().globalId_tag();
552 PetscLayout layout;
553 CHKERR problem_ptr->getNumberOfElementsByNameAndPart(m_field.get_comm(),
554 fe_name, &layout);
555 int gid, last_gid;
556 CHKERR PetscLayoutGetRange(layout, &gid, &last_gid);
557 CHKERR PetscLayoutDestroy(&layout);
558
559 const FiniteElement_multiIndex *fes_ptr;
560 CHKERR m_field.get_finite_elements(&fes_ptr);
561
562 auto fe_miit = fes_ptr->get<FiniteElement_name_mi_tag>().find(fe_name);
563 if (fe_miit != fes_ptr->get<FiniteElement_name_mi_tag>().end()) {
564 auto fit =
565 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>().lower_bound(
567 0, (*fe_miit)->getFEUId()));
568 auto hi_fe_it =
569 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>().upper_bound(
571 get_id_for_max_type<MBENTITYSET>(), (*fe_miit)->getFEUId()));
572 for (; fit != hi_fe_it; ++fit) {
573
574 auto ent = (*fit)->getEnt();
575 auto part = (*fit)->getPart();
576
577 ents.insert(ent);
578 CHKERR m_field.get_moab().tag_set_data(pcomm->part_tag(), &ent, 1, &part);
579 if (part == pcomm->rank()) {
580 CHKERR m_field.get_moab().tag_set_data(th_gid, &ent, 1, &gid);
581 gid++;
582 }
583 shprocs.clear();
584 shhandles.clear();
585
586 if (pcomm->size() > 1) {
587
588 unsigned char pstatus = 0;
589 if (pcomm->rank() != part) {
590 pstatus = PSTATUS_NOT_OWNED;
591 pstatus |= PSTATUS_GHOST;
592 }
593
594 if (pcomm->size() > 2) {
595 pstatus |= PSTATUS_SHARED;
596 pstatus |= PSTATUS_MULTISHARED;
597 } else {
598 pstatus |= PSTATUS_SHARED;
599 }
600
601 size_t rrr = 0;
602 for (size_t rr = 0; rr < pcomm->size(); ++rr) {
603 if (rr != pcomm->rank()) {
604 shhandles[rrr] = ent;
605 shprocs[rrr] = rr;
606 ++rrr;
607 }
608 }
609 for (; rrr != pcomm->size(); ++rrr)
610 shprocs[rrr] = -1;
611
612 if (pstatus & PSTATUS_SHARED) {
613 CHKERR m_field.get_moab().tag_set_data(pcomm->sharedp_tag(), &ent, 1,
614 &shprocs[0]);
615 CHKERR m_field.get_moab().tag_set_data(pcomm->sharedh_tag(), &ent, 1,
616 &shhandles[0]);
617 }
618
619 if (pstatus & PSTATUS_MULTISHARED) {
620 CHKERR m_field.get_moab().tag_set_data(pcomm->sharedps_tag(), &ent, 1,
621 &shprocs[0]);
622 CHKERR m_field.get_moab().tag_set_data(pcomm->sharedhs_tag(), &ent, 1,
623 &shhandles[0]);
624 }
625 CHKERR m_field.get_moab().tag_set_data(pcomm->pstatus_tag(), &ent, 1,
626 &pstatus);
627 }
628 }
629 }
630
631 CHKERR pcomm->exchange_tags(th_gid, ents);
633}
634
636 const std::string name, const std::string &fe_name, int verb) {
637 MoFEM::Interface &m_field = cOre;
639 const Problem *problem_ptr;
640 CHKERR m_field.get_problem(name, &problem_ptr);
641 CHKERR resolveSharedFiniteElements(problem_ptr, fe_name, verb);
643}
644
647 const int num_entities,
648 const int owner_proc, int verb) {
649 MoFEM::Interface &m_field = cOre;
651
652 if (m_field.get_comm_size() > 1) {
653
654 ParallelComm *pcomm = ParallelComm::get_pcomm(
655 &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
656
657 Range all_ents_range;
658 all_ents_range.insert_list(entities, entities + num_entities);
659
660 auto get_tag = [&]() {
661 const int negone = -1;
662 Tag th;
663 m_field.get_moab().tag_get_handle("TMP_GLOBAL_ID_TAG_NAME", 1,
664 MB_TYPE_INTEGER, th,
665 MB_TAG_CREAT | MB_TAG_SPARSE, &negone);
666 return th;
667 };
668
669 auto delete_tag = [&](auto &&th_gid) {
671 CHKERR m_field.get_moab().tag_delete(th_gid);
673 };
674
675 auto resolve_shared_ents = [&](auto &&th_gid, auto &all_ents_range) {
676 auto set_gid = [&](auto &th_gid) {
677 std::vector<int> gids(num_entities);
678 for (size_t g = 0; g != all_ents_range.size(); ++g)
679 gids[g] = g + 1;
680 CHKERR m_field.get_moab().tag_set_data(th_gid, all_ents_range,
681 &*gids.begin());
682
683 return &th_gid;
684 };
685
686 auto get_skin_ents = [&](auto &all_ents_range) {
687 std::array<Range, 4> proc_ents_skin;
688 proc_ents_skin[3] = all_ents_range.subset_by_dimension(3);
689 proc_ents_skin[2] = all_ents_range.subset_by_dimension(2);
690 proc_ents_skin[1] = all_ents_range.subset_by_dimension(1);
691 proc_ents_skin[0] = all_ents_range.subset_by_dimension(0);
692 return proc_ents_skin;
693 };
694
695 auto resolve_dim = [&](auto &all_ents_range) {
696 for (int resolve_dim = 3; resolve_dim >= 0; --resolve_dim) {
697 if (all_ents_range.num_of_dimension(resolve_dim))
698 return resolve_dim;
699 }
700 return -1;
701 };
702
703 auto get_proc_ent = [&](auto &all_ents_range) {
704 Range proc_ent;
705 if (m_field.get_comm_rank() == owner_proc)
706 proc_ent = all_ents_range;
707 return proc_ent;
708 };
709
710 auto resolve_shared_ents = [&](auto &&proc_ents, auto &&skin_ents) {
711 return pcomm->resolve_shared_ents(
712 0, proc_ents, resolve_dim(all_ents_range),
713 resolve_dim(all_ents_range), skin_ents.data(), set_gid(th_gid));
714 };
715
716 CHKERR resolve_shared_ents(get_proc_ent(all_ents_range),
717 get_skin_ents(all_ents_range));
718
719 return th_gid;
720 };
721
722 CHKERR delete_tag(resolve_shared_ents(get_tag(), all_ents_range));
723
724 if (verb >= NOISY) {
725
726 auto print_owner = [&](const EntityHandle e) {
728 int moab_owner_proc;
729 EntityHandle moab_owner_handle;
730 CHKERR pcomm->get_owner_handle(e, moab_owner_proc, moab_owner_handle);
731
732 unsigned char pstatus = 0;
733
734 CHKERR m_field.get_moab().tag_get_data(pcomm->pstatus_tag(), &e, 1,
735 &pstatus);
736
737 std::vector<int> shprocs(MAX_SHARING_PROCS, 0);
738 std::vector<EntityHandle> shhandles(MAX_SHARING_PROCS, 0);
739
740 CHKERR m_field.get_moab().tag_get_data(pcomm->sharedp_tag(), &e, 1,
741 &shprocs[0]);
742 CHKERR m_field.get_moab().tag_get_data(pcomm->sharedh_tag(), &e, 1,
743 &shhandles[0]);
744 if (pstatus & PSTATUS_MULTISHARED) {
745 CHKERR m_field.get_moab().tag_get_data(pcomm->sharedps_tag(), &e, 1,
746 &shprocs[0]);
747 CHKERR m_field.get_moab().tag_get_data(pcomm->sharedhs_tag(), &e, 1,
748 &shhandles[0]);
749 }
750
751 std::ostringstream ss;
752
753 ss << "Rank " << m_field.get_comm_rank() << " ";
754 if (!(pstatus & PSTATUS_NOT_OWNED))
755 ss << "OWNER ";
756 if (pstatus & PSTATUS_SHARED)
757 ss << "PSTATUS_SHARED ";
758 if (pstatus & PSTATUS_MULTISHARED)
759 ss << "PSTATUS_MULTISHARED ";
760
761 ss << "owner " << moab_owner_proc << " (" << owner_proc << ") ";
762
763 ss << "shprocs: ";
764 for (size_t r = 0; r != m_field.get_comm_size() + 1; ++r)
765 ss << shprocs[r] << " ";
766
767 ss << "shhandles: ";
768 for (size_t r = 0; r != m_field.get_comm_size() + 1; ++r)
769 ss << shhandles[r] << " ";
770
771 ss << std::endl;
772 MOFEM_LOG("SYNC", Sev::noisy) << ss.str();
774
776 };
777
778 for (auto e : all_ents_range)
779 CHKERR print_owner(e);
780 }
781 }
782
784}
785
787 const int owner_proc,
788 int verb) {
789 MoFEM::Interface &m_field = cOre;
791 if (m_field.get_comm_size() > 1) {
792 const int num_ents = entities.size();
793 std::vector<EntityHandle> vec_ents(num_ents);
794 std::copy(entities.begin(), entities.end(), vec_ents.begin());
795 CHKERR makeEntitiesMultishared(&*vec_ents.begin(), num_ents, owner_proc,
796 verb);
797 }
799}
800
803 const int owner_proc, int verb) {
804 MoFEM::Interface &m_field = cOre;
806 if (m_field.get_comm_size() > 1) {
807 EntityHandle field_meshset = m_field.get_field_meshset(field_name);
808 std::vector<EntityHandle> field_ents;
809 CHKERR m_field.get_moab().get_entities_by_handle(field_meshset, field_ents,
810 true);
811 CHKERR makeEntitiesMultishared(&*field_ents.begin(), field_ents.size(),
812 owner_proc, verb);
813 }
815}
816
818 int verb) {
819 MoFEM::Interface &m_field = cOre;
821 if (m_field.get_comm_size() > 1) {
822
823 Range exchange_ents_data_verts, exchange_ents_data;
824
825 auto *field_ents = m_field.get_field_ents();
826 auto field_bit_number = m_field.get_field_bit_number(field_name);
827 auto lo = field_ents->get<Unique_mi_tag>().lower_bound(
828 FieldEntity::getLoBitNumberUId(field_bit_number));
829 auto hi = field_ents->get<Unique_mi_tag>().lower_bound(
830 FieldEntity::getHiBitNumberUId(field_bit_number));
831
832 for (auto it = lo; it != hi; ++it)
833 if (
834
835 ((*it)->getPStatus()) &&
836
837 (*it)->getNbDofsOnEnt()
838
839 ) {
840 if ((*it)->getEntType() == MBVERTEX)
841 exchange_ents_data_verts.insert((*it)->getEnt());
842 else
843 exchange_ents_data.insert((*it)->getEnt());
844 }
845
846 auto field_ptr = m_field.get_field_structure(field_name);
847 ParallelComm *pcomm = ParallelComm::get_pcomm(
848 &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
849
850 auto exchange = [&](const Range &ents, Tag th) {
852 if (!ents.empty()) {
853 std::vector<Tag> tags;
854 tags.push_back(th);
855 CHKERR pcomm->exchange_tags(tags, tags, ents);
856 }
858 };
859
860 CHKERR exchange(exchange_ents_data_verts, field_ptr->th_FieldDataVerts);
861 CHKERR exchange(exchange_ents_data, field_ptr->th_FieldData);
862 }
864}
865
867CommInterface::partitionMesh(const Range &ents, const int dim,
868 const int adj_dim, const int n_parts,
869 Tag *th_vertex_weights, Tag *th_edge_weights,
870 Tag *th_part_weights, int verb, const bool debug) {
871 MoFEM::Interface &m_field = cOre;
873
874 // get layout
875 int rstart, rend, nb_elems;
876 {
877 PetscLayout layout;
878 CHKERR PetscLayoutCreate(m_field.get_comm(), &layout);
879 CHKERR PetscLayoutSetBlockSize(layout, 1);
880 CHKERR PetscLayoutSetSize(layout, ents.size());
881 CHKERR PetscLayoutSetUp(layout);
882 CHKERR PetscLayoutGetSize(layout, &nb_elems);
883 CHKERR PetscLayoutGetRange(layout, &rstart, &rend);
884 CHKERR PetscLayoutDestroy(&layout);
885 if (verb >= VERBOSE) {
886 MOFEM_LOG("SYNC", Sev::inform)
887 << "Finite elements in problem: row lower " << rstart << " row upper "
888 << rend << " nb. elems " << nb_elems << " ( " << ents.size() << " )";
890 }
891 }
892
893 std::vector<EntityHandle> weight_ents;
894 weight_ents.reserve(rend - rstart + 1);
895
896 struct AdjBridge {
897 EntityHandle ent;
898 std::vector<int> adj;
899 AdjBridge(const EntityHandle ent, std::vector<int> &adj)
900 : ent(ent), adj(adj) {}
901 };
902
903 typedef multi_index_container<
904 AdjBridge,
905 indexed_by<
906
907 hashed_unique<member<AdjBridge, EntityHandle, &AdjBridge::ent>>
908
909 >>
910 AdjBridgeMap;
911
912 auto get_it = [&](auto i) {
913 auto it = ents.begin();
914 for (; i > 0; --i) {
915 if (it == ents.end())
916 break;
917 ++it;
918 }
919 return it;
920 };
921
922 Range proc_ents;
923 proc_ents.insert(get_it(rstart), get_it(rend));
924 if (proc_ents.size() != rend - rstart)
925 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
926 "Wrong number of elements in range %zu != %zu", proc_ents.size(),
927 static_cast<size_t>(rend - rstart));
928
929 Range all_dim_ents;
930 CHKERR m_field.get_moab().get_adjacencies(
931 proc_ents, adj_dim, true, all_dim_ents, moab::Interface::UNION);
932
933 AdjBridgeMap adj_bridge_map;
934 auto hint = adj_bridge_map.begin();
935 std::vector<int> adj;
936 for (auto ent : all_dim_ents) {
937 Range adj_ents;
938 CHKERR m_field.get_moab().get_adjacencies(&ent, 1, dim, false, adj_ents);
939 adj_ents = intersect(adj_ents, ents);
940 adj.clear();
941 adj.reserve(adj_ents.size());
942 for (auto a : adj_ents)
943 adj.emplace_back(ents.index(a));
944 hint = adj_bridge_map.emplace_hint(hint, ent, adj);
945 }
946
947 int *_i;
948 int *_j;
949 {
950 const int nb_loc_elements = rend - rstart;
951 std::vector<int> i(nb_loc_elements + 1, 0), j;
952 {
953 std::vector<int> row_adj;
954 Range::iterator fe_it;
955 int ii, jj;
956 size_t max_row_size;
957 for (fe_it = proc_ents.begin(), ii = rstart, jj = 0, max_row_size = 0;
958 fe_it != proc_ents.end(); ++fe_it, ++ii) {
959
960 if (type_from_handle(*fe_it) == MBENTITYSET) {
961 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
962 "not yet implemented, don't know what to do for meshset "
963 "element");
964 } else {
965
966 Range dim_ents;
967 CHKERR m_field.get_moab().get_adjacencies(&*fe_it, 1, adj_dim, false,
968 dim_ents);
969 dim_ents = intersect(dim_ents, all_dim_ents);
970
971 row_adj.clear();
972 for (auto e : dim_ents) {
973 auto adj_it = adj_bridge_map.find(e);
974 if (adj_it != adj_bridge_map.end()) {
975
976 for (const auto idx : adj_it->adj)
977 row_adj.push_back(idx);
978
979 } else
980 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
981 "Entity not found");
982 }
983
984 std::sort(row_adj.begin(), row_adj.end());
985 auto end = std::unique(row_adj.begin(), row_adj.end());
986
987 size_t row_size = std::distance(row_adj.begin(), end);
988 max_row_size = std::max(max_row_size, row_size);
989 if (j.capacity() < (nb_loc_elements - jj) * max_row_size)
990 j.reserve(nb_loc_elements * max_row_size);
991
992 i[jj] = j.size();
993 auto diag = ents.index(*fe_it);
994 for (auto it = row_adj.begin(); it != end; ++it)
995 if (*it != diag)
996 j.push_back(*it);
997 }
998
999 ++jj;
1000
1001 if (th_vertex_weights != NULL)
1002 weight_ents.push_back(*fe_it);
1003 }
1004
1005 i[jj] = j.size();
1006 }
1007
1008 CHKERR PetscMalloc(i.size() * sizeof(int), &_i);
1009 CHKERR PetscMalloc(j.size() * sizeof(int), &_j);
1010 copy(i.begin(), i.end(), _i);
1011 copy(j.begin(), j.end(), _j);
1012 }
1013
1014 // get weights
1015 int *vertex_weights = NULL;
1016 if (th_vertex_weights != NULL) {
1017 CHKERR PetscMalloc(weight_ents.size() * sizeof(int), &vertex_weights);
1018 CHKERR m_field.get_moab().tag_get_data(*th_vertex_weights,
1019 &*weight_ents.begin(),
1020 weight_ents.size(), vertex_weights);
1021 }
1022
1023 {
1024 Mat Adj;
1025 // Adjacency matrix used to partition problems, f.e. METIS
1026 CHKERR MatCreateMPIAdj(m_field.get_comm(), rend - rstart, nb_elems, _i, _j,
1027 PETSC_NULLPTR, &Adj);
1028 CHKERR MatSetOption(Adj, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE);
1029
1030 if (debug) {
1031 Mat A;
1032 CHKERR MatConvert(Adj, MATMPIAIJ, MAT_INITIAL_MATRIX, &A);
1033 CHKERR MatView(A, PETSC_VIEWER_DRAW_WORLD);
1034 std::string wait;
1035 std::cin >> wait;
1036 CHKERR MatDestroy(&A);
1037 }
1038
1039 // run pets to do partitioning
1040 MOFEM_LOG("WORLD", Sev::verbose) << "Start";
1041
1042 MatPartitioning part;
1043 IS is;
1044 CHKERR MatPartitioningCreate(m_field.get_comm(), &part);
1045
1046 CHKERR MatPartitioningSetAdjacency(part, Adj);
1047 CHKERR MatPartitioningSetFromOptions(part);
1048 CHKERR MatPartitioningSetNParts(part, n_parts);
1049 if (th_vertex_weights != NULL) {
1050 CHKERR MatPartitioningSetVertexWeights(part, vertex_weights);
1051 }
1052 CHKERR MatPartitioningApply(part, &is);
1053
1054 MOFEM_LOG("WORLD", Sev::verbose) << "End";
1055
1056 // gather
1057 IS is_gather, is_num, is_gather_num;
1058 CHKERR ISAllGather(is, &is_gather);
1059 CHKERR ISPartitioningToNumbering(is, &is_num);
1060 CHKERR ISAllGather(is_num, &is_gather_num);
1061
1062 const int *part_number, *gids;
1063 CHKERR ISGetIndices(is_gather, &part_number);
1064 CHKERR ISGetIndices(is_gather_num, &gids);
1065
1066 // set partition tag and gid tag to entities
1067 ParallelComm *pcomm = ParallelComm::get_pcomm(
1068 &m_field.get_moab(), m_field.get_basic_entity_data_ptr()->pcommID);
1069 Tag part_tag = pcomm->part_tag();
1070 CHKERR m_field.get_moab().tag_set_data(part_tag, ents, part_number);
1071 Tag gid_tag = m_field.get_moab().globalId_tag();
1072
1073 std::map<int, Range> parts_ents;
1074 {
1075 // get entities on each part
1076 Range::iterator eit = ents.begin();
1077 for (int ii = 0; eit != ents.end(); eit++, ii++) {
1078 parts_ents[part_number[ii]].insert(*eit);
1079 }
1080 Range tagged_sets;
1081 CHKERR m_field.get_moab().get_entities_by_type_and_tag(
1082 0, MBENTITYSET, &part_tag, NULL, 1, tagged_sets,
1083 moab::Interface::UNION);
1084 if (!tagged_sets.empty())
1085 CHKERR m_field.get_moab().tag_delete_data(part_tag, tagged_sets);
1086
1087 if (n_parts > (int)tagged_sets.size()) {
1088 // too few partition sets - create missing ones
1089 int num_new = n_parts - tagged_sets.size();
1090 for (int i = 0; i < num_new; i++) {
1091 EntityHandle new_set;
1092 CHKERR m_field.get_moab().create_meshset(MESHSET_SET, new_set);
1093 tagged_sets.insert(new_set);
1094 }
1095 } else if (n_parts < (int)tagged_sets.size()) {
1096 // too many partition sets - delete extras
1097 int num_del = tagged_sets.size() - n_parts;
1098 for (int i = 0; i < num_del; i++) {
1099 EntityHandle old_set = tagged_sets.pop_back();
1100 CHKERR m_field.get_moab().delete_entities(&old_set, 1);
1101 }
1102 }
1103 // write a tag to those sets denoting they're partition sets, with a
1104 // value of the proc number
1105 std::vector<int> dum_ids(n_parts);
1106 for (int i = 0; i < n_parts; i++)
1107 dum_ids[i] = i;
1108 CHKERR m_field.get_moab().tag_set_data(part_tag, tagged_sets,
1109 &*dum_ids.begin());
1110 CHKERR m_field.get_moab().clear_meshset(tagged_sets);
1111
1112 // get lower dimension entities on each part
1113 for (int pp = 0; pp != n_parts; pp++) {
1114 Range dim_ents = parts_ents[pp].subset_by_dimension(dim);
1115 for (int dd = dim - 1; dd >= 0; dd--) {
1116 Range adj_ents;
1117 CHKERR m_field.get_moab().get_adjacencies(
1118 dim_ents, dd, false, adj_ents, moab::Interface::UNION);
1119 parts_ents[pp].merge(adj_ents);
1120 }
1121 }
1122 for (int pp = 1; pp != n_parts; pp++) {
1123 for (int ppp = 0; ppp != pp; ppp++) {
1124 parts_ents[pp] = subtract(parts_ents[pp], parts_ents[ppp]);
1125 }
1126 }
1127
1128 for (int pp = 0; pp != n_parts; pp++) {
1129 CHKERR m_field.get_moab().add_entities(tagged_sets[pp], parts_ents[pp]);
1130 }
1131
1132 auto set_part = [&]() {
1134 for (EntityType t = MBEDGE; t != MBENTITYSET; ++t) {
1135 for (int pp = 0; pp != n_parts; pp++) {
1136 Range type_ents = parts_ents[pp].subset_by_type(t);
1137 CHKERR m_field.get_moab().tag_clear_data(part_tag, type_ents, &pp);
1138 }
1139 }
1141 };
1142
1143 auto set_gid = [&]() {
1145 for (int d = 0; d != 4; ++d) {
1146
1147 void *ptr;
1148 int count;
1149
1150 int gid = 1; // moab indexing from 1
1151 for (int pp = 0; pp != n_parts; pp++) {
1152 Range type_ents = parts_ents[pp].subset_by_dimension(d);
1153
1154 auto eit = type_ents.begin();
1155 for (; eit != type_ents.end();) {
1156 CHKERR m_field.get_moab().tag_iterate(
1157 gid_tag, eit, type_ents.end(), count, ptr);
1158 auto gid_tag_ptr = static_cast<int *>(ptr);
1159 for (; count > 0; --count) {
1160 *gid_tag_ptr = gid;
1161 ++eit;
1162 ++gid;
1163 ++gid_tag_ptr;
1164 }
1165 }
1166 }
1167 }
1168
1170 };
1171
1172 CHKERR set_part();
1173 CHKERR set_gid();
1174 }
1175
1176 if (debug) {
1177 if (m_field.get_comm_rank() == 0) {
1178 for (int rr = 0; rr != n_parts; rr++) {
1179 ostringstream ss;
1180 ss << "out_part_" << rr << ".vtk";
1181 MOFEM_LOG("SELF", Sev::inform) << "Save debug part mesh " << ss.str();
1182 EntityHandle meshset;
1183 CHKERR m_field.get_moab().create_meshset(MESHSET_SET, meshset);
1184 CHKERR m_field.get_moab().add_entities(meshset, parts_ents[rr]);
1185 CHKERR m_field.get_moab().write_file(ss.str().c_str(), "VTK", "",
1186 &meshset, 1);
1187 CHKERR m_field.get_moab().delete_entities(&meshset, 1);
1188 }
1189 }
1190 }
1191
1192 CHKERR ISRestoreIndices(is_gather, &part_number);
1193 CHKERR ISRestoreIndices(is_gather_num, &gids);
1194 CHKERR ISDestroy(&is_num);
1195 CHKERR ISDestroy(&is_gather_num);
1196 CHKERR ISDestroy(&is_gather);
1197 CHKERR ISDestroy(&is);
1198 CHKERR MatPartitioningDestroy(&part);
1199 CHKERR MatDestroy(&Adj);
1200 }
1201
1203}
1204
1206 moab::Interface &moab, const char *file_name, int dim,
1207 LoadFileFun proc_skin_fun, const char *options) {
1209
1210 MOFEM_LOG_CHANNEL("WORLD");
1211 MOFEM_LOG_CHANNEL("SYNC");
1212
1213 MOFEM_LOG("SYNC", sev) << "Load file " << file_name;
1214 CHKERR moab.load_file(file_name, 0, options);
1216 MOFEM_LOG("SYNC", sev) << "Load file <- done";
1217 MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, sev);
1218
1219 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
1220 if (pcomm == NULL)
1221 pcomm = new ParallelComm(&moab, PETSC_COMM_WORLD);
1222 if (pcomm->size() == 1)
1224
1225 Skinner skin(&moab);
1226
1227 auto print_range_on_procs = [&](const Range &range, std::string name) {
1228 MOFEM_LOG("SYNC", sev) << name << " on proc [" << pcomm->rank()
1229 << "] : " << range.size();
1230 MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, sev);
1231 };
1232
1233 auto save_range_to_file = [&](const Range range, std::string name = "part") {
1234 if (!debug)
1235 return;
1236 int rr = pcomm->rank();
1237 ostringstream ss;
1238 ss << "out_" << name << "_" << rr << ".vtk";
1239 MOFEM_LOG("SYNC", sev) << "Save debug part mesh " << ss.str();
1240 EntityHandle meshset;
1241 CHKERR moab.create_meshset(MESHSET_SET, meshset);
1242 CHKERR moab.add_entities(meshset, range);
1243 if (!range.empty())
1244 CHKERR moab.write_file(ss.str().c_str(), "VTK", "", &meshset, 1);
1245 MOFEM_LOG("SYNC", sev) << "Empty range";
1246 CHKERR moab.delete_entities(&meshset, 1);
1247 MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, sev);
1248 };
1249
1250 auto get_skin = [&](auto e) {
1251 Range s;
1252 CHKERR skin.find_skin(0, e.subset_by_dimension(dim), false, s);
1253 return s;
1254 };
1255
1256 auto get_adj = [&](auto ents, auto dim) {
1257 Range adj;
1258 CHKERR moab.get_adjacencies(ents, dim, false, adj, moab::Interface::UNION);
1259 return adj;
1260 };
1261
1262 Range all_ents;
1263 CHKERR moab.get_entities_by_handle(0, all_ents, false);
1264 save_range_to_file(all_ents, "all_ents");
1265
1266 Tag part_tag = pcomm->part_tag();
1267 Range tagged_sets, proc_ents, off_proc_ents;
1268
1269 CHKERR moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1270 tagged_sets, moab::Interface::UNION);
1271 print_range_on_procs(tagged_sets, "tagged_sets");
1272 for (auto &mit : tagged_sets) {
1273 int part;
1274 CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1275 if (part == pcomm->rank()) {
1276 CHKERR moab.get_entities_by_handle(mit, proc_ents, true);
1277 } else {
1278 CHKERR moab.get_entities_by_handle(mit, off_proc_ents, true);
1279 }
1280 }
1281
1282 // set part tags to entities, they might be not set
1283 for (auto &mit : tagged_sets) {
1284 int part;
1285 CHKERR moab.tag_get_data(part_tag, &mit, 1, &part);
1286 Range ents;
1287 CHKERR moab.get_entities_by_handle(mit, ents, true);
1288 CHKERR moab.tag_clear_data(part_tag, ents, &part);
1289 }
1290
1291 print_range_on_procs(proc_ents, "proc_ents");
1292 save_range_to_file(proc_ents, "proc_ents");
1293
1294 auto get_proc_ents_skin = [&]() {
1295 std::array<Range, 4>
1296 proc_ents_skin; // stores only entities shared with other processors
1297 auto all_skin = get_skin(all_ents.subset_by_dimension(dim));
1298 auto proc_skin = get_skin(proc_ents.subset_by_dimension(dim));
1299 if (dim == 3) {
1300 proc_ents_skin[2] = subtract(proc_skin, all_skin); // faces
1301 proc_ents_skin[1] = get_adj(proc_ents_skin[dim - 1], 1); // edges
1302 }
1303 if (dim == 2) {
1304 proc_ents_skin[1] = subtract(proc_skin, all_skin); // edges
1305 }
1306 CHKERR moab.get_connectivity(proc_ents_skin[dim - 1], proc_ents_skin[0],
1307 false); // vertices
1308 return proc_ents_skin;
1309 };
1310
1311 auto add_post_proc_skin = [&](auto &&proc_ents_skin) {
1312 CubitMeshSet_multiIndex cubit_meshsets_index; ///< cubit meshsets
1313
1314 Tag nsTag, ssTag, nsTag_data, ssTag_data, bhTag, bhTag_header;
1315 CHKERR MeshsetsManager::getTags(moab, nsTag, ssTag, nsTag_data, ssTag_data,
1316 bhTag, bhTag_header, QUIET);
1317
1318 Range meshsets;
1319 CHKERR moab.get_entities_by_type(0, MBENTITYSET, meshsets, false);
1320 for (auto m : meshsets) {
1321 // check if meshset is cubit meshset
1322 CubitMeshSets block(moab, m);
1324 .any()) {
1325 auto p = cubit_meshsets_index.insert(block);
1326 if (!p.second) {
1327 // blockset/nodeset/sideset set exist, could be created on other
1328 // processor.
1329 Range ents;
1330 CHKERR moab.get_entities_by_handle(m, ents, true);
1331 CHKERR moab.add_entities(p.first->getMeshset(), ents);
1332 CHKERR moab.delete_entities(&m, 1);
1333 }
1334 }
1335 }
1336
1337 for (auto &m : cubit_meshsets_index) {
1338 MOFEM_LOG("WORLD", sev) << "LoadFile read " << m;
1339 }
1340 MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, sev);
1341
1342 std::vector<const CubitMeshSets *> vec_ptr;
1343 for (auto &m : cubit_meshsets_index) {
1344 vec_ptr.push_back(&m);
1345 }
1347
1348 return proc_skin_fun(std::move(proc_ents_skin), std::move(vec_ptr));
1349 };
1350
1351 auto remove_off_proc_ents = [&](auto &all_ents, auto &off_proc_ents,
1352 auto &proc_ents_skin) {
1353 auto to_remove = off_proc_ents;
1354 for (auto d = dim - 1; d >= 0; --d) {
1355 to_remove = subtract(to_remove, proc_ents_skin[d]);
1356 }
1357
1358 Range meshsets;
1359 CHKERR moab.get_entities_by_type(0, MBENTITYSET, meshsets, true);
1360 for (auto m : meshsets) {
1361 CHKERR moab.remove_entities(m, to_remove);
1362 }
1363 for (int dd = dim; dd > 0; --dd) {
1364 CHKERR moab.delete_entities(to_remove.subset_by_dimension(dd));
1365 }
1366 };
1367
1368 auto proc_ents_skin = add_post_proc_skin(get_proc_ents_skin());
1369 for (auto d = dim - 1; d >= 0; --d) {
1370 save_range_to_file(proc_ents_skin[d], "proc_ents_skin" + std::to_string(d));
1371 }
1372
1373 if (pcomm->rank()) {
1374 remove_off_proc_ents(all_ents, off_proc_ents, proc_ents_skin);
1375 }
1376
1377 for (auto d = dim - 1; d >= 0; --d) {
1378 print_range_on_procs(proc_ents_skin[d],
1379 "proc_ents_skin by dim" + std::to_string(d));
1380 }
1381
1382 CHKERR pcomm->resolve_shared_ents(0, proc_ents, dim, -1,
1383 proc_ents_skin.data());
1384
1385 if (debug) {
1386
1387 // Create a tag
1388 auto gid_tag = moab.globalId_tag();
1389
1390 int def_val = -1;
1391 Tag tag_handle;
1392 CHKERR moab.tag_get_handle("TestGather", 1, MB_TYPE_INTEGER, tag_handle,
1393 MB_TAG_DENSE | MB_TAG_CREAT, &def_val);
1394 Range gather_ents;
1395 if (pcomm->rank() > 0) {
1396 gather_ents = proc_ents.subset_by_dimension(3);
1397 std::vector<int> vals(gather_ents.size());
1398 std::for_each(vals.begin(), vals.end(), [](auto &v) { v = std::rand(); });
1399 CHKERR moab.tag_set_data(tag_handle, gather_ents, vals.data());
1400 CHKERR pcomm->gather_data(gather_ents, tag_handle, gid_tag, 0, 0);
1401 } else {
1402 gather_ents = proc_ents.subset_by_dimension(3);
1403 CHKERR pcomm->gather_data(gather_ents, tag_handle, gid_tag, 0, 0);
1404 }
1405 }
1406
1407 Range all_ents_after;
1408 CHKERR moab.get_entities_by_handle(0, all_ents_after);
1409 save_range_to_file(all_ents_after.subset_by_dimension(3),
1410 "all_ents_part_after");
1411
1412 MOFEM_LOG("SYNC", sev) << "Resolved entities <- done";
1413 MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, sev);
1414
1416}
1417
1418Range CommInterface::getPartEntities(moab::Interface &moab, int part) {
1419
1420 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
1421 if (pcomm == NULL)
1422 pcomm = new ParallelComm(&moab, PETSC_COMM_WORLD);
1423 if (pcomm->size() == 1) {
1424 Range ents;
1425 CHK_MOAB_THROW(moab.get_entities_by_handle(0, ents, false),
1426 "get_entities_by_handle failed");
1427 return subtract(ents, ents.subset_by_type(MBENTITYSET));
1428 }
1429
1430 Range proc_ents;
1431
1432 auto get_proc_ents = [&]() {
1434
1435 auto get_all_mesh_entities = [&]() {
1437 CHKERR moab.get_entities_by_handle(0, proc_ents, false);
1438 proc_ents = subtract(proc_ents, proc_ents.subset_by_type(MBENTITYSET));
1440 };
1441
1442 Tag part_tag = pcomm->part_tag();
1443 Range tagged_sets;
1444 auto rval =
1445 moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1446 tagged_sets, moab::Interface::UNION);
1447 if (rval == MB_TAG_NOT_FOUND || rval == MB_ENTITY_NOT_FOUND ||
1448 tagged_sets.empty()) {
1449 MOFEM_LOG("SELF", Sev::warning)
1450 << "Partition tag or partition sets not found, returning all mesh "
1451 "entities";
1452 CHKERR get_all_mesh_entities();
1454 }
1455 CHKERR rval;
1456
1457 for (auto &mit : tagged_sets) {
1458 int part_set;
1459 CHKERR moab.tag_get_data(part_tag, &mit, 1, &part_set);
1460 if (part_set == part) {
1461 rval = moab.get_entities_by_handle(mit, proc_ents, true);
1462 if (rval == MB_SUCCESS) {
1464 }
1465 if (rval == MB_ENTITY_NOT_FOUND) {
1466 MOFEM_LOG("SELF", Sev::warning)
1467 << "Partition set is stale, returning all mesh entities";
1468 proc_ents.clear();
1469 CHKERR get_all_mesh_entities();
1471 }
1472 CHKERR rval;
1473 }
1474 }
1475
1476 MOFEM_LOG("SELF", Sev::warning)
1477 << "Partition set for requested part not found, returning all mesh "
1478 "entities";
1479 CHKERR get_all_mesh_entities();
1482 };
1483
1484 CHK_THROW_MESSAGE(get_proc_ents(), "get_proc_ents failed");
1485
1486 return proc_ents;
1487}
1488
1490 MPI_Comm comm, moab::Interface &moab,
1491 std::function<Range(Range)> get_entities_fun, const int nb_coeffs, Sev sev,
1492 int root_rank, bool get_vertices) {
1493
1495 Range r, ghost_ents;
1496
1497 auto get_gids = [&](Range &ents) {
1498 std::vector<int> ids(ents.size());
1499 auto gid_tag = moab.globalId_tag();
1500 CHKERR moab.tag_get_data(gid_tag, ents, ids.data());
1501 return ids;
1502 };
1503
1504 auto create_ao = [&](auto &&ids) {
1505 AO ao_raw;
1507 AOCreateMapping(comm, ids.size(), ids.data(), PETSC_NULLPTR, &ao_raw),
1508 "create ao failed");
1509 return SmartPetscObj<AO>(ao_raw, false);
1510 };
1511
1512 auto apply_ao = [&](auto ao, std::vector<int> &&ids) {
1513 CHK_THROW_MESSAGE(AOApplicationToPetsc(ao, ids.size(), ids.data()),
1514 "AOApplicationToPetsc failed");
1515 return ids;
1516 };
1517
1518 auto get_tag_ids = [&](auto ao, Range &ents) {
1519 return apply_ao(ao, get_gids(ents));
1520 };
1521
1522 auto fun = [&]() {
1524 auto pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
1525 Tag part_tag = pcomm->part_tag();
1526 Range tagged_sets;
1527 CHKERR moab.get_entities_by_type_and_tag(0, MBENTITYSET, &part_tag, NULL, 1,
1528 tagged_sets,
1529 moab::Interface::UNION);
1530 auto get_proc_and_off_proc_ents = [&]() {
1531 Range proc_ents, off_proc_ents;
1532 if (tagged_sets.empty() && pcomm->size() == 1) {
1533 CHK_MOAB_THROW(moab.get_entities_by_handle(0, proc_ents, false),
1534 "get_entities_by_handle failed");
1535 proc_ents = subtract(proc_ents, proc_ents.subset_by_type(MBENTITYSET));
1536 proc_ents = subtract(proc_ents, proc_ents.subset_by_type(MBVERTEX));
1537 return std::make_pair(proc_ents, Range());
1538 }
1539 for (auto &mit : tagged_sets) {
1540 int part;
1541 CHK_MOAB_THROW(moab.tag_get_data(part_tag, &mit, 1, &part),
1542 "tag_get_data failed");
1543 if (part == pcomm->rank()) {
1544 CHK_MOAB_THROW(moab.get_entities_by_handle(mit, proc_ents, false),
1545 "get_entities_by_handle failed");
1546 } else {
1547 CHK_MOAB_THROW(moab.get_entities_by_handle(mit, off_proc_ents, false),
1548 "get_entities_by_handle failed");
1549 }
1550 proc_ents = subtract(proc_ents, off_proc_ents);
1551 }
1552 return std::make_pair(proc_ents, off_proc_ents);
1553 };
1554
1555 auto get_proc_and_off_proc_verts = [&]() {
1556 Range proc_ents, off_proc_ents;
1557 if (tagged_sets.empty()) {
1558 CHK_MOAB_THROW(moab.get_entities_by_type(0, MBVERTEX, proc_ents),
1559 "get_entities_by_type failed");
1560 return std::make_pair(proc_ents, Range());
1561 }
1562 std::map<int, Range> parts_ents;
1563 for (auto &mit : tagged_sets) {
1564 int part;
1565 CHK_MOAB_THROW(moab.tag_get_data(part_tag, &mit, 1, &part),
1566 "tag_get_data failed");
1568 moab.get_entities_by_handle(mit, parts_ents[part], false),
1569 "get_entities_by_handle failed");
1570 parts_ents[part] = subtract(
1571 parts_ents[part], parts_ents[part].subset_by_type(MBENTITYSET));
1572 }
1573 Range v;
1574 CHK_MOAB_THROW(moab.get_connectivity(parts_ents[pcomm->rank()], v),
1575 "get_connectivity failed");
1576 int p = 0;
1577 for (; p != pcomm->rank(); ++p) {
1578 Range vv;
1579 CHK_MOAB_THROW(moab.get_connectivity(parts_ents[p], vv),
1580 "get_connectivity failed");
1581 v = subtract(v, vv);
1582 off_proc_ents.merge(vv);
1583 }
1584 for (; p != pcomm->size(); ++p) {
1585 Range vv;
1586 CHK_MOAB_THROW(moab.get_connectivity(parts_ents[p], vv),
1587 "get_connectivity failed");
1588 vv = subtract(vv, v);
1589 off_proc_ents.merge(vv);
1590 }
1591 proc_ents = v;
1592 return std::make_pair(proc_ents, off_proc_ents);
1593 };
1594
1595 auto [proc_ents, off_proc_ents] = get_proc_and_off_proc_ents();
1596
1597 if (get_vertices) {
1598 auto [proc_verts, off_proc_verts] = get_proc_and_off_proc_verts();
1599 proc_ents.merge(proc_verts);
1600 off_proc_ents.merge(off_proc_verts);
1601 }
1602 r = get_entities_fun(proc_ents);
1603 auto o = get_entities_fun(off_proc_ents);
1604 auto ao = create_ao(get_gids(r));
1605
1606 auto set_ghosts = [&](auto &&ghosts_gids) {
1607 std::vector<int> ghosts_dofs(nb_coeffs * ghosts_gids.size());
1608 for (int i = 0; i < ghosts_gids.size(); ++i)
1609 for (int j = 0; j < nb_coeffs; ++j)
1610 ghosts_dofs[i * nb_coeffs + j] = nb_coeffs * ghosts_gids[i] + j;
1611 return ghosts_dofs;
1612 };
1613
1614 std::vector<int> ghosts;
1615 if (pcomm->rank() == root_rank) {
1616 ghosts = set_ghosts(get_tag_ids(ao, o));
1617 ghost_ents = o;
1618 } else {
1619 Range ents;
1620 CHKERR moab.get_entities_by_handle(0, ents, true);
1621 ents = get_entities_fun(ents);
1622 ents = subtract(ents, r);
1623 ghosts = set_ghosts(get_tag_ids(ao, ents));
1624 ghost_ents = ents;
1625 }
1626
1627 auto create_vec = [&]() {
1629 vec = createGhostVector(comm, nb_coeffs * r.size(), PETSC_DETERMINE,
1630 ghosts.size(), ghosts.data());
1632 };
1633 CHKERR create_vec();
1634
1636 };
1637
1638 CHKERR fun();
1639
1640 auto out = std::make_pair(std::make_pair(r, ghost_ents), vec);
1641
1642#ifndef NDEBUG
1643 {
1644
1645 auto check = [&](auto &ents, auto &id, auto &idx) {
1647 bool error = false;
1648 for (int i = 0; i < ents.size(); ++i) {
1649 for (int j = 0; j < nb_coeffs; ++j) {
1650 if (idx[i * nb_coeffs + j] != nb_coeffs * id[i] + j) {
1651 error = true;
1652 MOFEM_LOG("SYNC", Sev::error)
1653 << "indexes not equal: " << idx[i * nb_coeffs + j]
1654 << " != " << nb_coeffs * idx[i] + j;
1655 }
1656 }
1657 }
1658 MOFEM_LOG_SEVERITY_SYNC(PETSC_COMM_WORLD, Sev::error);
1659 if (error)
1660 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "indexes do not match");
1662 };
1663
1664 std::vector<double> def_val(nb_coeffs, 0.0);
1665 Tag tag;
1666 CHKERR moab.tag_get_handle("TestGather", nb_coeffs, MB_TYPE_DOUBLE, tag,
1667 MB_TAG_SPARSE | MB_TAG_CREAT, def_val.data());
1668 auto ao = create_ao(get_gids(r));
1669 auto id = get_tag_ids(ao, r);
1670 std::vector<double> idx(nb_coeffs * r.size());
1671 for (int i = 0; i < r.size(); ++i) {
1672 for (int j = 0; j < nb_coeffs; ++j) {
1673 idx[i * nb_coeffs + j] = nb_coeffs * id[i] + j;
1674 }
1675 }
1676 CHKERR moab.tag_set_data(tag, r, idx.data());
1677 CHKERR updateEntitiesPetscVector(moab, out, tag);
1678 idx.resize(nb_coeffs * r.size());
1679 CHKERR moab.tag_get_data(tag, r, idx.data());
1680 CHK_THROW_MESSAGE(check(r, id, idx), "indexes do not match")
1681 auto ghost_id = get_tag_ids(ao, ghost_ents);
1682 idx.resize(nb_coeffs * ghost_ents.size());
1683 CHKERR moab.tag_get_data(tag, ghost_ents, idx.data());
1684 CHK_THROW_MESSAGE(check(ghost_ents, ghost_id, idx),
1685 "ghost indexes do not match")
1686 CHKERR moab.tag_delete(tag);
1687 }
1688#endif // NDEBUG
1689
1690 return out;
1691}
1692
1695 Tag tag) {
1697
1698 int local_size;
1699 CHKERR VecGetLocalSize(vec.second, &local_size);
1700 int nb_coeffs;
1701 CHKERR moab.tag_get_length(tag, nb_coeffs);
1702 if (vec.first.first.size() * nb_coeffs != local_size) {
1703 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1704 "Local size of vector does not match number of entities");
1705 }
1706
1707 auto set_vec_from_tags = [&]() {
1709 double *v_array;
1710 // set vector
1711 CHKERR VecGetArray(vec.second, &v_array);
1712 CHKERR moab.tag_get_data(tag, vec.first.first, v_array);
1713 CHKERR moab.tag_get_data(tag, vec.first.second, &v_array[local_size]);
1714 CHKERR VecRestoreArray(vec.second, &v_array);
1716 };
1717
1718 CHKERR set_vec_from_tags();
1719
1721}
1722
1725 Tag tag) {
1727
1728 int local_size;
1729 CHKERR VecGetLocalSize(vec.second, &local_size);
1730 int nb_coeffs;
1731 CHKERR moab.tag_get_length(tag, nb_coeffs);
1732 if (vec.first.first.size() * nb_coeffs != local_size) {
1733 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1734 "Local size of vector does not match number of entities");
1735 }
1736
1737 auto set_tags_from_vec = [&]() {
1739 double *v_array;
1740 CHKERR VecGetArray(vec.second, &v_array);
1741 CHKERR moab.tag_set_data(tag, vec.first.first, v_array);
1742 CHKERR moab.tag_set_data(tag, vec.first.second, &v_array[local_size]);
1743 CHKERR VecRestoreArray(vec.second, &v_array);
1745 };
1746
1747 CHKERR set_tags_from_vec();
1748
1750}
1751
1753CommInterface::createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab,
1754 int dim, const int nb_coeffs, Sev sev,
1755 int root_rank) {
1757 comm, moab,
1758
1759 [dim](Range r) { return r.subset_by_dimension(dim); }
1760
1761 ,
1762 nb_coeffs, sev, root_rank, (dim != 0) ? false : true);
1763}
1764
1767 EntitiesPetscVector &vec, Tag tag,
1768 UpdateGhosts update_ghosts) {
1770
1771 CHKERR setVectorFromTag(moab, vec, tag);
1772 CHKERR update_ghosts(vec.second);
1773 CHKERR setTagFromVector(moab, vec, tag);
1774
1776}
1777
1778} // namespace MoFEM
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
constexpr double a
@ QUIET
@ NOISY
@ VERBOSE
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ NODESET
@ SIDESET
@ BLOCKSET
@ MOFEM_IMPOSSIBLE_CASE
Definition definitions.h:35
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
auto fun
multi_index_container< boost::shared_ptr< FiniteElement >, indexed_by< hashed_unique< tag< FiniteElement_Meshset_mi_tag >, member< FiniteElement, EntityHandle, &FiniteElement::meshset > >, hashed_unique< tag< BitFEId_mi_tag >, const_mem_fun< FiniteElement, BitFEId, &FiniteElement::getId >, HashBit< BitFEId >, EqBit< BitFEId > >, ordered_unique< tag< FiniteElement_name_mi_tag >, const_mem_fun< FiniteElement, boost::string_ref, &FiniteElement::getNameRef > > > > FiniteElement_multiIndex
MultiIndex for entities for FiniteElement.
virtual const Problem * get_problem(const std::string problem_name) const =0
Get the problem object.
virtual const FieldEntity_multiIndex * get_field_ents() const =0
Get the field ents object.
virtual const FiniteElement_multiIndex * get_finite_elements() const =0
Get the finite elements object.
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
MoFEMErrorCode synchroniseFieldEntities(const std::string name, int verb=DEFAULT_VERBOSITY)
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
MoFEMErrorCode getTags(int verb=-1)
Get tag handles used on meshsets.
MoFEMErrorCode partitionMesh(const Range &ents, const int dim, const int adj_dim, const int n_parts, Tag *th_vertex_weights=nullptr, Tag *th_edge_weights=nullptr, Tag *th_part_weights=nullptr, int verb=VERBOSE, const bool debug=false)
Set partition tag to each finite element in the problem.
MoFEMErrorCode resolveSharedFiniteElements(const Problem *problem_ptr, const std::string &fe_name, int verb=DEFAULT_VERBOSITY)
resolve shared entities for finite elements in the problem
auto bit
set bit
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'j', 3 > j
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< 32 > CubitBCType
Definition Types.hpp:52
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto type_from_handle(const EntityHandle h)
get type from entity handle
static const bool debug
multi_index_container< CubitMeshSets, indexed_by< hashed_unique< tag< Meshset_mi_tag >, member< CubitMeshSets, EntityHandle, &CubitMeshSets::meshset > >, ordered_non_unique< tag< CubitMeshsetType_mi_tag >, const_mem_fun< CubitMeshSets, unsigned long int, &CubitMeshSets::getBcTypeULong > >, ordered_non_unique< tag< CubitMeshsetMaskedType_mi_tag >, const_mem_fun< CubitMeshSets, unsigned long int, &CubitMeshSets::getMaskedBcTypeULong > >, ordered_non_unique< tag< CubitMeshsets_name >, const_mem_fun< CubitMeshSets, std::string, &CubitMeshSets::getName > >, hashed_unique< tag< Composite_Cubit_msId_And_MeshsetType_mi_tag >, composite_key< CubitMeshSets, const_mem_fun< CubitMeshSets, int, &CubitMeshSets::getMeshsetId >, const_mem_fun< CubitMeshSets, unsigned long int, &CubitMeshSets::getMaskedBcTypeULong > > > > > CubitMeshSet_multiIndex
Stores data about meshsets (see CubitMeshSets) storing data about boundary conditions,...
auto createGhostVector(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt nghost, const PetscInt ghosts[])
Create smart ghost vector.
constexpr AssemblyType A
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
constexpr double g
FTensor::Index< 'm', 3 > m
Managing BitRefLevels.
static MoFEMErrorCode updateEntitiesPetscVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag, UpdateGhosts update_gosts=defaultUpdateGhosts)
Exchange data between vector and data.
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
std::function< MoFEMErrorCode(Vec vec)> UpdateGhosts
static Range getPartEntities(moab::Interface &moab, int part)
CommInterface(const MoFEM::Core &core)
MoFEMErrorCode makeEntitiesMultishared(const EntityHandle *entities, const int num_entities, const int owner_proc=0, int verb=DEFAULT_VERBOSITY)
make entities from proc 0 shared on all proc
static MoFEMErrorCode loadFileRootProcAllRestDistributed(moab::Interface &moab, const char *file_name, int dim, LoadFileFun proc_skin_fun=defaultProcSkinFun, const char *options="PARALLEL=BCAST;PARTITION=")
Root proc has whole mesh, other procs only part of it.
MoFEMErrorCode synchroniseEntities(Range &ent, std::map< int, Range > *received_ents, int verb=DEFAULT_VERBOSITY)
synchronize entity range on processors (collective)
std::function< std::array< Range, 4 >(std::array< Range, 4 > &&, std::vector< const CubitMeshSets * > &&)> LoadFileFun
static MoFEMErrorCode setVectorFromTag(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Vector From Tag object.
static MoFEMErrorCode setTagFromVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Tag From Vector object.
MoFEMErrorCode makeFieldEntitiesMultishared(const std::string field_name, const int owner_proc=0, int verb=DEFAULT_VERBOSITY)
make field entities multi shared
std::pair< std::pair< Range, Range >, SmartPetscObj< Vec > > EntitiesPetscVector
MoFEMErrorCode resolveParentEntities(const Range &ent, int verb=DEFAULT_VERBOSITY)
Synchronise parent entities.
MoFEMErrorCode exchangeFieldData(const std::string field_name, int verb=DEFAULT_VERBOSITY)
Exchange field data.
static EntitiesPetscVector createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab, std::function< Range(Range)> get_entities_fun, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0, bool get_vertices=true)
Create a ghost vector for exchanging data.
virtual int get_comm_size() const =0
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
virtual moab::Interface & get_moab()=0
virtual EntityHandle get_field_meshset(const std::string name) const =0
get field meshset
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
virtual boost::shared_ptr< BasicEntityData > & get_basic_entity_data_ptr()=0
Get pointer to basic entity data.
Core (interface) class.
Definition Core.hpp:83
Tag get_th_RefBitLevel() const
Definition Core.hpp:203
Tag get_th_RefParentHandle() const
Definition Core.hpp:202
this struct keeps basic methods for moab meshset about material and boundary conditions
Deprecated interface functions.
UId getLocalUniqueIdCalculate() const
Generate UId for finite element entity.
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
static void sortMeshsets(std::vector< const CubitMeshSets * > &vec_ptr)
keeps basic data about problem
MoFEMErrorCode getNumberOfElementsByNameAndPart(MPI_Comm comm, const std::string name, PetscLayout *layout) const
Get number of finite elements by name on processors.
boost::shared_ptr< NumeredEntFiniteElement_multiIndex > numeredFiniteElementsPtr
store finite elements
intrusive_ptr for managing petsc objects
base class for all interface classes