v0.16.3
Loading...
Searching...
No Matches
ProblemsManager.cpp
Go to the documentation of this file.
1/** \file ProblemsManager.cpp
2 * \brief Managing complexities for problem
3 * \ingroup mofem_problems_manager
4 */
5
6namespace MoFEM {
7
8#define ProblemManagerFunctionBegin \
9 MoFEMFunctionBegin; \
10 MOFEM_LOG_CHANNEL("WORLD"); \
11 MOFEM_LOG_CHANNEL("SYNC"); \
12 MOFEM_LOG_FUNCTION(); \
13 MOFEM_LOG_TAG("SYNC", "ProblemsManager"); \
14 MOFEM_LOG_TAG("WORLD", "ProblemsManager")
15
17 IdxDataType(const UId uid, const int dof) {
18 bcopy(&uid, dAta, 4 * sizeof(int));
19 dAta[4] = dof;
20 }
21
22private:
23 int dAta[5];
24};
25
27 IdxDataTypePtr(const int *ptr) : pTr(ptr) {}
28 inline int getDofIdx() const {
29 int global_dof = pTr[4];
30 return global_dof;
31 }
32 inline UId getUId() const {
33 unsigned int b0, b1, b2, b3;
34 bcopy(&pTr[0], &b0, sizeof(int));
35 bcopy(&pTr[1], &b1, sizeof(int));
36 bcopy(&pTr[2], &b2, sizeof(int));
37 bcopy(&pTr[3], &b3, sizeof(int));
38 UId uid = static_cast<UId>(b0) | static_cast<UId>(b1) << 8 * sizeof(int) |
39 static_cast<UId>(b2) << 16 * sizeof(int) |
40 static_cast<UId>(b3) << 24 * sizeof(int);
41 return uid;
42 }
43
44private:
45 const int *pTr;
46};
47
49ProblemsManager::query_interface(boost::typeindex::type_index type_index,
50 UnknownInterface **iface) const {
51 *iface = const_cast<ProblemsManager *>(this);
52 return 0;
53}
54
56 : cOre(const_cast<MoFEM::Core &>(core)),
57 buildProblemFromFields(PETSC_FALSE),
58 synchroniseProblemEntities(PETSC_FALSE) {
59 PetscLogEventRegister("ProblemsManager", 0, &MOFEM_EVENT_ProblemsManager);
60}
61
63 MoFEM::Interface &m_field = cOre;
65 PetscOptionsBegin(m_field.get_comm(), "", "Problem manager", "none");
66 {
67 CHKERR PetscOptionsBool(
68 "-problem_build_from_fields",
69 "Add DOFs to problem directly from fields not through DOFs on elements",
71 }
72 PetscOptionsEnd();
74}
75
77 const Range &ents, const int dim, const int adj_dim, const int n_parts,
78 Tag *th_vertex_weights, Tag *th_edge_weights, Tag *th_part_weights,
79 int verb, const bool debug) {
80 return static_cast<MoFEM::Interface &>(cOre)
81 .getInterface<CommInterface>()
82 ->partitionMesh(ents, dim, adj_dim, n_parts, th_vertex_weights,
83 th_edge_weights, th_part_weights, verb, debug);
84}
85
87 const bool square_matrix,
88 int verb) {
89
90 MoFEM::Interface &m_field = cOre;
92 if (!(cOre.getBuildMoFEM() & (1 << 0)))
93 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
94 if (!(cOre.getBuildMoFEM() & (1 << 1)))
95 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
96 if (!(cOre.getBuildMoFEM() & (1 << 2)))
97 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
98 const Problem *problem_ptr;
99 CHKERR m_field.get_problem(name, &problem_ptr);
100 CHKERR buildProblem(const_cast<Problem *>(problem_ptr), square_matrix, verb);
101 cOre.getBuildMoFEM() |= 1 << 3; // It is assumed that user who uses this
102 // function knows what he is doing
104}
105
107 const bool square_matrix,
108 int verb) {
109 MoFEM::Interface &m_field = cOre;
110 auto dofs_field_ptr = m_field.get_dofs();
111 auto ents_field_ptr = m_field.get_field_ents();
112 auto adjacencies_ptr = m_field.get_ents_elements_adjacency();
114 PetscLogEventBegin(MOFEM_EVENT_ProblemsManager, 0, 0, 0, 0);
115
116 // Note: Only allowed changes on problem_ptr structure which not influence
117 // multi-index.
118
119 if (problem_ptr->getBitRefLevel().none()) {
120 SETERRQ(PETSC_COMM_SELF, 1, "problem <%s> refinement level not set",
121 problem_ptr->getName().c_str());
122 }
123 CHKERR m_field.clear_problem(problem_ptr->getName());
124
125 // zero finite elements
126 problem_ptr->numeredFiniteElementsPtr->clear();
127
128 DofEntity_multiIndex_active_view dofs_rows, dofs_cols;
129 auto make_rows_and_cols_view = [&](auto &dofs_rows, auto &dofs_cols) {
131 for (auto it = ents_field_ptr->begin(); it != ents_field_ptr->end(); ++it) {
132
133 const auto uid = (*it)->getLocalUniqueId();
134
135 auto r = adjacencies_ptr->get<Unique_mi_tag>().equal_range(uid);
136 for (auto lo = r.first; lo != r.second; ++lo) {
137
138 if ((lo->getBitFEId() & problem_ptr->getBitFEId()).any()) {
139 std::array<bool, 2> row_col = {false, false};
140
141 const BitRefLevel &prb_bit = problem_ptr->getBitRefLevel();
142 const BitRefLevel &prb_mask = problem_ptr->getBitRefLevelMask();
143 const BitRefLevel &fe_bit = lo->entFePtr->getBitRefLevel();
144
145 // if entity is not problem refinement level
146 if ((fe_bit & prb_mask) != fe_bit)
147 continue;
148 if ((fe_bit & prb_bit).none())
149 continue;
150
151 auto add_to_view = [&](auto &nb_dofs, auto &view, auto rc) {
152 auto dit = nb_dofs->lower_bound(uid);
153 decltype(dit) hi_dit;
154 if (dit != nb_dofs->end()) {
155 hi_dit = nb_dofs->upper_bound(
156 uid | static_cast<UId>(MAX_DOFS_ON_ENTITY - 1));
157 view.insert(dit, hi_dit);
158 row_col[rc] = true;
159 }
160 };
161
162 if ((lo->entFePtr->getBitFieldIdRow() & (*it)->getId()).any())
163 add_to_view(dofs_field_ptr, dofs_rows, ROW);
164
165 if (!square_matrix)
166 if ((lo->entFePtr->getBitFieldIdCol() & (*it)->getId()).any())
167 add_to_view(dofs_field_ptr, dofs_cols, COL);
168
169 if (square_matrix && row_col[ROW])
170 break;
171 else if (row_col[ROW] && row_col[COL])
172 break;
173 }
174 }
175 }
177 };
178
179 CHKERR make_rows_and_cols_view(dofs_rows, dofs_cols);
180
181 // Add row dofs to problem
182 {
183 // zero rows
184 problem_ptr->nbDofsRow = 0;
185 problem_ptr->nbLocDofsRow = 0;
186 problem_ptr->nbGhostDofsRow = 0;
187
188 // add dofs for rows
189 DofEntity_multiIndex_active_view::nth_index<0>::type::iterator miit,
190 hi_miit;
191 hi_miit = dofs_rows.get<0>().end();
192
193 int count_dofs = dofs_rows.get<1>().count(true);
194 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array =
195 boost::shared_ptr<std::vector<NumeredDofEntity>>(
196 new std::vector<NumeredDofEntity>());
197 problem_ptr->getRowDofsSequence()->push_back(dofs_array);
198 dofs_array->reserve(count_dofs);
199 miit = dofs_rows.get<0>().begin();
200 for (; miit != hi_miit; miit++) {
201 if ((*miit)->getActive()) {
202 dofs_array->emplace_back(*miit);
203 dofs_array->back().dofIdx = (problem_ptr->nbDofsRow)++;
204 }
205 }
206 auto hint = problem_ptr->numeredRowDofsPtr->end();
207 for (auto &v : *dofs_array) {
208 hint = problem_ptr->numeredRowDofsPtr->emplace_hint(hint, dofs_array, &v);
209 }
210 }
211
212 // Add col dofs to problem
213 if (!square_matrix) {
214 // zero cols
215 problem_ptr->nbDofsCol = 0;
216 problem_ptr->nbLocDofsCol = 0;
217 problem_ptr->nbGhostDofsCol = 0;
218
219 // add dofs for cols
220 DofEntity_multiIndex_active_view::nth_index<0>::type::iterator miit,
221 hi_miit;
222 hi_miit = dofs_cols.get<0>().end();
223
224 int count_dofs = 0;
225 miit = dofs_cols.get<0>().begin();
226 for (; miit != hi_miit; miit++) {
227 if (!(*miit)->getActive()) {
228 continue;
229 }
230 count_dofs++;
231 }
232
233 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array =
234 boost::shared_ptr<std::vector<NumeredDofEntity>>(
235 new std::vector<NumeredDofEntity>());
236 problem_ptr->getColDofsSequence()->push_back(dofs_array);
237 dofs_array->reserve(count_dofs);
238 miit = dofs_cols.get<0>().begin();
239 for (; miit != hi_miit; miit++) {
240 if (!(*miit)->getActive()) {
241 continue;
242 }
243 dofs_array->emplace_back(*miit);
244 dofs_array->back().dofIdx = problem_ptr->nbDofsCol++;
245 }
246 auto hint = problem_ptr->numeredColDofsPtr->end();
247 for (auto &v : *dofs_array) {
248 hint = problem_ptr->numeredColDofsPtr->emplace_hint(hint, dofs_array, &v);
249 }
250 } else {
251 problem_ptr->numeredColDofsPtr = problem_ptr->numeredRowDofsPtr;
252 problem_ptr->nbLocDofsCol = problem_ptr->nbLocDofsRow;
253 problem_ptr->nbDofsCol = problem_ptr->nbDofsRow;
254 }
255
256 // job done, some debugging and postprocessing
257 if (verb >= VERBOSE) {
258 MOFEM_LOG("SYNC", Sev::verbose)
259 << problem_ptr->getName() << " Nb. local dofs "
260 << problem_ptr->numeredRowDofsPtr->size() << " by "
261 << problem_ptr->numeredColDofsPtr->size();
262 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
263 }
264
265 if (verb >= NOISY) {
266 MOFEM_LOG("SYNC", Sev::noisy)
267 << "FEs row dofs " << *problem_ptr << " Nb. row dof "
268 << problem_ptr->getNbDofsRow();
269 for (auto &miit : *problem_ptr->numeredRowDofsPtr)
270 MOFEM_LOG("SYNC", Sev::noisy) << *miit;
271
272 MOFEM_LOG("SYNC", Sev::noisy)
273 << "FEs col dofs " << *problem_ptr << " Nb. col dof "
274 << problem_ptr->getNbDofsCol();
275 for (auto &miit : *problem_ptr->numeredColDofsPtr)
276 MOFEM_LOG("SYNC", Sev::noisy) << *miit;
277 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
278 }
279
280 cOre.getBuildMoFEM() |= Core::BUILD_PROBLEM; // It is assumed that user who
281 // uses this function knows
282 // what he is doing
283
284 PetscLogEventEnd(MOFEM_EVENT_ProblemsManager, 0, 0, 0, 0);
285
287}
288
290 const std::string name, const bool square_matrix, int verb) {
291 MoFEM::Interface &m_field = cOre;
293
295 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
296 if (!((cOre.getBuildMoFEM()) & Core::BUILD_FE))
297 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
299 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
300
301 const Problem *problem_ptr;
302 CHKERR m_field.get_problem(name, &problem_ptr);
303 CHKERR buildProblemOnDistributedMesh(const_cast<Problem *>(problem_ptr),
304 square_matrix, verb);
305
308
310}
311
313 Problem *problem_ptr, const bool square_matrix, int verb) {
314 MoFEM::Interface &m_field = cOre;
315 auto fields_ptr = m_field.get_fields();
316 auto fe_ptr = m_field.get_finite_elements();
317 auto dofs_field_ptr = m_field.get_dofs();
319 PetscLogEventBegin(MOFEM_EVENT_ProblemsManager, 0, 0, 0, 0);
320
321 // clear data structures
322 CHKERR m_field.clear_problem(problem_ptr->getName());
323
325
326 if (problem_ptr->getBitRefLevel().none())
327 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_FOUND,
328 "problem <%s> refinement level not set",
329 problem_ptr->getName().c_str());
330
331 int loop_size = 2;
332 if (square_matrix) {
333 loop_size = 1;
334 problem_ptr->numeredColDofsPtr = problem_ptr->numeredRowDofsPtr;
335 } else if (problem_ptr->numeredColDofsPtr == problem_ptr->numeredRowDofsPtr) {
336 problem_ptr->numeredColDofsPtr =
337 boost::shared_ptr<NumeredDofEntity_multiIndex>(
339 }
340
341 const BitRefLevel &prb_bit = problem_ptr->getBitRefLevel();
342 const BitRefLevel &prb_mask = problem_ptr->getBitRefLevelMask();
343
344 // // get rows and cols dofs view based on data on elements
345 DofEntity_multiIndex_active_view dofs_rows, dofs_cols;
346
347 // Add DOFs to problem by visiting all elements and adding DOFs from
348 // elements to the problem
349 if (buildProblemFromFields == PETSC_FALSE) {
350
351 auto make_rows_and_cols_view = [&](auto &dofs_rows, auto &dofs_cols) {
352 auto ents_field_ptr = m_field.get_field_ents();
353 auto adjacencies_ptr = m_field.get_ents_elements_adjacency();
355 for (auto it = ents_field_ptr->begin(); it != ents_field_ptr->end();
356 ++it) {
357
358 const auto uid = (*it)->getLocalUniqueId();
359
360 auto r = adjacencies_ptr->get<Unique_mi_tag>().equal_range(uid);
361 for (auto lo = r.first; lo != r.second; ++lo) {
362
363 if ((lo->getBitFEId() & problem_ptr->getBitFEId()).any()) {
364 std::array<bool, 2> row_col = {false, false};
365
366 const BitRefLevel &fe_bit = lo->entFePtr->getBitRefLevel();
367
368 // if entity is not problem refinement level
369 if ((fe_bit & prb_bit).any() && (fe_bit & prb_mask) == fe_bit) {
370
371 auto add_to_view = [&](auto dofs, auto &view, auto rc) {
372 auto dit = dofs->lower_bound(uid);
373 decltype(dit) hi_dit;
374 if (dit != dofs->end()) {
375 hi_dit = dofs->upper_bound(
376 uid | static_cast<UId>(MAX_DOFS_ON_ENTITY - 1));
377 view.insert(dit, hi_dit);
378 row_col[rc] = true;
379 }
380 };
381
382 if ((lo->entFePtr->getBitFieldIdRow() & (*it)->getId()).any())
383 add_to_view(dofs_field_ptr, dofs_rows, ROW);
384
385 if (!square_matrix)
386 if ((lo->entFePtr->getBitFieldIdCol() & (*it)->getId()).any())
387 add_to_view(dofs_field_ptr, dofs_cols, COL);
388
389 if (square_matrix && row_col[ROW])
390 break;
391 else if (row_col[ROW] && row_col[COL])
392 break;
393 }
394 }
395 }
396 }
398 };
399
400 CHKERR make_rows_and_cols_view(dofs_rows, dofs_cols);
401 }
402
403 // Add DOFS to the problem by searching all the filedes, and adding to
404 // problem owned or shared DOFs
405 if (buildProblemFromFields == PETSC_TRUE) {
406 // Get fields IDs on elements
407 BitFieldId fields_ids_row, fields_ids_col;
408 for (auto fit = fe_ptr->begin(); fit != fe_ptr->end(); fit++) {
409 if ((fit->get()->getId() & problem_ptr->getBitFEId()).any()) {
410 fields_ids_row |= fit->get()->getBitFieldIdRow();
411 fields_ids_col |= fit->get()->getBitFieldIdCol();
412 }
413 }
414 // Get fields DOFs
415 for (auto fit = fields_ptr->begin(); fit != fields_ptr->end(); fit++) {
416 if ((fit->get()->getId() & (fields_ids_row | fields_ids_col)).any()) {
417
418 auto dit = dofs_field_ptr->get<Unique_mi_tag>().lower_bound(
419 FieldEntity::getLoBitNumberUId((*fit)->getBitNumber()));
420 auto hi_dit = dofs_field_ptr->get<Unique_mi_tag>().upper_bound(
421 FieldEntity::getHiBitNumberUId((*fit)->getBitNumber()));
422
423 for (; dit != hi_dit; dit++) {
424
425 const int owner_proc = dit->get()->getOwnerProc();
426 if (owner_proc != m_field.get_comm_rank()) {
427 const unsigned char pstatus = dit->get()->getPStatus();
428 if (pstatus == 0) {
429 continue;
430 }
431 }
432
433 const auto &dof_bit = (*dit)->getBitRefLevel();
434 // if entity is not problem refinement level
435 if ((dof_bit & prb_bit).any() && (dof_bit & prb_mask) == dof_bit) {
436
437 if ((fit->get()->getId() & fields_ids_row).any()) {
438 dofs_rows.insert(*dit);
439 }
440 if (!square_matrix) {
441 if ((fit->get()->getId() & fields_ids_col).any()) {
442 dofs_cols.insert(*dit);
443 }
444 }
445 }
446 }
447 }
448 }
449 }
450
452 // Get fields IDs on elements
453 BitFieldId fields_ids_row, fields_ids_col;
454 BitFieldId *fields_ids[2] = {&fields_ids_row, &fields_ids_col};
455 for (FiniteElement_multiIndex::iterator fit = fe_ptr->begin();
456 fit != fe_ptr->end(); fit++) {
457 if ((fit->get()->getId() & problem_ptr->getBitFEId()).any()) {
458 fields_ids_row |= fit->get()->getBitFieldIdRow();
459 fields_ids_col |= fit->get()->getBitFieldIdCol();
460 }
461 }
462
463 DofEntity_multiIndex_active_view *dofs_ptr[] = {&dofs_rows, &dofs_cols};
464 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ++ss) {
465 DofEntity_multiIndex_active_view::nth_index<1>::type::iterator miit,
466 hi_miit;
467 miit = dofs_ptr[ss]->get<1>().lower_bound(1);
468 hi_miit = dofs_ptr[ss]->get<1>().upper_bound(1);
469 Range ents_to_synchronise;
470 for (; miit != hi_miit; ++miit) {
471 if (miit->get()->getEntDofIdx() != 0)
472 continue;
473 ents_to_synchronise.insert(miit->get()->getEnt());
474 }
475 Range tmp_ents = ents_to_synchronise;
476 CHKERR m_field.getInterface<CommInterface>()->synchroniseEntities(
477 ents_to_synchronise, nullptr, verb);
478 ents_to_synchronise = subtract(ents_to_synchronise, tmp_ents);
479 for (auto fit = fields_ptr->begin(); fit != fields_ptr->end(); fit++) {
480 if ((fit->get()->getId() & *fields_ids[ss]).any()) {
481 const auto bit_number = (*fit)->getBitNumber();
482 for (Range::pair_iterator pit = ents_to_synchronise.pair_begin();
483 pit != ents_to_synchronise.pair_end(); ++pit) {
484 const auto f = pit->first;
485 const auto s = pit->second;
486 const auto lo_uid =
488 const auto hi_uid =
490
491 auto dit = dofs_field_ptr->get<Unique_mi_tag>().lower_bound(lo_uid);
492 auto hi_dit =
493 dofs_field_ptr->get<Unique_mi_tag>().upper_bound(hi_uid);
494
495 dofs_ptr[ss]->insert(dit, hi_dit);
496 }
497 }
498 }
499 }
500 }
501
502 // add dofs for rows and cols and set ownership
503 DofEntity_multiIndex_active_view *dofs_ptr[] = {&dofs_rows, &dofs_cols};
504 boost::shared_ptr<NumeredDofEntity_multiIndex> numered_dofs_ptr[] = {
505 problem_ptr->numeredRowDofsPtr, problem_ptr->numeredColDofsPtr};
506 int *nbdof_ptr[] = {&problem_ptr->nbDofsRow, &problem_ptr->nbDofsCol};
507 int *local_nbdof_ptr[] = {&problem_ptr->nbLocDofsRow,
508 &problem_ptr->nbLocDofsCol};
509 int *ghost_nbdof_ptr[] = {&problem_ptr->nbGhostDofsRow,
510 &problem_ptr->nbGhostDofsCol};
511 for (int ss = 0; ss < 2; ss++) {
512 *(nbdof_ptr[ss]) = 0;
513 *(local_nbdof_ptr[ss]) = 0;
514 *(ghost_nbdof_ptr[ss]) = 0;
515 }
516
517 // Loop over dofs on rows and columns and add to multi-indices in dofs
518 // problem structure, set partition for each dof
519 int nb_local_dofs[] = {0, 0};
520 for (int ss = 0; ss < loop_size; ss++) {
521 DofEntity_multiIndex_active_view::nth_index<1>::type::iterator miit,
522 hi_miit;
523 miit = dofs_ptr[ss]->get<1>().lower_bound(1);
524 hi_miit = dofs_ptr[ss]->get<1>().upper_bound(1);
525 for (; miit != hi_miit; miit++) {
526 int owner_proc = (*miit)->getOwnerProc();
527 if (owner_proc == m_field.get_comm_rank()) {
528 nb_local_dofs[ss]++;
529 }
530 }
531 }
532
533 // get layout
534 int start_ranges[2], end_ranges[2];
535 for (int ss = 0; ss != loop_size; ss++) {
536 PetscLayout layout;
537 CHKERR PetscLayoutCreate(m_field.get_comm(), &layout);
538 CHKERR PetscLayoutSetBlockSize(layout, 1);
539 CHKERR PetscLayoutSetLocalSize(layout, nb_local_dofs[ss]);
540 CHKERR PetscLayoutSetUp(layout);
541 CHKERR PetscLayoutGetSize(layout, &*nbdof_ptr[ss]);
542 CHKERR PetscLayoutGetRange(layout, &start_ranges[ss], &end_ranges[ss]);
543 CHKERR PetscLayoutDestroy(&layout);
544 }
545 if (square_matrix) {
546 nbdof_ptr[1] = nbdof_ptr[0];
547 nb_local_dofs[1] = nb_local_dofs[0];
548 start_ranges[1] = start_ranges[0];
549 end_ranges[1] = end_ranges[0];
550 }
551
552 // set local and global indices on own dofs
553 const size_t idx_data_type_size = sizeof(IdxDataType);
554 const size_t data_block_size = idx_data_type_size / sizeof(int);
555
556 if (sizeof(IdxDataType) % sizeof(int)) {
557 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
558 }
559 std::vector<std::vector<IdxDataType>> ids_data_packed_rows(
560 m_field.get_comm_size()),
561 ids_data_packed_cols(m_field.get_comm_size());
562
563 // Loop over dofs on this processor and prepare those dofs to send on
564 // another proc
565 for (int ss = 0; ss != loop_size; ++ss) {
566
567 DofEntity_multiIndex_active_view::nth_index<0>::type::iterator miit,
568 hi_miit;
569 hi_miit = dofs_ptr[ss]->get<0>().end();
570
571 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array =
572 boost::shared_ptr<std::vector<NumeredDofEntity>>(
573 new std::vector<NumeredDofEntity>());
574 int nb_dofs_to_add = 0;
575 miit = dofs_ptr[ss]->get<0>().begin();
576 for (; miit != hi_miit; ++miit) {
577 // Only set global idx for dofs on this processor part
578 if (!(miit->get()->getActive()))
579 continue;
580 ++nb_dofs_to_add;
581 }
582 dofs_array->reserve(nb_dofs_to_add);
583 if (ss == 0) {
584 problem_ptr->getRowDofsSequence()->push_back(dofs_array);
585 } else {
586 problem_ptr->getColDofsSequence()->push_back(dofs_array);
587 }
588
589 int &local_idx = *local_nbdof_ptr[ss];
590 miit = dofs_ptr[ss]->get<0>().begin();
591 for (; miit != hi_miit; ++miit) {
592
593 // Only set global idx for dofs on this processor part
594 if (!(miit->get()->getActive()))
595 continue;
596
597 dofs_array->emplace_back(*miit);
598
599 int owner_proc = dofs_array->back().getOwnerProc();
600 if (owner_proc < 0) {
601 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
602 "data inconsistency");
603 }
604
605 if (owner_proc != m_field.get_comm_rank()) {
606 dofs_array->back().pArt = owner_proc;
607 dofs_array->back().dofIdx = -1;
608 dofs_array->back().petscGloablDofIdx = -1;
609 dofs_array->back().petscLocalDofIdx = -1;
610 } else {
611
612 // Set part and indexes
613 int glob_idx = start_ranges[ss] + local_idx;
614 dofs_array->back().pArt = owner_proc;
615 dofs_array->back().dofIdx = glob_idx;
616 dofs_array->back().petscGloablDofIdx = glob_idx;
617 dofs_array->back().petscLocalDofIdx = local_idx;
618 local_idx++;
619
620 unsigned char pstatus = dofs_array->back().getPStatus();
621 // check id dof is shared, if that is a case global idx added to data
622 // structure and is sended to other processors
623 if (pstatus > 0) {
624
625 for (int proc = 0;
626 proc < MAX_SHARING_PROCS &&
627 -1 != dofs_array->back().getSharingProcsPtr()[proc];
628 proc++) {
629 // make it different for rows and columns when needed
630 if (ss == 0) {
631 ids_data_packed_rows[dofs_array->back()
632 .getSharingProcsPtr()[proc]]
633 .emplace_back(dofs_array->back().getGlobalUniqueId(),
634 glob_idx);
635 } else {
636 ids_data_packed_cols[dofs_array->back()
637 .getSharingProcsPtr()[proc]]
638 .emplace_back(dofs_array->back().getGlobalUniqueId(),
639 glob_idx);
640 }
641 if (!(pstatus & PSTATUS_MULTISHARED)) {
642 break;
643 }
644 }
645 }
646 }
647 }
648
649 auto hint = numered_dofs_ptr[ss]->end();
650 for (auto &v : *dofs_array)
651 hint = numered_dofs_ptr[ss]->emplace_hint(hint, dofs_array, &v);
652 }
653 if (square_matrix) {
654 local_nbdof_ptr[1] = local_nbdof_ptr[0];
655 }
656
657 int nsends_rows = 0, nsends_cols = 0;
658 // Non zero lengths[i] represent a message to i of length lengths[i].
659 std::vector<int> lengths_rows(m_field.get_comm_size()),
660 lengths_cols(m_field.get_comm_size());
661 lengths_rows.clear();
662 lengths_cols.clear();
663 for (int proc = 0; proc < m_field.get_comm_size(); proc++) {
664 lengths_rows[proc] = ids_data_packed_rows[proc].size() * data_block_size;
665 lengths_cols[proc] = ids_data_packed_cols[proc].size() * data_block_size;
666 if (!ids_data_packed_rows[proc].empty())
667 nsends_rows++;
668 if (!ids_data_packed_cols[proc].empty())
669 nsends_cols++;
670 }
671
672 MPI_Status *status;
673 CHKERR PetscMalloc1(m_field.get_comm_size(), &status);
674
675 // Do rows
676 int nrecvs_rows; // number of messages received
677 int *onodes_rows; // list of node-ids from which messages are expected
678 int *olengths_rows; // corresponding message lengths
679 int **rbuf_row; // must bee freed by user
680
681 // make sure it is a PETSc comm
682 MPI_Comm comm;
683 CHKERR PetscCommDuplicate(m_field.get_comm(), &comm, NULL);
684
685 {
686
687 // rows
688
689 // Computes the number of messages a node expects to receive
690 CHKERR PetscGatherNumberOfMessages(comm, NULL, &lengths_rows[0],
691 &nrecvs_rows);
692 // std::cerr << nrecvs_rows << std::endl;
693
694 // Computes info about messages that a MPI-node will receive, including
695 // (from-id,length) pairs for each message.
696 CHKERR PetscGatherMessageLengths(comm, nsends_rows, nrecvs_rows,
697 &lengths_rows[0], &onodes_rows,
698 &olengths_rows);
699
700 // Gets a unique new tag from a PETSc communicator. All processors that
701 // share the communicator MUST call this routine EXACTLY the same number
702 // of times. This tag should only be used with the current objects
703 // communicator; do NOT use it with any other MPI communicator.
704 int tag_row;
705 CHKERR PetscCommGetNewTag(comm, &tag_row);
706
707 // Allocate a buffer sufficient to hold messages of size specified in
708 // olengths. And post Irecvs on these buffers using node info from onodes
709 MPI_Request *r_waits_row; // must bee freed by user
710 // rbuf has a pointers to messeges. It has size of of nrecvs (number of
711 // messages) +1. In the first index a block is allocated,
712 // such that rbuf[i] = rbuf[i-1]+olengths[i-1].
713
714 CHKERR PetscPostIrecvInt(comm, tag_row, nrecvs_rows, onodes_rows,
715 olengths_rows, &rbuf_row, &r_waits_row);
716 CHKERR PetscFree(onodes_rows);
717
718 MPI_Request *s_waits_row; // status of sens messages
719 CHKERR PetscMalloc1(nsends_rows, &s_waits_row);
720
721 // Send messeges
722 for (int proc = 0, kk = 0; proc < m_field.get_comm_size(); proc++) {
723 if (!lengths_rows[proc])
724 continue; // no message to send to this proc
725 CHKERR MPI_Isend(&(ids_data_packed_rows[proc])[0], // buffer to send
726 lengths_rows[proc], // message length
727 MPIU_INT, proc, // to proc
728 tag_row, comm, s_waits_row + kk);
729 kk++;
730 }
731
732 if (nrecvs_rows) {
733 CHKERR MPI_Waitall(nrecvs_rows, r_waits_row, status);
734 }
735 if (nsends_rows) {
736 CHKERR MPI_Waitall(nsends_rows, s_waits_row, status);
737 }
738
739 CHKERR PetscFree(r_waits_row);
740 CHKERR PetscFree(s_waits_row);
741 }
742
743 // cols
744 int nrecvs_cols = nrecvs_rows;
745 int *olengths_cols = olengths_rows;
746 PetscInt **rbuf_col = rbuf_row;
747 if (!square_matrix) {
748
749 // Computes the number of messages a node expects to receive
750 CHKERR PetscGatherNumberOfMessages(comm, NULL, &lengths_cols[0],
751 &nrecvs_cols);
752
753 // Computes info about messages that a MPI-node will receive, including
754 // (from-id,length) pairs for each message.
755 int *onodes_cols;
756 CHKERR PetscGatherMessageLengths(comm, nsends_cols, nrecvs_cols,
757 &lengths_cols[0], &onodes_cols,
758 &olengths_cols);
759
760 // Gets a unique new tag from a PETSc communicator.
761 int tag_col;
762 CHKERR PetscCommGetNewTag(comm, &tag_col);
763
764 // Allocate a buffer sufficient to hold messages of size specified in
765 // olengths. And post Irecvs on these buffers using node info from onodes
766 MPI_Request *r_waits_col; // must bee freed by user
767 CHKERR PetscPostIrecvInt(comm, tag_col, nrecvs_cols, onodes_cols,
768 olengths_cols, &rbuf_col, &r_waits_col);
769 CHKERR PetscFree(onodes_cols);
770
771 MPI_Request *s_waits_col; // status of sens messages
772 CHKERR PetscMalloc1(nsends_cols, &s_waits_col);
773
774 // Send messages
775 for (int proc = 0, kk = 0; proc < m_field.get_comm_size(); proc++) {
776 if (!lengths_cols[proc])
777 continue; // no message to send to this proc
778 CHKERR MPI_Isend(&(ids_data_packed_cols[proc])[0], // buffer to send
779 lengths_cols[proc], // message length
780 MPIU_INT, proc, // to proc
781 tag_col, comm, s_waits_col + kk);
782 kk++;
783 }
784
785 if (nrecvs_cols) {
786 CHKERR MPI_Waitall(nrecvs_cols, r_waits_col, status);
787 }
788 if (nsends_cols) {
789 CHKERR MPI_Waitall(nsends_cols, s_waits_col, status);
790 }
791
792 CHKERR PetscFree(r_waits_col);
793 CHKERR PetscFree(s_waits_col);
794 }
795
796 CHKERR PetscCommDestroy(&comm);
797 CHKERR PetscFree(status);
798
799 DofEntity_multiIndex_global_uid_view dofs_glob_uid_view;
800 auto hint = dofs_glob_uid_view.begin();
801 for (auto dof : *m_field.get_dofs())
802 dofs_glob_uid_view.emplace_hint(hint, dof);
803
804 // set values received from other processors
805 for (int ss = 0; ss != loop_size; ++ss) {
806
807 int nrecvs;
808 int *olengths;
809 int **data_procs;
810 if (ss == 0) {
811 nrecvs = nrecvs_rows;
812 olengths = olengths_rows;
813 data_procs = rbuf_row;
814 } else {
815 nrecvs = nrecvs_cols;
816 olengths = olengths_cols;
817 data_procs = rbuf_col;
818 }
819
820 UId uid;
821 for (int kk = 0; kk != nrecvs; ++kk) {
822 int len = olengths[kk];
823 int *data_from_proc = data_procs[kk];
824 for (int dd = 0; dd < len; dd += data_block_size) {
825 uid = IdxDataTypePtr(&data_from_proc[dd]).getUId();
826 auto ddit = dofs_glob_uid_view.find(uid);
827 const auto owner_proc = FieldEntity::getOwnerFromUniqueId(uid);
828
829 if (owner_proc == m_field.get_comm_rank() &&
830 PetscUnlikely(ddit == dofs_glob_uid_view.end())) {
831
832#ifndef NDEBUG
833 auto ents_field_ptr = m_field.get_field_ents();
834 MOFEM_LOG("SELF", Sev::error)
835 << "DOF is shared or multishared between processors. For example "
836 "if order of field on given entity is set in inconsistently, "
837 "has different value on two processor, error such as this is "
838 "triggered";
839
840 MOFEM_LOG("SELF", Sev::error) << "UId " << uid << " is not found";
841 MOFEM_LOG("SELF", Sev::error)
842 << "Problematic UId owner proc is " << owner_proc;
843 const auto uid_handle = FieldEntity::getHandleFromUniqueId(uid);
844 MOFEM_LOG("SELF", Sev::error)
845 << "Problematic UId entity owning processor handle is "
846 << uid_handle << " entity type "
847 << moab::CN::EntityTypeName(type_from_handle(uid_handle));
848 const auto uid_bit_number =
850 MOFEM_LOG("SELF", Sev::error)
851 << "Problematic UId field is "
852 << m_field.get_field_name(
853 field_bit_from_bit_number(uid_bit_number));
854
856 field_view.insert(ents_field_ptr->begin(), ents_field_ptr->end());
857 auto fe_it = field_view.find(FieldEntity::getGlobalUniqueIdCalculate(
858 owner_proc, uid_bit_number, uid_handle));
859 if (fe_it == field_view.end()) {
860 MOFEM_LOG("SELF", Sev::error)
861 << "Also, no field entity in database for given global UId";
862 } else {
863 MOFEM_LOG("SELF", Sev::error) << "Field entity in databse exist "
864 "(but have no DOF wih give UId";
865 MOFEM_LOG("SELF", Sev::error) << **fe_it;
866
867 // Save file with missing entity
868 auto error_file_name =
869 "error_with_missing_entity_" +
870 boost::lexical_cast<std::string>(m_field.get_comm_rank()) +
871 ".vtk";
872 MOFEM_LOG("SELF", Sev::error)
873 << "Look to file < " << error_file_name
874 << " > it contains entity with missing DOF.";
875
876 auto tmp_msh = get_temp_meshset_ptr(m_field.get_moab());
877 const auto local_fe_ent = (*fe_it)->getEnt();
878 CHKERR m_field.get_moab().add_entities(*tmp_msh, &local_fe_ent, 1);
879 CHKERR m_field.get_moab().write_file(error_file_name.c_str(), "VTK",
880 "", tmp_msh->get_ptr(), 1);
881 }
882#endif
883
884 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
885 "DOF with global UId not found (Compile code in Debug to "
886 "learn more about problem");
887 }
888
889 if (PetscUnlikely(ddit == dofs_glob_uid_view.end())) {
890 continue;
891 }
892
893 auto dit = numered_dofs_ptr[ss]->find((*ddit)->getLocalUniqueId());
894
895 if (dit != numered_dofs_ptr[ss]->end()) {
896
897 int global_idx = IdxDataTypePtr(&data_from_proc[dd]).getDofIdx();
898#ifndef NDEBUG
899 if (PetscUnlikely(global_idx < 0))
900 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
901 "received negative dof");
902#endif
903 bool success;
904 success = numered_dofs_ptr[ss]->modify(
905 dit, NumeredDofEntity_mofem_index_change(global_idx));
906
907#ifndef NDEBUG
908 if (PetscUnlikely(!success))
909 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
910 "modification unsuccessful");
911#endif
912 success = numered_dofs_ptr[ss]->modify(
913 dit, NumeredDofEntity_part_and_glob_idx_change((*dit)->getPart(),
914 global_idx));
915#ifndef NDEBUG
916 if (PetscUnlikely(!success))
917 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
918 "modification unsuccessful");
919#endif
920 };
921
922#ifndef NDEBUG
923 if (PetscUnlikely(ddit->get()->getPStatus() == 0)) {
924
925 // Dof is shared on this processor, however there is no element
926 // which have this dof. If DOF is not shared and received from other
927 // processor, but not marked as a shared on other that means that is
928 // data inconstancy and error should be thrown.
929
930 std::ostringstream zz;
931 zz << **ddit << std::endl;
932 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
933 "data inconsistency, dofs is not shared, but received "
934 "from other proc\n"
935 "%s",
936 zz.str().c_str());
937 }
938#endif
939 }
940 }
941 }
942
943 if (square_matrix) {
944 (problem_ptr->nbDofsCol) = (problem_ptr->nbDofsRow);
945 (problem_ptr->nbLocDofsCol) = (problem_ptr->nbLocDofsRow);
946 }
947
948 CHKERR PetscFree(olengths_rows);
949 CHKERR PetscFree(rbuf_row[0]);
950 CHKERR PetscFree(rbuf_row);
951 if (!square_matrix) {
952 CHKERR PetscFree(olengths_cols);
953 CHKERR PetscFree(rbuf_col[0]);
954 CHKERR PetscFree(rbuf_col);
955 }
956
957 if (square_matrix) {
958 if (numered_dofs_ptr[0]->size() != numered_dofs_ptr[1]->size()) {
959 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
960 "data inconsistency for square_matrix %ld!=%ld",
961 numered_dofs_ptr[0]->size(), numered_dofs_ptr[1]->size());
962 }
963 if (problem_ptr->numeredRowDofsPtr != problem_ptr->numeredColDofsPtr) {
964 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
965 "data inconsistency for square_matrix");
966 }
967 }
968
969 CHKERR printPartitionedProblem(problem_ptr, verb);
970 CHKERR debugPartitionedProblem(problem_ptr, verb);
971
972 PetscLogEventEnd(MOFEM_EVENT_ProblemsManager, 0, 0, 0, 0);
973
975}
976
978 const std::string out_name,
979
980 const std::vector<std::string> &fields_row,
981 const std::vector<std::string> &fields_col,
982
983 const std::string main_problem, const bool square_matrix,
984
985 const map<std::string, boost::shared_ptr<Range>> *entityMapRow,
986 const map<std::string, boost::shared_ptr<Range>> *entityMapCol,
987
988 int verb) {
989 MoFEM::Interface &m_field = cOre;
990 auto problems_ptr = m_field.get_problems();
992
993 CHKERR m_field.clear_problem(out_name);
994
995 // get reference to all problems
996 using ProblemByName = decltype(problems_ptr->get<Problem_mi_tag>());
997 auto &problems_by_name =
998 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
999
1000 // get iterators to out problem, i.e. build problem
1001 auto out_problem_it = problems_by_name.find(out_name);
1002 if (out_problem_it == problems_by_name.end()) {
1003 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1004 "subproblem with name < %s > not defined (top tip check spelling)",
1005 out_name.c_str());
1006 }
1007 // get iterator to main problem, i.e. out problem is subproblem of main
1008 // problem
1009 auto main_problem_it = problems_by_name.find(main_problem);
1010 if (main_problem_it == problems_by_name.end()) {
1011 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1012 "problem of subproblem with name < %s > not defined (top tip "
1013 "check spelling)",
1014 main_problem.c_str());
1015 }
1016
1017 // get dofs for row & columns for out problem,
1018 boost::shared_ptr<NumeredDofEntity_multiIndex> out_problem_dofs[] = {
1019 out_problem_it->numeredRowDofsPtr, out_problem_it->numeredColDofsPtr};
1020 // get dofs for row & columns for main problem
1021 boost::shared_ptr<NumeredDofEntity_multiIndex> main_problem_dofs[] = {
1022 main_problem_it->numeredRowDofsPtr, main_problem_it->numeredColDofsPtr};
1023 // get local indices counter
1024 int *nb_local_dofs[] = {&out_problem_it->nbLocDofsRow,
1025 &out_problem_it->nbLocDofsCol};
1026 // get global indices counter
1027 int *nb_dofs[] = {&out_problem_it->nbDofsRow, &out_problem_it->nbDofsCol};
1028
1029 // set number of ghost nodes to zero
1030 {
1031 out_problem_it->nbGhostDofsRow = 0;
1032 out_problem_it->nbGhostDofsCol = 0;
1033 }
1034
1035 // put rows & columns field names in array
1036 std::vector<std::string> fields[] = {fields_row, fields_col};
1037 const map<std::string, boost::shared_ptr<Range>> *entityMap[] = {
1038 entityMapRow, entityMapCol};
1039
1040 // make data structure fos sub-problem data
1041 out_problem_it->subProblemData =
1042 boost::make_shared<Problem::SubProblemData>();
1043
1044 // Loop over rows and columns
1045 for (int ss = 0; ss != (square_matrix ? 1 : 2); ++ss) {
1046
1047 // reset dofs and columns counters
1048 (*nb_local_dofs[ss]) = 0;
1049 (*nb_dofs[ss]) = 0;
1050 // clear arrays
1051 out_problem_dofs[ss]->clear();
1052
1053 // If DOFs are cleared clear finite elements too.
1054 out_problem_it->numeredFiniteElementsPtr->clear();
1055
1056 // get dofs by field name and insert them in out problem multi-indices
1057 for (auto field : fields[ss]) {
1058
1059 // Following reserve memory in sequences, only two allocations are here,
1060 // once for array of objects, next for array of shared pointers
1061
1062 // aliased sequence of pointer is killed with element
1063 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array =
1064 boost::make_shared<std::vector<NumeredDofEntity>>();
1065 // reserve memory for field dofs
1066 if (!ss)
1067 out_problem_it->getRowDofsSequence()->emplace_back(dofs_array);
1068 else
1069 out_problem_it->getColDofsSequence()->emplace_back(dofs_array);
1070
1071 // create elements objects
1072 auto bit_number = m_field.get_field_bit_number(field);
1073
1074 auto add_dit_to_dofs_array = [&](auto &dit) {
1075 if (dit->get()->getPetscGlobalDofIdx() >= 0)
1076 dofs_array->emplace_back(
1077 dit->get()->getDofEntityPtr(), dit->get()->getPetscGlobalDofIdx(),
1078 dit->get()->getPetscGlobalDofIdx(),
1079 dit->get()->getPetscLocalDofIdx(), dit->get()->getPart());
1080 };
1081
1082 auto get_dafult_dof_range = [&]() {
1083 auto dit = main_problem_dofs[ss]->get<Unique_mi_tag>().lower_bound(
1084 FieldEntity::getLoBitNumberUId(bit_number));
1085 auto hi_dit = main_problem_dofs[ss]->get<Unique_mi_tag>().upper_bound(
1086 FieldEntity::getHiBitNumberUId(bit_number));
1087 return std::make_pair(dit, hi_dit);
1088 };
1089
1090 auto check = [&](auto &field) -> boost::shared_ptr<Range> {
1091 if (entityMap[ss]) {
1092 auto mit = entityMap[ss]->find(field);
1093 if (mit != entityMap[ss]->end()) {
1094 return mit->second;
1095 } else {
1096 return nullptr;
1097 }
1098 } else {
1099 return nullptr;
1100 }
1101 };
1102
1103 if (auto r_ptr = check(field)) {
1104 for (auto p = r_ptr->pair_begin(); p != r_ptr->pair_end(); ++p) {
1105 const auto lo_ent = p->first;
1106 const auto hi_ent = p->second;
1107 auto dit = main_problem_dofs[ss]->get<Unique_mi_tag>().lower_bound(
1108 DofEntity::getLoFieldEntityUId(bit_number, lo_ent));
1109 auto hi_dit = main_problem_dofs[ss]->get<Unique_mi_tag>().upper_bound(
1110 DofEntity::getHiFieldEntityUId(bit_number, hi_ent));
1111 dofs_array->reserve(std::distance(dit, hi_dit));
1112 for (; dit != hi_dit; dit++) {
1113 add_dit_to_dofs_array(dit);
1114 }
1115 }
1116 } else {
1117 auto [dit, hi_dit] = get_dafult_dof_range();
1118 dofs_array->reserve(std::distance(dit, hi_dit));
1119 for (; dit != hi_dit; dit++)
1120 add_dit_to_dofs_array(dit);
1121 }
1122
1123 // fill multi-index
1124 auto hint = out_problem_dofs[ss]->end();
1125 for (auto &v : *dofs_array)
1126 hint = out_problem_dofs[ss]->emplace_hint(hint, dofs_array, &v);
1127 }
1128 // Set local indexes
1129 {
1130 auto dit = out_problem_dofs[ss]->get<Idx_mi_tag>().begin();
1131 auto hi_dit = out_problem_dofs[ss]->get<Idx_mi_tag>().end();
1132 for (; dit != hi_dit; dit++) {
1133 int idx = -1; // if dof is not part of partition, set local index to -1
1134 if (dit->get()->getPart() == (unsigned int)m_field.get_comm_rank()) {
1135 idx = (*nb_local_dofs[ss])++;
1136 }
1137 bool success = out_problem_dofs[ss]->modify(
1138 out_problem_dofs[ss]->project<0>(dit),
1140 if (!success) {
1141 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1142 "operation unsuccessful");
1143 }
1144 };
1145 }
1146 // Set global indexes, compress global indices
1147 {
1148 auto dit =
1149 out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().lower_bound(0);
1150 auto hi_dit =
1151 out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().upper_bound(
1152 out_problem_dofs[ss]->size());
1153 const int nb = std::distance(dit, hi_dit);
1154 // get main problem global indices
1155 std::vector<int> main_indices(nb);
1156 for (auto it = main_indices.begin(); dit != hi_dit; dit++, it++) {
1157 *it = dit->get()->getPetscGlobalDofIdx();
1158 }
1159 // create is with global dofs
1160 IS is;
1161 CHKERR ISCreateGeneral(m_field.get_comm(), nb, &*main_indices.begin(),
1162 PETSC_USE_POINTER, &is);
1163 // create map form main problem global indices to out problem global
1164 // indices
1165 AO ao;
1166 CHKERR AOCreateMappingIS(is, PETSC_NULLPTR, &ao);
1167 if (ss == 0) {
1168 IS is_dup;
1169 CHKERR ISDuplicate(is, &is_dup);
1170 out_problem_it->getSubData()->rowIs = SmartPetscObj<IS>(is_dup, false);
1171 out_problem_it->getSubData()->rowMap = SmartPetscObj<AO>(ao, true);
1172 } else {
1173 IS is_dup;
1174 CHKERR ISDuplicate(is, &is_dup);
1175 out_problem_it->getSubData()->colIs = SmartPetscObj<IS>(is_dup, false);
1176 out_problem_it->getSubData()->colMap = SmartPetscObj<AO>(ao, true);
1177 }
1178 CHKERR AOApplicationToPetscIS(ao, is);
1179 // set global number of DOFs
1180 CHKERR ISGetSize(is, nb_dofs[ss]);
1181 CHKERR ISDestroy(&is);
1182 // set out problem global indices after applying map
1183 dit = out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().lower_bound(0);
1184 for (std::vector<int>::iterator it = main_indices.begin(); dit != hi_dit;
1185 dit++, it++) {
1186 bool success = out_problem_dofs[ss]->modify(
1187 out_problem_dofs[ss]->project<0>(dit),
1189 dit->get()->getPart(), *it, *it,
1190 dit->get()->getPetscLocalDofIdx()));
1191 if (!success) {
1192 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1193 "operation unsuccessful");
1194 }
1195 }
1196 // set global indices to nodes not on this part
1197 {
1198 NumeredDofEntityByLocalIdx::iterator dit =
1199 out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().lower_bound(-1);
1200 NumeredDofEntityByLocalIdx::iterator hi_dit =
1201 out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().upper_bound(-1);
1202 const int nb = std::distance(dit, hi_dit);
1203 std::vector<int> main_indices_non_local(nb);
1204 for (auto it = main_indices_non_local.begin(); dit != hi_dit;
1205 dit++, it++) {
1206 *it = dit->get()->getPetscGlobalDofIdx();
1207 }
1208 IS is;
1209 CHKERR ISCreateGeneral(m_field.get_comm(), nb,
1210 &*main_indices_non_local.begin(),
1211 PETSC_USE_POINTER, &is);
1212 CHKERR AOApplicationToPetscIS(ao, is);
1213 CHKERR ISDestroy(&is);
1214 dit = out_problem_dofs[ss]->get<PetscLocalIdx_mi_tag>().lower_bound(-1);
1215 for (auto it = main_indices_non_local.begin(); dit != hi_dit;
1216 dit++, it++) {
1217 bool success = out_problem_dofs[ss]->modify(
1218 out_problem_dofs[ss]->project<0>(dit),
1220 dit->get()->getPart(), dit->get()->getDofIdx(), *it,
1221 dit->get()->getPetscLocalDofIdx()));
1222 if (!success) {
1223 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1224 "operation unsuccessful");
1225 }
1226 }
1227 }
1228 CHKERR AODestroy(&ao);
1229 }
1230 }
1231
1232 if (square_matrix) {
1233 out_problem_it->numeredColDofsPtr = out_problem_it->numeredRowDofsPtr;
1234 out_problem_it->nbLocDofsCol = out_problem_it->nbLocDofsRow;
1235 out_problem_it->nbDofsCol = out_problem_it->nbDofsRow;
1236 out_problem_it->getSubData()->colIs = out_problem_it->getSubData()->rowIs;
1237 out_problem_it->getSubData()->colMap = out_problem_it->getSubData()->rowMap;
1238 }
1239
1240 CHKERR printPartitionedProblem(&*out_problem_it, verb);
1241 CHKERR debugPartitionedProblem(&*out_problem_it, verb);
1242
1244}
1245
1247 const std::string out_name, const std::vector<std::string> add_row_problems,
1248 const std::vector<std::string> add_col_problems, const bool square_matrix,
1249 int verb) {
1251 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
1253 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
1255 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
1256 MoFEM::Interface &m_field = cOre;
1257 auto problems_ptr = m_field.get_problems();
1259
1260 CHKERR m_field.clear_problem(out_name);
1261 // get reference to all problems
1262 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemByName;
1263 ProblemByName &problems_by_name =
1264 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
1265
1266 // Get iterators to out problem, i.e. build problem
1267 ProblemByName::iterator out_problem_it = problems_by_name.find(out_name);
1268 if (out_problem_it == problems_by_name.end()) {
1269 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1270 "problem with name < %s > not defined (top tip check spelling)",
1271 out_name.c_str());
1272 }
1273 // Make data structure for composed-problem data
1274 out_problem_it->composedProblemsData =
1275 boost::make_shared<ComposedProblemsData>();
1276 boost::shared_ptr<ComposedProblemsData> cmp_prb_data =
1277 out_problem_it->getComposedProblemsData();
1278
1279 const std::vector<std::string> *add_prb[] = {&add_row_problems,
1280 &add_col_problems};
1281 std::vector<const Problem *> *add_prb_ptr[] = {&cmp_prb_data->rowProblemsAdd,
1282 &cmp_prb_data->colProblemsAdd};
1283 std::vector<SmartPetscObj<IS>> *add_prb_is[] = {&cmp_prb_data->rowIs,
1284 &cmp_prb_data->colIs};
1285
1286 // Get local indices counter
1287 int *nb_local_dofs[] = {&out_problem_it->nbLocDofsRow,
1288 &out_problem_it->nbLocDofsCol};
1289 // Get global indices counter
1290 int *nb_dofs[] = {&out_problem_it->nbDofsRow, &out_problem_it->nbDofsCol};
1291
1292 // Set number of ghost nodes to zero
1293 {
1294 out_problem_it->nbDofsRow = 0;
1295 out_problem_it->nbDofsCol = 0;
1296 out_problem_it->nbLocDofsRow = 0;
1297 out_problem_it->nbLocDofsCol = 0;
1298 out_problem_it->nbGhostDofsRow = 0;
1299 out_problem_it->nbGhostDofsCol = 0;
1300 }
1301 int nb_dofs_reserve[] = {0, 0};
1302
1303 // Loop over rows and columns in the main problem and sub-problems
1304 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1305 add_prb_ptr[ss]->reserve(add_prb[ss]->size());
1306 add_prb_is[ss]->reserve(add_prb[ss]->size());
1307 for (std::vector<std::string>::const_iterator vit = add_prb[ss]->begin();
1308 vit != add_prb[ss]->end(); vit++) {
1309 ProblemByName::iterator prb_it = problems_by_name.find(*vit);
1310 if (prb_it == problems_by_name.end()) {
1311 SETERRQ(
1312 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1313 "problem with name < %s > not defined (top tip check spelling)",
1314 vit->c_str());
1315 }
1316 add_prb_ptr[ss]->push_back(&*prb_it);
1317 // set number of dofs on rows and columns
1318 if (ss == 0) {
1319 // row
1320 *nb_dofs[ss] += add_prb_ptr[ss]->back()->getNbDofsRow();
1321 *nb_local_dofs[ss] += add_prb_ptr[ss]->back()->getNbLocalDofsRow();
1322 nb_dofs_reserve[ss] +=
1323 add_prb_ptr[ss]->back()->numeredRowDofsPtr->size();
1324 } else {
1325 // column
1326 *nb_dofs[ss] += add_prb_ptr[ss]->back()->getNbDofsCol();
1327 *nb_local_dofs[ss] += add_prb_ptr[ss]->back()->getNbLocalDofsCol();
1328 nb_dofs_reserve[ss] +=
1329 add_prb_ptr[ss]->back()->numeredColDofsPtr->size();
1330 }
1331 }
1332 }
1333 // if squre problem, rows and columns are the same
1334 if (square_matrix) {
1335 add_prb_ptr[1]->reserve(add_prb_ptr[0]->size());
1336 add_prb_is[1]->reserve(add_prb_ptr[0]->size());
1337 out_problem_it->numeredColDofsPtr = out_problem_it->numeredRowDofsPtr;
1338 *nb_dofs[1] = *nb_dofs[0];
1339 *nb_local_dofs[1] = *nb_local_dofs[0];
1340 }
1341
1342 // reserve memory for dofs
1343 boost::shared_ptr<std::vector<NumeredDofEntity>> dofs_array[2];
1344 // Reserve memory
1345 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1346 dofs_array[ss] = boost::make_shared<std::vector<NumeredDofEntity>>();
1347 dofs_array[ss]->reserve(nb_dofs_reserve[ss]);
1348 if (!ss)
1349 out_problem_it->getRowDofsSequence()->emplace_back(dofs_array[ss]);
1350 else
1351 out_problem_it->getColDofsSequence()->emplace_back(dofs_array[ss]);
1352 }
1353
1354 // Push back DOFs
1355 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1356 NumeredDofEntity_multiIndex::index<PetscGlobalIdx_mi_tag>::type::iterator
1357 dit,
1358 hi_dit;
1359 int shift_glob = 0;
1360 int shift_loc = 0;
1361 for (unsigned int pp = 0; pp != add_prb_ptr[ss]->size(); pp++) {
1362 PetscInt *dofs_out_idx_ptr;
1363 int nb_local_dofs = (*add_prb_ptr[ss])[pp]->getNbLocalDofsRow();
1364 CHKERR PetscMalloc(nb_local_dofs * sizeof(int), &dofs_out_idx_ptr);
1365 if (ss == 0) {
1366 dit = (*add_prb_ptr[ss])[pp]
1367 ->numeredRowDofsPtr->get<PetscGlobalIdx_mi_tag>()
1368 .begin();
1369 hi_dit = (*add_prb_ptr[ss])[pp]
1370 ->numeredRowDofsPtr->get<PetscGlobalIdx_mi_tag>()
1371 .end();
1372 } else {
1373 dit = (*add_prb_ptr[ss])[pp]
1374 ->numeredColDofsPtr->get<PetscGlobalIdx_mi_tag>()
1375 .begin();
1376 hi_dit = (*add_prb_ptr[ss])[pp]
1377 ->numeredColDofsPtr->get<PetscGlobalIdx_mi_tag>()
1378 .end();
1379 }
1380 int is_nb = 0;
1381 for (; dit != hi_dit; dit++) {
1382 const BitRefLevel &prb_bit = out_problem_it->getBitRefLevel();
1383 const BitRefLevel &prb_mask = out_problem_it->getBitRefLevelMask();
1384 const BitRefLevel &dof_bit = dit->get()->getBitRefLevel();
1385 if ((dof_bit & prb_bit).none() || ((dof_bit & prb_mask) != dof_bit))
1386 continue;
1387 const int rank = m_field.get_comm_rank();
1388 const int part = dit->get()->getPart();
1389 const int glob_idx = shift_glob + dit->get()->getPetscGlobalDofIdx();
1390 const int loc_idx =
1391 (part == rank) ? (shift_loc + dit->get()->getPetscLocalDofIdx())
1392 : -1;
1393 dofs_array[ss]->emplace_back(dit->get()->getDofEntityPtr(), glob_idx,
1394 glob_idx, loc_idx, part);
1395 if (part == rank) {
1396 dofs_out_idx_ptr[is_nb++] = glob_idx;
1397 }
1398 }
1399 if (is_nb > nb_local_dofs) {
1400 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
1401 "Data inconsistency");
1402 }
1403 IS is;
1404 CHKERR ISCreateGeneral(m_field.get_comm(), is_nb, dofs_out_idx_ptr,
1405 PETSC_OWN_POINTER, &is);
1406 auto smart_is = SmartPetscObj<IS>(is);
1407 (*add_prb_is[ss]).push_back(smart_is);
1408 if (ss == 0) {
1409 shift_glob += (*add_prb_ptr[ss])[pp]->getNbDofsRow();
1410 shift_loc += (*add_prb_ptr[ss])[pp]->getNbLocalDofsRow();
1411 } else {
1412 shift_glob += (*add_prb_ptr[ss])[pp]->getNbDofsCol();
1413 shift_loc += (*add_prb_ptr[ss])[pp]->getNbLocalDofsCol();
1414 }
1415 if (square_matrix) {
1416 (*add_prb_ptr[1]).push_back((*add_prb_ptr[0])[pp]);
1417 (*add_prb_is[1]).push_back(smart_is);
1418 }
1419 }
1420 }
1421
1422 if ((*add_prb_is[1]).size() != (*add_prb_is[0]).size()) {
1423 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "Data inconsistency");
1424 }
1425
1426 // Insert DOFs to problem multi-index
1427 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1428 auto hint = (ss == 0) ? out_problem_it->numeredRowDofsPtr->end()
1429 : out_problem_it->numeredColDofsPtr->end();
1430 for (auto &v : *dofs_array[ss])
1431 hint = (ss == 0) ? out_problem_it->numeredRowDofsPtr->emplace_hint(
1432 hint, dofs_array[ss], &v)
1433 : out_problem_it->numeredColDofsPtr->emplace_hint(
1434 hint, dofs_array[ss], &v);
1435 }
1436
1437 // Compress DOFs
1438 *nb_dofs[0] = 0;
1439 *nb_dofs[1] = 0;
1440 *nb_local_dofs[0] = 0;
1441 *nb_local_dofs[1] = 0;
1442 for (int ss = 0; ss != ((square_matrix) ? 1 : 2); ss++) {
1443
1444 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs_ptr;
1445 if (ss == 0) {
1446 dofs_ptr = out_problem_it->numeredRowDofsPtr;
1447 } else {
1448 dofs_ptr = out_problem_it->numeredColDofsPtr;
1449 }
1450 NumeredDofEntityByUId::iterator dit, hi_dit;
1451 dit = dofs_ptr->get<Unique_mi_tag>().begin();
1452 hi_dit = dofs_ptr->get<Unique_mi_tag>().end();
1453 std::vector<int> idx;
1454 idx.reserve(std::distance(dit, hi_dit));
1455 // set dofs in order entity and dof number on entity
1456 for (; dit != hi_dit; dit++) {
1457 if (dit->get()->getPart() == (unsigned int)m_field.get_comm_rank()) {
1458 bool success = dofs_ptr->get<Unique_mi_tag>().modify(
1459 dit, NumeredDofEntity_local_idx_change((*nb_local_dofs[ss])++));
1460 if (!success) {
1461 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
1462 "modification unsuccessful");
1463 }
1464 idx.push_back(dit->get()->getPetscGlobalDofIdx());
1465 } else {
1466 if (dit->get()->getPetscLocalDofIdx() != -1) {
1467 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
1468 "local index should be negative");
1469 }
1470 }
1471 }
1472 if (square_matrix) {
1473 *nb_local_dofs[1] = *nb_local_dofs[0];
1474 }
1475
1476 // set new dofs mapping
1477 IS is;
1478 CHKERR ISCreateGeneral(m_field.get_comm(), idx.size(), &*idx.begin(),
1479 PETSC_USE_POINTER, &is);
1480 CHKERR ISGetSize(is, nb_dofs[ss]);
1481 if (square_matrix) {
1482 *nb_dofs[1] = *nb_dofs[0];
1483 }
1484
1485 AO ao;
1486 CHKERR AOCreateMappingIS(is, PETSC_NULLPTR, &ao);
1487 for (unsigned int pp = 0; pp != (*add_prb_is[ss]).size(); pp++)
1488 CHKERR AOApplicationToPetscIS(ao, (*add_prb_is[ss])[pp]);
1489
1490 // Set DOFs numeration
1491 {
1492 std::vector<int> idx_new;
1493 idx_new.reserve(dofs_ptr->size());
1494 for (NumeredDofEntityByUId::iterator dit =
1495 dofs_ptr->get<Unique_mi_tag>().begin();
1496 dit != dofs_ptr->get<Unique_mi_tag>().end(); dit++) {
1497 idx_new.push_back(dit->get()->getPetscGlobalDofIdx());
1498 }
1499 // set new global dofs numeration
1500 IS is_new;
1501 CHKERR ISCreateGeneral(m_field.get_comm(), idx_new.size(),
1502 &*idx_new.begin(), PETSC_USE_POINTER, &is_new);
1503 CHKERR AOApplicationToPetscIS(ao, is_new);
1504 // set global indices to multi-index
1505 std::vector<int>::iterator vit = idx_new.begin();
1506 for (NumeredDofEntityByUId::iterator dit =
1507 dofs_ptr->get<Unique_mi_tag>().begin();
1508 dit != dofs_ptr->get<Unique_mi_tag>().end(); dit++) {
1509 bool success =
1510 dofs_ptr->modify(dit, NumeredDofEntity_part_and_glob_idx_change(
1511 dit->get()->getPart(), *(vit++)));
1512 if (!success) {
1513 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
1514 "modification unsuccessful");
1515 }
1516 }
1517 CHKERR ISDestroy(&is_new);
1518 }
1519 CHKERR ISDestroy(&is);
1520 CHKERR AODestroy(&ao);
1521 }
1522
1523 CHKERR printPartitionedProblem(&*out_problem_it, verb);
1524 CHKERR debugPartitionedProblem(&*out_problem_it, verb);
1525
1526 // Inidcate that porble has been build
1529
1531}
1532
1534 int verb) {
1535
1536 MoFEM::Interface &m_field = cOre;
1537 auto problems_ptr = m_field.get_problems();
1539
1541 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
1543 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
1545 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
1547 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "adjacencies not build");
1548 MOFEM_LOG("WORLD", Sev::verbose) << "Simple partition problem " << name;
1549
1550 // find p_miit
1551 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemByName;
1552 ProblemByName &problems_set =
1553 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
1554 ProblemByName::iterator p_miit = problems_set.find(name);
1555 if (p_miit == problems_set.end()) {
1556 SETERRQ(PETSC_COMM_SELF, 1,
1557 "problem < %s > is not found (top tip: check spelling)",
1558 name.c_str());
1559 }
1560 typedef boost::multi_index::index<NumeredDofEntity_multiIndex,
1561 Idx_mi_tag>::type NumeredDofEntitysByIdx;
1562 NumeredDofEntitysByIdx &dofs_row_by_idx =
1563 p_miit->numeredRowDofsPtr->get<Idx_mi_tag>();
1564 NumeredDofEntitysByIdx &dofs_col_by_idx =
1565 p_miit->numeredColDofsPtr->get<Idx_mi_tag>();
1566 boost::multi_index::index<NumeredDofEntity_multiIndex,
1567 Idx_mi_tag>::type::iterator miit_row,
1568 hi_miit_row;
1569 boost::multi_index::index<NumeredDofEntity_multiIndex,
1570 Idx_mi_tag>::type::iterator miit_col,
1571 hi_miit_col;
1572 DofIdx &nb_row_local_dofs = p_miit->nbLocDofsRow;
1573 DofIdx &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
1574 nb_row_local_dofs = 0;
1575 nb_row_ghost_dofs = 0;
1576 DofIdx &nb_col_local_dofs = p_miit->nbLocDofsCol;
1577 DofIdx &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
1578 nb_col_local_dofs = 0;
1579 nb_col_ghost_dofs = 0;
1580
1581 bool square_matrix = false;
1582 if (p_miit->numeredRowDofsPtr == p_miit->numeredColDofsPtr) {
1583 square_matrix = true;
1584 }
1585
1586 // get row range of local indices
1587 PetscLayout layout_row;
1588 const int *ranges_row;
1589
1590 DofIdx nb_dofs_row = dofs_row_by_idx.size();
1591 CHKERR PetscLayoutCreate(m_field.get_comm(), &layout_row);
1592 CHKERR PetscLayoutSetBlockSize(layout_row, 1);
1593 CHKERR PetscLayoutSetSize(layout_row, nb_dofs_row);
1594 CHKERR PetscLayoutSetUp(layout_row);
1595 CHKERR PetscLayoutGetRanges(layout_row, &ranges_row);
1596 // get col range of local indices
1597 PetscLayout layout_col;
1598 const int *ranges_col;
1599 if (!square_matrix) {
1600 DofIdx nb_dofs_col = dofs_col_by_idx.size();
1601 CHKERR PetscLayoutCreate(m_field.get_comm(), &layout_col);
1602 CHKERR PetscLayoutSetBlockSize(layout_col, 1);
1603 CHKERR PetscLayoutSetSize(layout_col, nb_dofs_col);
1604 CHKERR PetscLayoutSetUp(layout_col);
1605 CHKERR PetscLayoutGetRanges(layout_col, &ranges_col);
1606 }
1607 for (unsigned int part = 0; part < (unsigned int)m_field.get_comm_size();
1608 part++) {
1609 miit_row = dofs_row_by_idx.lower_bound(ranges_row[part]);
1610 hi_miit_row = dofs_row_by_idx.lower_bound(ranges_row[part + 1]);
1611 if (std::distance(miit_row, hi_miit_row) !=
1612 ranges_row[part + 1] - ranges_row[part]) {
1613 SETERRQ(
1614 PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1615 "data inconsistency, std::distance(miit_row,hi_miit_row) != rend - "
1616 "rstart (%ld != %d - %d = %d) ",
1617 std::distance(miit_row, hi_miit_row), ranges_row[part + 1],
1618 ranges_row[part], ranges_row[part + 1] - ranges_row[part]);
1619 }
1620 // loop rows
1621 for (; miit_row != hi_miit_row; miit_row++) {
1622 bool success = dofs_row_by_idx.modify(
1623 miit_row,
1624 NumeredDofEntity_part_and_glob_idx_change(part, (*miit_row)->dofIdx));
1625 if (!success)
1626 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1627 "modification unsuccessful");
1628 if (part == (unsigned int)m_field.get_comm_rank()) {
1629 success = dofs_row_by_idx.modify(
1630 miit_row, NumeredDofEntity_local_idx_change(nb_row_local_dofs++));
1631 if (!success)
1632 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1633 "modification unsuccessful");
1634 }
1635 }
1636 if (!square_matrix) {
1637 miit_col = dofs_col_by_idx.lower_bound(ranges_col[part]);
1638 hi_miit_col = dofs_col_by_idx.lower_bound(ranges_col[part + 1]);
1639 if (std::distance(miit_col, hi_miit_col) !=
1640 ranges_col[part + 1] - ranges_col[part]) {
1641 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1642 "data inconsistency, std::distance(miit_col,hi_miit_col) != "
1643 "rend - "
1644 "rstart (%ld != %d - %d = %d) ",
1645 std::distance(miit_col, hi_miit_col), ranges_col[part + 1],
1646 ranges_col[part], ranges_col[part + 1] - ranges_col[part]);
1647 }
1648 // loop cols
1649 for (; miit_col != hi_miit_col; miit_col++) {
1650 bool success = dofs_col_by_idx.modify(
1652 part, (*miit_col)->dofIdx));
1653 if (!success)
1654 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1655 "modification unsuccessful");
1656 if (part == (unsigned int)m_field.get_comm_rank()) {
1657 success = dofs_col_by_idx.modify(
1658 miit_col, NumeredDofEntity_local_idx_change(nb_col_local_dofs++));
1659 if (!success)
1660 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1661 "modification unsuccessful");
1662 }
1663 }
1664 }
1665 }
1666 CHKERR PetscLayoutDestroy(&layout_row);
1667 if (!square_matrix) {
1668 CHKERR PetscLayoutDestroy(&layout_col);
1669 }
1670 if (square_matrix) {
1671 nb_col_local_dofs = nb_row_local_dofs;
1672 nb_col_ghost_dofs = nb_row_ghost_dofs;
1673 }
1674 CHKERR printPartitionedProblem(&*p_miit, verb);
1677}
1678
1680 int verb) {
1681 MoFEM::Interface &m_field = cOre;
1682 auto problems_ptr = m_field.get_problems();
1684
1685 MOFEM_LOG("WORLD", Sev::noisy) << "Partition problem " << name;
1686
1687 using NumeredDofEntitysByIdx =
1688 NumeredDofEntity_multiIndex::index<Idx_mi_tag>::type;
1689 using ProblemsByName = Problem_multiIndex::index<Problem_mi_tag>::type;
1690
1691 // Find problem pointer by name
1692 auto &problems_set =
1693 const_cast<ProblemsByName &>(problems_ptr->get<Problem_mi_tag>());
1694 auto p_miit = problems_set.find(name);
1695 if (p_miit == problems_set.end()) {
1696 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
1697 "problem with name %s not defined (top tip check spelling)",
1698 name.c_str());
1699 }
1700 int nb_dofs_row = p_miit->getNbDofsRow();
1701
1702 if (m_field.get_comm_size() != 1) {
1703
1704 if (!(cOre.getBuildMoFEM() & (1 << 0)))
1705 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "fields not build");
1706 if (!(cOre.getBuildMoFEM() & (1 << 1)))
1707 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "FEs not build");
1708 if (!(cOre.getBuildMoFEM() & (1 << 2)))
1709 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1710 "entFEAdjacencies not build");
1711 if (!(cOre.getBuildMoFEM() & (1 << 3)))
1712 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Problems not build");
1713
1714 Mat Adj;
1716 ->createMPIAdjWithArrays<Idx_mi_tag>(name, &Adj, verb);
1717
1718 int m, n;
1719 CHKERR MatGetSize(Adj, &m, &n);
1720 if (verb > VERY_VERBOSE)
1721 MatView(Adj, PETSC_VIEWER_STDOUT_WORLD);
1722
1723 // partitioning
1724 MatPartitioning part;
1725 IS is;
1726 CHKERR MatPartitioningCreate(m_field.get_comm(), &part);
1727 CHKERR MatPartitioningSetAdjacency(part, Adj);
1728 CHKERR MatPartitioningSetFromOptions(part);
1729 CHKERR MatPartitioningSetNParts(part, m_field.get_comm_size());
1730 CHKERR MatPartitioningApply(part, &is);
1731 if (verb > VERY_VERBOSE)
1732 ISView(is, PETSC_VIEWER_STDOUT_WORLD);
1733
1734 // gather
1735 IS is_gather, is_num, is_gather_num;
1736 CHKERR ISAllGather(is, &is_gather);
1737 CHKERR ISPartitioningToNumbering(is, &is_num);
1738 CHKERR ISAllGather(is_num, &is_gather_num);
1739 const int *part_number, *petsc_idx;
1740 CHKERR ISGetIndices(is_gather, &part_number);
1741 CHKERR ISGetIndices(is_gather_num, &petsc_idx);
1742 int size_is_num, size_is_gather;
1743 CHKERR ISGetSize(is_gather, &size_is_gather);
1744 if (size_is_gather != (int)nb_dofs_row)
1745 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1746 "data inconsistency %d != %d", size_is_gather, nb_dofs_row);
1747
1748 CHKERR ISGetSize(is_num, &size_is_num);
1749 if (size_is_num != (int)nb_dofs_row)
1750 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1751 "data inconsistency %d != %d", size_is_num, nb_dofs_row);
1752
1753 bool square_matrix = false;
1754 if (p_miit->numeredRowDofsPtr == p_miit->numeredColDofsPtr)
1755 square_matrix = true;
1756
1757 // if (!square_matrix) {
1758 // // FIXME: This is for back compatibility, if deprecate interface
1759 // function
1760 // // build interfaces is removed, this part of the code will be obsolete
1761 // auto mit_row = p_miit->numeredRowDofsPtr->get<Idx_mi_tag>().begin();
1762 // auto hi_mit_row = p_miit->numeredRowDofsPtr->get<Idx_mi_tag>().end();
1763 // auto mit_col = p_miit->numeredColDofsPtr->get<Idx_mi_tag>().begin();
1764 // auto hi_mit_col = p_miit->numeredColDofsPtr->get<Idx_mi_tag>().end();
1765 // for (; mit_row != hi_mit_row; mit_row++, mit_col++) {
1766 // if (mit_col == hi_mit_col) {
1767 // SETERRQ(
1768 // PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1769 // "check finite element definition, nb. of rows is not equal to "
1770 // "number for columns");
1771 // }
1772 // if (mit_row->get()->getLocalUniqueId() !=
1773 // mit_col->get()->getLocalUniqueId()) {
1774 // SETERRQ(
1775 // PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1776 // "check finite element definition, nb. of rows is not equal to "
1777 // "number for columns");
1778 // }
1779 // }
1780 // }
1781
1782 auto number_dofs = [&](auto &dofs_idx, auto &counter) {
1784 for (auto miit_dofs_row = dofs_idx.begin();
1785 miit_dofs_row != dofs_idx.end(); miit_dofs_row++) {
1786 const int part = part_number[(*miit_dofs_row)->dofIdx];
1787 if (part == (unsigned int)m_field.get_comm_rank()) {
1788 const bool success = dofs_idx.modify(
1789 miit_dofs_row,
1791 part, petsc_idx[(*miit_dofs_row)->dofIdx], counter++));
1792 if (!success) {
1793 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1794 "modification unsuccessful");
1795 }
1796 } else {
1797 const bool success = dofs_idx.modify(
1799 part, petsc_idx[(*miit_dofs_row)->dofIdx]));
1800 if (!success) {
1801 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1802 "modification unsuccessful");
1803 }
1804 }
1805 }
1807 };
1808
1809 // Set petsc global indices
1810 auto &dofs_row_by_idx_no_const = const_cast<NumeredDofEntitysByIdx &>(
1811 p_miit->numeredRowDofsPtr->get<Idx_mi_tag>());
1812 int &nb_row_local_dofs = p_miit->nbLocDofsRow;
1813 int &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
1814 nb_row_local_dofs = 0;
1815 nb_row_ghost_dofs = 0;
1816
1817 CHKERR number_dofs(dofs_row_by_idx_no_const, nb_row_local_dofs);
1818
1819 int &nb_col_local_dofs = p_miit->nbLocDofsCol;
1820 int &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
1821 if (square_matrix) {
1822 nb_col_local_dofs = nb_row_local_dofs;
1823 nb_col_ghost_dofs = nb_row_ghost_dofs;
1824 } else {
1825 NumeredDofEntitysByIdx &dofs_col_by_idx_no_const =
1826 const_cast<NumeredDofEntitysByIdx &>(
1827 p_miit->numeredColDofsPtr->get<Idx_mi_tag>());
1828 nb_col_local_dofs = 0;
1829 nb_col_ghost_dofs = 0;
1830 CHKERR number_dofs(dofs_col_by_idx_no_const, nb_col_local_dofs);
1831 }
1832
1833 CHKERR ISRestoreIndices(is_gather, &part_number);
1834 CHKERR ISRestoreIndices(is_gather_num, &petsc_idx);
1835 CHKERR ISDestroy(&is_num);
1836 CHKERR ISDestroy(&is_gather_num);
1837 CHKERR ISDestroy(&is_gather);
1838 CHKERR ISDestroy(&is);
1839 CHKERR MatPartitioningDestroy(&part);
1840 CHKERR MatDestroy(&Adj);
1841 CHKERR printPartitionedProblem(&*p_miit, verb);
1842 } else {
1843
1844 auto number_dofs = [&](auto &dof_idx, auto &counter) {
1846 for (auto miit_dofs_row = dof_idx.begin(); miit_dofs_row != dof_idx.end();
1847 miit_dofs_row++) {
1848 const bool success = dof_idx.modify(
1849 miit_dofs_row,
1850 NumeredDofEntity_part_and_indices_change(0, counter, counter));
1851 ++counter;
1852 if (!success) {
1853 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1854 "modification unsuccessful");
1855 }
1856 }
1858 };
1859
1860 auto &dofs_row_by_idx_no_const = const_cast<NumeredDofEntitysByIdx &>(
1861 p_miit->numeredRowDofsPtr->get<Idx_mi_tag>());
1862 int &nb_row_local_dofs = p_miit->nbLocDofsRow;
1863 int &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
1864 nb_row_local_dofs = 0;
1865 nb_row_ghost_dofs = 0;
1866
1867 CHKERR number_dofs(dofs_row_by_idx_no_const, nb_row_local_dofs);
1868
1869 bool square_matrix = false;
1870 if (p_miit->numeredRowDofsPtr == p_miit->numeredColDofsPtr)
1871 square_matrix = true;
1872
1873 int &nb_col_local_dofs = p_miit->nbLocDofsCol;
1874 int &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
1875 if (square_matrix) {
1876 nb_col_local_dofs = nb_row_local_dofs;
1877 nb_col_ghost_dofs = nb_row_ghost_dofs;
1878 } else {
1879 NumeredDofEntitysByIdx &dofs_col_by_idx_no_const =
1880 const_cast<NumeredDofEntitysByIdx &>(
1881 p_miit->numeredColDofsPtr->get<Idx_mi_tag>());
1882 nb_col_local_dofs = 0;
1883 nb_col_ghost_dofs = 0;
1884 CHKERR number_dofs(dofs_col_by_idx_no_const, nb_col_local_dofs);
1885 }
1886 }
1887
1888 cOre.getBuildMoFEM() |= 1 << 4;
1890}
1891
1893 const std::string name, const std::string problem_for_rows, bool copy_rows,
1894 const std::string problem_for_cols, bool copy_cols, int verb) {
1895 MoFEM::Interface &m_field = cOre;
1896 auto problems_ptr = m_field.get_problems();
1898
1900 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "pRoblems not build");
1901
1902 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemByName;
1903
1904 // find p_miit
1905 ProblemByName &problems_by_name =
1906 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
1907 ProblemByName::iterator p_miit = problems_by_name.find(name);
1908 if (p_miit == problems_by_name.end()) {
1909 SETERRQ(m_field.get_comm(), MOFEM_NOT_FOUND,
1910 "problem with name < %s > not defined (top tip check spelling)",
1911 name.c_str());
1912 }
1913 if (verb > QUIET)
1914 MOFEM_LOG("WORLD", Sev::inform)
1915 << p_miit->getName() << " from rows of " << problem_for_rows
1916 << " and columns of " << problem_for_cols;
1917
1918 // find p_miit_row
1919 ProblemByName::iterator p_miit_row = problems_by_name.find(problem_for_rows);
1920 if (p_miit_row == problems_by_name.end()) {
1921 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
1922 "problem with name < %s > not defined (top tip check spelling)",
1923 problem_for_rows.c_str());
1924 }
1925 const boost::shared_ptr<NumeredDofEntity_multiIndex> dofs_row =
1926 p_miit_row->numeredRowDofsPtr;
1927
1928 // find p_mit_col
1929 ProblemByName::iterator p_miit_col = problems_by_name.find(problem_for_cols);
1930 if (p_miit_col == problems_by_name.end()) {
1931 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
1932 "problem with name < %s > not defined (top tip check spelling)",
1933 problem_for_cols.c_str());
1934 }
1935 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs_col =
1936 p_miit_col->numeredColDofsPtr;
1937
1938 bool copy[] = {copy_rows, copy_cols};
1939 boost::shared_ptr<NumeredDofEntity_multiIndex> composed_dofs[] = {
1940 p_miit->numeredRowDofsPtr, p_miit->numeredColDofsPtr};
1941
1942 int *nb_local_dofs[] = {&p_miit->nbLocDofsRow, &p_miit->nbLocDofsCol};
1943 int *nb_dofs[] = {&p_miit->nbDofsRow, &p_miit->nbDofsCol};
1944 boost::shared_ptr<NumeredDofEntity_multiIndex> copied_dofs[] = {dofs_row,
1945 dofs_col};
1946
1947 for (int ss = 0; ss < 2; ss++) {
1948
1949 // build indices
1950 *nb_local_dofs[ss] = 0;
1951 if (!copy[ss]) {
1952
1953 // only copy indices which are belong to some elements if this problem
1954 std::vector<int> is_local, is_new;
1955
1956 NumeredDofEntityByUId &dofs_by_uid =
1957 copied_dofs[ss]->get<Unique_mi_tag>();
1958 for (NumeredDofEntity_multiIndex::iterator dit =
1959 composed_dofs[ss]->begin();
1960 dit != composed_dofs[ss]->end(); dit++) {
1961 NumeredDofEntityByUId::iterator diit =
1962 dofs_by_uid.find((*dit)->getLocalUniqueId());
1963 if (diit == dofs_by_uid.end()) {
1964 SETERRQ(
1966 "data inconsistency, could not find dof in composite problem");
1967 }
1968 int part_number = (*diit)->getPart(); // get part number
1969 int petsc_global_dof = (*diit)->getPetscGlobalDofIdx();
1970 bool success;
1971 success = composed_dofs[ss]->modify(
1973 petsc_global_dof));
1974 if (!success) {
1975 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
1976 "modification unsuccessful");
1977 }
1978 if ((*dit)->getPart() == (unsigned int)m_field.get_comm_rank()) {
1979 success = composed_dofs[ss]->modify(
1980 dit, NumeredDofEntity_local_idx_change((*nb_local_dofs[ss])++));
1981 if (!success) {
1982 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
1983 "modification unsuccessful");
1984 }
1985 is_local.push_back(petsc_global_dof);
1986 }
1987 }
1988
1989 AO ao;
1990 CHKERR AOCreateMapping(m_field.get_comm(), is_local.size(), &is_local[0],
1991 NULL, &ao);
1992
1993 // apply local to global mapping
1994 is_local.resize(0);
1995 for (NumeredDofEntity_multiIndex::iterator dit =
1996 composed_dofs[ss]->begin();
1997 dit != composed_dofs[ss]->end(); dit++) {
1998 is_local.push_back((*dit)->getPetscGlobalDofIdx());
1999 }
2000 CHKERR AOPetscToApplication(ao, is_local.size(), &is_local[0]);
2001 int idx2 = 0;
2002 for (NumeredDofEntity_multiIndex::iterator dit =
2003 composed_dofs[ss]->begin();
2004 dit != composed_dofs[ss]->end(); dit++) {
2005 int part_number = (*dit)->getPart(); // get part number
2006 int petsc_global_dof = is_local[idx2++];
2007 bool success;
2008 success = composed_dofs[ss]->modify(
2010 petsc_global_dof));
2011 if (!success) {
2012 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2013 "modification unsuccessful");
2014 }
2015 }
2016
2017 CHKERR AODestroy(&ao);
2018
2019 } else {
2020
2021 for (NumeredDofEntity_multiIndex::iterator dit = copied_dofs[ss]->begin();
2022 dit != copied_dofs[ss]->end(); dit++) {
2023 std::pair<NumeredDofEntity_multiIndex::iterator, bool> p;
2024 p = composed_dofs[ss]->insert(boost::shared_ptr<NumeredDofEntity>(
2025 new NumeredDofEntity((*dit)->getDofEntityPtr())));
2026 if (p.second) {
2027 (*nb_dofs[ss])++;
2028 }
2029 int dof_idx = (*dit)->getDofIdx();
2030 int part_number = (*dit)->getPart(); // get part number
2031 int petsc_global_dof = (*dit)->getPetscGlobalDofIdx();
2032 if (part_number == (unsigned int)m_field.get_comm_rank()) {
2033 const bool success = composed_dofs[ss]->modify(
2035 part_number, dof_idx, petsc_global_dof,
2036 (*nb_local_dofs[ss])++));
2037 if (!success) {
2038 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2039 "modification unsuccessful");
2040 }
2041 } else {
2042 const bool success = composed_dofs[ss]->modify(
2044 part_number, dof_idx, petsc_global_dof));
2045 if (!success) {
2046 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2047 "modification unsuccessful");
2048 }
2049 }
2050 }
2051 }
2052 }
2053
2054 CHKERR printPartitionedProblem(&*p_miit, verb);
2055 CHKERR debugPartitionedProblem(&*p_miit, verb);
2056
2058}
2059
2062 MoFEM::Interface &m_field = cOre;
2064
2065 if (verb > QUIET) {
2066
2067 MOFEM_LOG("SYNC", Sev::inform)
2068 << problem_ptr->getName() << " Nb. local dof "
2069 << problem_ptr->getNbLocalDofsRow() << " by "
2070 << problem_ptr->getNbLocalDofsCol() << " nb global dofs "
2071 << problem_ptr->getNbDofsRow() << " by " << problem_ptr->getNbDofsCol();
2072
2074 }
2075
2077}
2078
2081 MoFEM::Interface &m_field = cOre;
2083
2084 auto save_ent = [](moab::Interface &moab, const std::string name,
2085 const EntityHandle ent) {
2087 EntityHandle out_meshset;
2088 CHKERR moab.create_meshset(MESHSET_SET, out_meshset);
2089 CHKERR moab.add_entities(out_meshset, &ent, 1);
2090 CHKERR moab.write_file(name.c_str(), "VTK", "", &out_meshset, 1);
2091 CHKERR moab.delete_entities(&out_meshset, 1);
2093 };
2094
2095 if (debug > 0) {
2096
2097 typedef NumeredDofEntity_multiIndex::index<Idx_mi_tag>::type
2098 NumeredDofEntitysByIdx;
2099 NumeredDofEntitysByIdx::iterator dit, hi_dit;
2100 const NumeredDofEntitysByIdx *numered_dofs_ptr[] = {
2101 &(problem_ptr->numeredRowDofsPtr->get<Idx_mi_tag>()),
2102 &(problem_ptr->numeredColDofsPtr->get<Idx_mi_tag>())};
2103
2104 int *nbdof_ptr[] = {&problem_ptr->nbDofsRow, &problem_ptr->nbDofsCol};
2105 int *local_nbdof_ptr[] = {&problem_ptr->nbLocDofsRow,
2106 &problem_ptr->nbLocDofsCol};
2107
2108 for (int ss = 0; ss < 2; ss++) {
2109
2110 dit = numered_dofs_ptr[ss]->begin();
2111 hi_dit = numered_dofs_ptr[ss]->end();
2112 for (; dit != hi_dit; dit++) {
2113 if ((*dit)->getPart() == (unsigned int)m_field.get_comm_rank()) {
2114 if ((*dit)->getPetscLocalDofIdx() < 0) {
2115 std::ostringstream zz;
2116 zz << "rank " << m_field.get_comm_rank() << " " << **dit;
2117 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
2118 "local dof index for %d (0-row, 1-col) not set, i.e. has "
2119 "negative value\n %s",
2120 ss, zz.str().c_str());
2121 }
2122 if ((*dit)->getPetscLocalDofIdx() >= *local_nbdof_ptr[ss]) {
2123 std::ostringstream zz;
2124 zz << "rank " << m_field.get_comm_rank() << " " << **dit;
2125 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
2126 "local dofs for %d (0-row, 1-col) out of range\n %s", ss,
2127 zz.str().c_str());
2128 }
2129 } else {
2130 if ((*dit)->getPetscGlobalDofIdx() < 0) {
2131
2132 const EntityHandle ent = (*dit)->getEnt();
2133 CHKERR save_ent(
2134 m_field.get_moab(),
2135 "debug_part" +
2136 boost::lexical_cast<std::string>(m_field.get_comm_rank()) +
2137 "_negative_global_index.vtk",
2138 ent);
2139
2140 std::ostringstream zz;
2141 zz << "rank " << m_field.get_comm_rank() << " "
2142 << dit->get()->getBitRefLevel() << " " << **dit;
2143 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
2144 "global dof index for %d (0-row, 1-col) row not set, i.e. "
2145 "has negative value\n %s",
2146 ss, zz.str().c_str());
2147 }
2148 if ((*dit)->getPetscGlobalDofIdx() >= *nbdof_ptr[ss]) {
2149 std::ostringstream zz;
2150 zz << "rank " << m_field.get_comm_rank() << " nb_dofs "
2151 << *nbdof_ptr[ss] << " " << **dit;
2152 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
2153 "global dofs for %d (0-row, 1-col) out of range\n %s", ss,
2154 zz.str().c_str());
2155 }
2156 }
2157 }
2158 }
2159 }
2161}
2162
2164 bool part_from_moab,
2165 int low_proc,
2166 int hi_proc, int verb) {
2167 MoFEM::Interface &m_field = cOre;
2168 auto problems_ptr = m_field.get_problems();
2169 auto fe_ent_ptr = m_field.get_ents_finite_elements();
2171
2173 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "fields not build");
2174
2176 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "FEs not build");
2177
2179 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2180 "adjacencies not build");
2181
2183 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY, "problem not build");
2184
2186 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2187 "problem not partitioned");
2188
2189 if (low_proc == -1)
2190 low_proc = m_field.get_comm_rank();
2191 if (hi_proc == -1)
2192 hi_proc = m_field.get_comm_rank();
2193
2194 // Find pointer to problem of given name
2195 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemByName;
2196 auto &problems =
2197 const_cast<ProblemByName &>(problems_ptr->get<Problem_mi_tag>());
2198 ProblemByName::iterator p_miit = problems.find(name);
2199 if (p_miit == problems.end()) {
2200 SETERRQ(m_field.get_comm(), MOFEM_NOT_FOUND,
2201 "problem < %s > not found (top tip: check spelling)",
2202 name.c_str());
2203 }
2204
2205 // Get reference on finite elements multi-index on the problem
2206 NumeredEntFiniteElement_multiIndex &problem_finite_elements =
2207 *p_miit->numeredFiniteElementsPtr;
2208
2209 // Clear all elements and data, build it again
2210 problem_finite_elements.clear();
2211
2212 // Check if dofs and columns are the same, i.e. structurally symmetric
2213 // problem
2214 bool do_cols_prob = true;
2215 if (p_miit->numeredRowDofsPtr == p_miit->numeredColDofsPtr) {
2216 do_cols_prob = false;
2217 }
2218
2219 auto get_good_elems = [&]() {
2220 auto good_elems = std::vector<decltype(fe_ent_ptr->begin())>();
2221 good_elems.reserve(fe_ent_ptr->size());
2222
2223 const auto prb_bit = p_miit->getBitRefLevel();
2224 const auto prb_mask = p_miit->getBitRefLevelMask();
2225
2226 // Loop over all elements in database and if right element is there add it
2227 // to problem finite element multi-index
2228 for (auto efit = fe_ent_ptr->begin(); efit != fe_ent_ptr->end(); ++efit) {
2229
2230 // if element is not part of problem
2231 if (((*efit)->getId() & p_miit->getBitFEId()).any()) {
2232
2233 const auto &fe_bit = (*efit)->getBitRefLevel();
2234
2235 // if entity is not problem refinement level
2236 if ((fe_bit & prb_mask) == fe_bit && (fe_bit & prb_bit).any())
2237 good_elems.emplace_back(efit);
2238 }
2239 }
2240
2241 return good_elems;
2242 };
2243
2244 auto good_elems = get_good_elems();
2245
2246 auto numbered_good_elems_ptr =
2247 boost::make_shared<std::vector<NumeredEntFiniteElement>>();
2248 numbered_good_elems_ptr->reserve(good_elems.size());
2249 for (auto &efit : good_elems)
2250 numbered_good_elems_ptr->emplace_back(NumeredEntFiniteElement(*efit));
2251
2252 if (!do_cols_prob) {
2253 for (auto &fe : *numbered_good_elems_ptr) {
2254 if (fe.sPtr->getRowFieldEntsPtr() == fe.sPtr->getColFieldEntsPtr()) {
2255 fe.getColFieldEntsPtr() = fe.getRowFieldEntsPtr();
2256 }
2257 }
2258 }
2259
2260 if (part_from_moab) {
2261 for (auto &fe : *numbered_good_elems_ptr) {
2262 // All imported elements belong to rank zero in a serial communicator.
2263 if (m_field.get_comm_size() == 1 || fe.getEntType() == MBENTITYSET) {
2264 fe.part = m_field.get_comm_rank();
2265 } else {
2266 // if partition is taken from moab partition
2267 int proc = fe.getPartProc();
2268 if (proc == -1 && fe.getEntType() == MBVERTEX)
2269 proc = fe.getOwnerProc();
2270 fe.part = proc;
2271 }
2272 }
2273 }
2274
2275 for (auto &fe : *numbered_good_elems_ptr) {
2276
2278 CHKERR fe.sPtr->getRowDofView(*(p_miit->numeredRowDofsPtr), rows_view);
2279
2280 if (!part_from_moab) {
2281 if (fe.getEntType() == MBENTITYSET) {
2282 fe.part = m_field.get_comm_rank();
2283 } else {
2284 std::vector<int> parts(m_field.get_comm_size(), 0);
2285 for (auto &dof_ptr : rows_view)
2286 parts[dof_ptr->pArt]++;
2287 std::vector<int>::iterator pos =
2288 max_element(parts.begin(), parts.end());
2289 const auto max_part = std::distance(parts.begin(), pos);
2290 fe.part = max_part;
2291 }
2292 }
2293 }
2294
2295 for (auto &fe : *numbered_good_elems_ptr) {
2296
2297 auto check_fields_and_dofs = [&]() {
2298 if (!part_from_moab) {
2299 if (fe.getBitFieldIdRow().none() && m_field.get_comm_size() == 0) {
2300 MOFEM_LOG("WORLD", Sev::warning)
2301 << "At least one field has to be added to element row to "
2302 "determine partition of finite element. Check element " +
2303 boost::lexical_cast<std::string>(fe.getName());
2304 }
2305 }
2306
2307 return true;
2308 };
2309
2310 if (check_fields_and_dofs()) {
2311 // Add element to the problem
2312 auto p = problem_finite_elements.insert(
2313 boost::shared_ptr<NumeredEntFiniteElement>(numbered_good_elems_ptr,
2314 &fe));
2315 if (!p.second)
2316 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_FOUND, "element is there");
2317 }
2318 }
2319
2320 if (verb >= VERBOSE) {
2321 auto elements_on_rank =
2322 problem_finite_elements.get<Part_mi_tag>().equal_range(
2323 m_field.get_comm_rank());
2324 MOFEM_LOG("SYNC", Sev::verbose)
2325 << p_miit->getName() << " nb. elems "
2326 << std::distance(elements_on_rank.first, elements_on_rank.second);
2327 auto fe_ptr = m_field.get_finite_elements();
2328 for (auto &fe : *fe_ptr) {
2329 auto e_range =
2330 problem_finite_elements.get<Composite_Name_And_Part_mi_tag>()
2331 .equal_range(
2332 boost::make_tuple(fe->getName(), m_field.get_comm_rank()));
2333 MOFEM_LOG("SYNC", Sev::noisy)
2334 << "Element " << fe->getName() << " nb. elems "
2335 << std::distance(e_range.first, e_range.second);
2336 }
2337
2339 }
2340
2343}
2344
2346 int verb) {
2347 MoFEM::Interface &m_field = cOre;
2348 auto problems_ptr = m_field.get_problems();
2350
2352 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2353 "partition of problem not build");
2355 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2356 "partitions finite elements not build");
2357
2358 // get problem pointer
2359 auto p_miit = problems_ptr->get<Problem_mi_tag>().find(name);
2360 if (p_miit == problems_ptr->get<Problem_mi_tag>().end())
2361 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA, "Problem %s not fond",
2362 name.c_str());
2363
2364 // get reference to number of ghost dofs
2365 int &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
2366 int &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
2367 nb_row_ghost_dofs = 0;
2368 nb_col_ghost_dofs = 0;
2369
2370 // do work if more than one processor
2371 if (m_field.get_comm_size() > 1) {
2372
2374 ghost_idx_col_view;
2375
2376 // get elements on this partition
2377 auto fe_range =
2378 p_miit->numeredFiniteElementsPtr->get<Part_mi_tag>().equal_range(
2379 m_field.get_comm_rank());
2380
2381 // get dofs on elements which are not part of this partition
2382
2383 struct Inserter {
2384 using Vec = std::vector<boost::shared_ptr<NumeredDofEntity>>;
2385 using It = Vec::iterator;
2386 It operator()(Vec &dofs_view, It &hint,
2387 boost::shared_ptr<NumeredDofEntity> &&dof) {
2388 dofs_view.emplace_back(dof);
2389 return dofs_view.end();
2390 }
2391 };
2392
2393 // rows
2394 std::vector<boost::shared_ptr<NumeredDofEntity>> fe_vec_view;
2395 auto hint_r = ghost_idx_row_view.begin();
2396 for (auto fe_ptr = fe_range.first; fe_ptr != fe_range.second; ++fe_ptr) {
2397
2398 fe_vec_view.clear();
2399 CHKERR EntFiniteElement::getDofView((*fe_ptr)->getRowFieldEnts(),
2400 *(p_miit->getNumeredRowDofsPtr()),
2401 fe_vec_view, Inserter());
2402
2403 for (auto &dof_ptr : fe_vec_view) {
2404 if (dof_ptr->getPart() != (unsigned int)m_field.get_comm_rank()) {
2405 hint_r = ghost_idx_row_view.emplace_hint(hint_r, dof_ptr);
2406 }
2407 }
2408 }
2409
2410 // columns
2411 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2412
2413 auto hint_c = ghost_idx_col_view.begin();
2414 for (auto fe_ptr = fe_range.first; fe_ptr != fe_range.second; ++fe_ptr) {
2415
2416 fe_vec_view.clear();
2417 CHKERR EntFiniteElement::getDofView((*fe_ptr)->getColFieldEnts(),
2418 *(p_miit->getNumeredColDofsPtr()),
2419 fe_vec_view, Inserter());
2420
2421 for (auto &dof_ptr : fe_vec_view) {
2422 if (dof_ptr->getPart() != (unsigned int)m_field.get_comm_rank()) {
2423 hint_c = ghost_idx_col_view.emplace_hint(hint_c, dof_ptr);
2424 }
2425 }
2426 }
2427 }
2428
2429 int *nb_ghost_dofs[2] = {&nb_row_ghost_dofs, &nb_col_ghost_dofs};
2430 int nb_local_dofs[2] = {p_miit->nbLocDofsRow, p_miit->nbLocDofsCol};
2431
2433 &ghost_idx_row_view, &ghost_idx_col_view};
2434 NumeredDofEntityByUId *dof_by_uid_no_const[2] = {
2435 &p_miit->numeredRowDofsPtr->get<Unique_mi_tag>(),
2436 &p_miit->numeredColDofsPtr->get<Unique_mi_tag>()};
2437
2438 int loop_size = 2;
2439 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2440 loop_size = 1;
2441 }
2442
2443 // set local ghost dofs indices
2444 for (int ss = 0; ss != loop_size; ++ss) {
2445 for (auto &gid : *ghost_idx_view[ss]) {
2446 NumeredDofEntityByUId::iterator dof =
2447 dof_by_uid_no_const[ss]->find(gid->getLocalUniqueId());
2448 if (PetscUnlikely((*dof)->petscLocalDofIdx != (DofIdx)-1))
2449 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2450 "inconsistent data, ghost dof already set");
2451 bool success = dof_by_uid_no_const[ss]->modify(
2452 dof, NumeredDofEntity_local_idx_change(nb_local_dofs[ss]++));
2453 if (PetscUnlikely(!success))
2454 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2455 "modification unsuccessful");
2456 (*nb_ghost_dofs[ss])++;
2457 }
2458 }
2459 if (loop_size == 1) {
2460 (*nb_ghost_dofs[1]) = (*nb_ghost_dofs[0]);
2461 }
2462 }
2463
2464 if (verb > QUIET) {
2465 MOFEM_LOG("SYNC", Sev::inform)
2466 << " FEs ghost dofs on problem " << p_miit->getName()
2467 << " Nb. ghost dof " << p_miit->getNbGhostDofsRow() << " by "
2468 << p_miit->getNbGhostDofsCol() << " Nb. local dof "
2469 << p_miit->getNbLocalDofsRow() << " by " << p_miit->getNbLocalDofsCol();
2470
2472 }
2473
2476}
2477
2480 int verb) {
2481 MoFEM::Interface &m_field = cOre;
2482 auto problems_ptr = m_field.get_problems();
2484
2486 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2487 "partition of problem not build");
2489 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2490 "partitions finite elements not build");
2491
2492 // get problem pointer
2493 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemsByName;
2494 // find p_miit
2495 ProblemsByName &problems_set =
2496 const_cast<ProblemsByName &>(problems_ptr->get<Problem_mi_tag>());
2497 ProblemsByName::iterator p_miit = problems_set.find(name);
2498
2499 // get reference to number of ghost dofs
2500 // get number of local dofs
2501 DofIdx *nb_ghost_dofs[2] = {&(p_miit->nbGhostDofsRow),
2502 &(p_miit->nbGhostDofsCol)};
2503 DofIdx nb_local_dofs[2] = {p_miit->nbLocDofsRow, p_miit->nbLocDofsCol};
2504 for (int ss = 0; ss != 2; ++ss) {
2505 (*nb_ghost_dofs[ss]) = 0;
2506 }
2507
2508 // do work if more than one processor
2509 if (m_field.get_comm_size() > 1) {
2510 // determine if rows on columns are different from dofs on rows
2511 int loop_size = 2;
2512 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2513 loop_size = 1;
2514 }
2515
2516 typedef decltype(p_miit->numeredRowDofsPtr) NumbDofTypeSharedPtr;
2517 NumbDofTypeSharedPtr numered_dofs[] = {p_miit->numeredRowDofsPtr,
2518 p_miit->numeredColDofsPtr};
2519
2520 // iterate over dofs on rows and dofs on columns
2521 for (int ss = 0; ss != loop_size; ++ss) {
2522
2523 // create dofs view by uid
2524 auto r = numered_dofs[ss]->get<PetscLocalIdx_mi_tag>().equal_range(-1);
2525
2526 std::vector<NumeredDofEntity_multiIndex::iterator> ghost_idx_view;
2527 ghost_idx_view.reserve(std::distance(r.first, r.second));
2528 for (; r.first != r.second; ++r.first)
2529 ghost_idx_view.emplace_back(numered_dofs[ss]->project<0>(r.first));
2530
2531 auto cmp = [](auto a, auto b) {
2532 return (*a)->getLocalUniqueId() < (*b)->getLocalUniqueId();
2533 };
2534 sort(ghost_idx_view.begin(), ghost_idx_view.end(), cmp);
2535
2536 // iterate over dofs which have negative local index
2537 for (auto gid_it : ghost_idx_view) {
2538 bool success = numered_dofs[ss]->modify(
2539 gid_it, NumeredDofEntity_local_idx_change((nb_local_dofs[ss])++));
2540 if (!success)
2541 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
2542 "modification unsuccessful");
2543 ++(*nb_ghost_dofs[ss]);
2544 }
2545 }
2546 if (loop_size == 1) {
2547 (*nb_ghost_dofs[1]) = (*nb_ghost_dofs[0]);
2548 }
2549 }
2550
2551 if (verb > QUIET) {
2552 MOFEM_LOG("SYNC", Sev::inform)
2553 << " FEs ghost dofs on problem " << p_miit->getName()
2554 << " Nb. ghost dof " << p_miit->getNbGhostDofsRow() << " by "
2555 << p_miit->getNbGhostDofsCol() << " Nb. local dof "
2556 << p_miit->getNbLocalDofsRow() << " by " << p_miit->getNbLocalDofsCol();
2557
2559 }
2560
2563}
2564
2566 const std::string &fe_name,
2567 EntityHandle *meshset) const {
2568 MoFEM::Interface &m_field = cOre;
2569 const Problem *problem_ptr;
2570 const FiniteElement_multiIndex *fes_ptr;
2572
2573 CHKERR m_field.get_moab().create_meshset(MESHSET_SET, *meshset);
2574 CHKERR m_field.get_problem(prb_name, &problem_ptr);
2575 CHKERR m_field.get_finite_elements(&fes_ptr);
2576
2577 auto fe_miit = fes_ptr->get<FiniteElement_name_mi_tag>().find(fe_name);
2578 if (fe_miit != fes_ptr->get<FiniteElement_name_mi_tag>().end()) {
2579 auto fit =
2580 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>().lower_bound(
2582 0, (*fe_miit)->getFEUId()));
2583 auto hi_fe_it =
2584 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>().upper_bound(
2586 get_id_for_max_type<MBENTITYSET>(), (*fe_miit)->getFEUId()));
2587 std::vector<EntityHandle> fe_vec;
2588 fe_vec.reserve(std::distance(fit, hi_fe_it));
2589 for (; fit != hi_fe_it; fit++)
2590 fe_vec.push_back(fit->get()->getEnt());
2591 CHKERR m_field.get_moab().add_entities(*meshset, &*fe_vec.begin(),
2592 fe_vec.size());
2593 }
2594
2596}
2597
2600 const std::string &fe_name,
2601 PetscLayout *layout) const {
2602 MoFEM::Interface &m_field = cOre;
2603 const Problem *problem_ptr;
2605 CHKERR m_field.get_problem(name, &problem_ptr);
2606 CHKERR problem_ptr->getNumberOfElementsByNameAndPart(PETSC_COMM_WORLD,
2607 fe_name, layout);
2609}
2610
2612
2613 std::vector<boost::weak_ptr<NumeredDofEntity>> &vec_dof_view,
2614
2615 const std::string problem_name, RowColData rc, const std::string field_name,
2616 const Range ents, int bridge_dim, const int lo_coeff, const int hi_coeff,
2617 const int lo_order, const int hi_order, int verb, const bool debug
2618
2619) const {
2620 MoFEM::Interface &m_field = cOre;
2622
2623 switch (rc) {
2624 case ROW:
2625 case COL:
2626 break;
2627 default:
2628 SETERRQ(m_field.get_comm(), MOFEM_INVALID_DATA, "invalid RowColData");
2629 break;
2630 }
2631
2632 const Problem *prb_ptr;
2633 CHKERR m_field.get_problem(problem_name, &prb_ptr);
2634
2635 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
2636 prb_ptr->numeredRowDofsPtr, nullptr};
2637 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
2638 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
2639
2640 Range bridge_ents;
2641 CHKERR m_field.get_moab().get_adjacencies(
2642 ents, bridge_dim, false, bridge_ents, moab::Interface::UNION);
2643
2644 auto &moab = m_field.get_moab();
2645 const auto bit_number = m_field.get_field_bit_number(field_name);
2646 const auto nb_coeffs =
2648 const auto &side_dof_map = m_field.get_field_structure(field_name)
2649 ->getDofSideMap();
2650
2651 using NumeredDofEntity_it_view_multiIndex = multi_index_container<
2652
2653 NumeredDofEntity_multiIndex::iterator, indexed_by<sequenced<>>
2654
2655 >;
2656 NumeredDofEntity_it_view_multiIndex dofs_it_view;
2657
2658 for (auto pit = bridge_ents.const_pair_begin();
2659 pit != bridge_ents.const_pair_end(); ++pit) {
2660 auto lo = numered_dofs[rc]->get<Unique_mi_tag>().lower_bound(
2661 DofEntity::getLoFieldEntityUId(bit_number, pit->first));
2662 auto hi = numered_dofs[rc]->get<Unique_mi_tag>().upper_bound(
2663 DofEntity::getHiFieldEntityUId(bit_number, pit->second));
2664
2665 auto bride_type = moab.type_from_handle(pit->first);
2666
2667 for (; lo != hi; ++lo) {
2668 if ((*lo)->getDofCoeffIdx() >= lo_coeff &&
2669 (*lo)->getDofCoeffIdx() <= hi_coeff &&
2670 (*lo)->getDofOrder() >= lo_order &&
2671 (*lo)->getDofOrder() <= hi_order) {
2672 auto ent_dof_index = (*lo)->getEntDofIdx();
2673 auto side_it = side_dof_map.at(bride_type)
2674 .get<EntDofIdx_mi_tag>()
2675 .find(std::floor(static_cast<double>(ent_dof_index) /
2676 nb_coeffs));
2677 if (side_it !=
2678 side_dof_map.at(bride_type).get<EntDofIdx_mi_tag>().end()) {
2679 auto bridge_ent = (*lo)->getEnt();
2680 auto type = side_it->type;
2681 auto side = side_it->side;
2682 auto dim = CN::Dimension(type);
2683 EntityHandle side_ent = 0;
2684 CHKERR moab.side_element(bridge_ent, dim, side, side_ent);
2685 if (ents.find(side_ent) != ents.end()) {
2686 dofs_it_view.emplace_back(numered_dofs[rc]->project<0>(lo));
2687 }
2688 } else {
2689#ifndef NDEBUG
2690 MOFEM_LOG("SELF", Sev::error)
2691 << *m_field.get_field_structure(field_name);
2692 MOFEM_LOG("SELF", Sev::error)
2693 << "side not found for entity " << CN::EntityTypeName(bride_type);
2694 MOFEM_LOG("SELF", Sev::error)
2695 << "ent_dof_index / nb_coeffs "
2696 << std::floor(static_cast<double>(ent_dof_index) / nb_coeffs);
2697 MOFEM_LOG("SELF", Sev::error)
2698 << "side_dof_map.size() " << side_dof_map.size();
2699#endif // NDEBUG
2700 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2701 "side not found - you will get more information in debug");
2702 }
2703 }
2704 }
2705 }
2706
2707 if (verb > QUIET) {
2708 for (auto &dof : dofs_it_view)
2709 MOFEM_LOG("SYNC", Sev::noisy) << **dof;
2710 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
2711 }
2712
2713 vec_dof_view.reserve(vec_dof_view.size() + dofs_it_view.size());
2714 for (auto dit : dofs_it_view)
2715 vec_dof_view.push_back(*dit);
2716
2718}
2719
2721 const std::string problem_name, RowColData rc,
2722 std::vector<boost::weak_ptr<NumeredDofEntity>> &vec_dof_view, int verb,
2723 const bool debug) {
2724
2725 MoFEM::Interface &m_field = cOre;
2727
2728 switch (rc) {
2729 case ROW:
2730 case COL:
2731 break;
2732 default:
2733 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Should be row or column");
2734 }
2735
2736 const Problem *prb_ptr;
2737 CHKERR m_field.get_problem(problem_name, &prb_ptr);
2738
2739 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
2740 prb_ptr->numeredRowDofsPtr, nullptr};
2741 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
2742 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
2743
2744 int *nbdof_ptr[] = {&prb_ptr->nbDofsRow, &prb_ptr->nbDofsCol};
2745 int *local_nbdof_ptr[] = {&prb_ptr->nbLocDofsRow, &prb_ptr->nbLocDofsCol};
2746 int *ghost_nbdof_ptr[] = {&prb_ptr->nbGhostDofsRow, &prb_ptr->nbGhostDofsCol};
2747
2748 const int nb_init_row_dofs = prb_ptr->getNbDofsRow();
2749 const int nb_init_col_dofs = prb_ptr->getNbDofsCol();
2750 const int nb_init_loc_row_dofs = prb_ptr->getNbLocalDofsRow();
2751 const int nb_init_ghost_row_dofs = prb_ptr->getNbGhostDofsRow();
2752 const int nb_init_ghost_col_dofs = prb_ptr->getNbGhostDofsCol();
2753
2754 if (numered_dofs[rc]) {
2755
2756 if (verb >= NOISY)
2757 MOFEM_LOG_C("SYNC", Sev::noisy,
2758 "Number of DOFs in multi-index %zu and to delete %zu\n",
2759 numered_dofs[rc]->size(), vec_dof_view.size());
2760
2761 // erase dofs from problem
2762 for (auto weak_dit : vec_dof_view)
2763 if (auto dit = weak_dit.lock()) {
2764 numered_dofs[rc]->erase(dit->getLocalUniqueId());
2765 }
2766
2767 if (verb >= NOISY)
2768 MOFEM_LOG_C("SYNC", Sev::noisy,
2769 "Number of DOFs in multi-index after delete %zu\n",
2770 numered_dofs[rc]->size());
2771
2772 // get current number of ghost dofs
2773 int nb_local_dofs = 0;
2774 int nb_ghost_dofs = 0;
2775 for (auto dit = numered_dofs[rc]->get<PetscLocalIdx_mi_tag>().begin();
2776 dit != numered_dofs[rc]->get<PetscLocalIdx_mi_tag>().end(); ++dit) {
2777 if ((*dit)->getPetscLocalDofIdx() >= 0 &&
2778 (*dit)->getPetscLocalDofIdx() < *(local_nbdof_ptr[rc]))
2779 ++nb_local_dofs;
2780 else if ((*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[rc]))
2781 ++nb_ghost_dofs;
2782 else
2783 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2784 "Impossible case. You could run problem on no distributed "
2785 "mesh. That is not implemented. Dof local index is %d",
2786 (*dit)->getPetscLocalDofIdx());
2787 }
2788
2789 // get indices
2790 auto get_indices_by_tag = [&](auto tag, auto &indices, bool only_local) {
2791 const int nb_dofs = numered_dofs[rc]->size();
2792 indices.clear();
2793 indices.reserve(nb_dofs);
2794 for (auto dit = numered_dofs[rc]->get<decltype(tag)>().begin();
2795 dit != numered_dofs[rc]->get<decltype(tag)>().end(); ++dit) {
2796 bool add = true;
2797 if (only_local) {
2798 if ((*dit)->getPetscLocalDofIdx() < 0 ||
2799 (*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[rc])) {
2800 add = false;
2801 }
2802 }
2803 if (add)
2804 indices.push_back(decltype(tag)::get_index(dit));
2805 }
2806 };
2807
2808 auto get_indices_by_uid = [&](auto tag, auto &indices) {
2809 const int nb_dofs = numered_dofs[rc]->size();
2810 indices.clear();
2811 indices.reserve(nb_dofs);
2812 for (auto dit = numered_dofs[rc]->begin(); dit != numered_dofs[rc]->end();
2813 ++dit)
2814 indices.push_back(decltype(tag)::get_index(dit));
2815 };
2816
2817 auto get_sub_ao = [&](auto sub_data) {
2818 if (rc == 0) {
2819 return sub_data->getSmartRowMap();
2820 } else {
2821 return sub_data->getSmartColMap();
2822 }
2823 };
2824
2825 auto set_sub_is_and_ao = [&rc, &prb_ptr](auto sub_data, auto is, auto ao) {
2826 if (rc == ROW) {
2827 sub_data->rowIs = is;
2828 sub_data->rowMap = ao;
2829 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
2830 sub_data->colIs = is;
2831 sub_data->colMap = ao;
2832 }
2833 } else {
2834 sub_data->colIs = is;
2835 sub_data->colMap = ao;
2836 }
2837 };
2838
2839 auto apply_symmetry = [&rc, &prb_ptr](auto sub_data) {
2840 if (rc == ROW) {
2841 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
2842 sub_data->colIs = sub_data->getSmartRowIs();
2843 sub_data->colMap = sub_data->getSmartRowMap();
2844 }
2845 }
2846 };
2847
2848 auto concatenate_dofs = [&](auto tag, auto &indices,
2849 const auto local_only) {
2851 get_indices_by_tag(tag, indices, local_only);
2852
2853 auto indices_ptr = [](auto &indices) {
2854 return indices.empty() ? nullptr : indices.data();
2855 };
2856
2858 // Create AO from app indices (i.e. old), to pestc indices (new after
2859 // remove)
2860 if (local_only)
2861 ao = createAOMapping(m_field.get_comm(), indices.size(),
2862 indices_ptr(indices), PETSC_NULLPTR);
2863 else
2864 ao = createAOMapping(PETSC_COMM_SELF, indices.size(),
2865 indices_ptr(indices), PETSC_NULLPTR);
2866
2867 // Set mapping to sub dm data
2868 if (local_only) {
2869 if (auto sub_data = prb_ptr->getSubData()) {
2870 // create is and then map it to main problem of sub-problem
2871 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
2872 indices_ptr(indices), PETSC_COPY_VALUES);
2873 // get old app, i.e. oroginal befor sub indices, and ao, from app,
2874 // to petsc sub indices.
2875 auto sub_ao = get_sub_ao(sub_data);
2876 if (sub_ao.get()) {
2877 CHKERR AOPetscToApplicationIS(sub_ao, sub_is);
2878 sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
2879 } else {
2880 sub_ao = ao;
2881 }
2882 // set new sub ao
2883 set_sub_is_and_ao(sub_data, sub_is, sub_ao);
2884 apply_symmetry(sub_data);
2885 } else {
2886 // create sub data
2887 prb_ptr->getSubData() = boost::make_shared<Problem::SubProblemData>();
2888 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
2889 indices_ptr(indices), PETSC_COPY_VALUES);
2890 // set sub is ao
2891 set_sub_is_and_ao(prb_ptr->getSubData(), sub_is, ao);
2892 apply_symmetry(prb_ptr->getSubData());
2893 }
2894 }
2895
2896 get_indices_by_uid(tag, indices);
2897 CHKERR AOApplicationToPetsc(ao, indices.size(), indices_ptr(indices));
2898
2900 };
2901
2902 // set indices index
2903 auto set_concatenated_indices = [&]() {
2904 std::vector<int> global_indices;
2905 std::vector<int> local_indices;
2907 CHKERR concatenate_dofs(PetscGlobalIdx_mi_tag(), global_indices, true);
2908 CHKERR concatenate_dofs(PetscLocalIdx_mi_tag(), local_indices, false);
2909 auto gi = global_indices.begin();
2910 auto li = local_indices.begin();
2911 for (auto dit = numered_dofs[rc]->begin(); dit != numered_dofs[rc]->end();
2912 ++dit) {
2914 (*dit)->getPart(), (*dit)->getDofIdx(), *gi, *li);
2915 bool success = numered_dofs[rc]->modify(dit, mod);
2916 if (!success)
2917 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
2918 "can not set negative indices");
2919 ++gi;
2920 ++li;
2921 }
2923 };
2924 CHKERR set_concatenated_indices();
2925
2926 MPI_Allreduce(&nb_local_dofs, nbdof_ptr[rc], 1, MPI_INT, MPI_SUM,
2927 m_field.get_comm());
2928 *(local_nbdof_ptr[rc]) = nb_local_dofs;
2929 *(ghost_nbdof_ptr[rc]) = nb_ghost_dofs;
2930
2931 if (debug)
2932 for (auto dof : (*numered_dofs[rc])) {
2933 if (dof->getPetscGlobalDofIdx() < 0) {
2934 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2935 "Negative global idx");
2936 }
2937 if (dof->getPetscLocalDofIdx() < 0) {
2938 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2939 "Negative local idx");
2940 }
2941 }
2942
2943 } else {
2944
2945 *(nbdof_ptr[1]) = *(nbdof_ptr[0]);
2946 *(local_nbdof_ptr[1]) = *(local_nbdof_ptr[0]);
2947 *(ghost_nbdof_ptr[1]) = *(ghost_nbdof_ptr[0]);
2948 }
2949
2950 if (verb > QUIET) {
2952 "WORLD", Sev::inform,
2953 "Removed DOFs from problem %s dofs [%d / %d (before %d / %d) global]",
2954 prb_ptr->getName().c_str(), prb_ptr->getNbDofsRow(),
2955 prb_ptr->getNbDofsCol(), nb_init_row_dofs, nb_init_col_dofs);
2956 MOFEM_LOG_C("SYNC", Sev::verbose,
2957 "Removed DOFs from problem %s dofs [ %d / %d "
2958 "(before %d / %d) local, %d / %d (before %d / %d)]",
2959 prb_ptr->getName().c_str(), prb_ptr->getNbLocalDofsRow(),
2960 prb_ptr->getNbLocalDofsCol(), nb_init_loc_row_dofs,
2961 nb_init_loc_row_dofs, prb_ptr->getNbGhostDofsRow(),
2962 prb_ptr->getNbGhostDofsCol(), nb_init_ghost_row_dofs,
2963 nb_init_ghost_col_dofs);
2964 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
2965 }
2966
2968}
2969
2971 const std::string problem_name, const std::string field_name,
2972 const Range ents, const int lo_coeff, const int hi_coeff,
2973 const int lo_order, const int hi_order, int verb, const bool debug) {
2974
2975 MoFEM::Interface &m_field = cOre;
2977
2978 const Problem *prb_ptr;
2979 CHKERR m_field.get_problem(problem_name, &prb_ptr);
2980
2981 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
2982 prb_ptr->numeredRowDofsPtr, nullptr};
2983 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
2984 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
2985
2986 int *nbdof_ptr[] = {&prb_ptr->nbDofsRow, &prb_ptr->nbDofsCol};
2987 int *local_nbdof_ptr[] = {&prb_ptr->nbLocDofsRow, &prb_ptr->nbLocDofsCol};
2988 int *ghost_nbdof_ptr[] = {&prb_ptr->nbGhostDofsRow, &prb_ptr->nbGhostDofsCol};
2989
2990 const int nb_init_row_dofs = prb_ptr->getNbDofsRow();
2991 const int nb_init_col_dofs = prb_ptr->getNbDofsCol();
2992 const int nb_init_loc_row_dofs = prb_ptr->getNbLocalDofsRow();
2993 const int nb_init_loc_col_dofs = prb_ptr->getNbLocalDofsCol();
2994 const int nb_init_ghost_row_dofs = prb_ptr->getNbGhostDofsRow();
2995 const int nb_init_ghost_col_dofs = prb_ptr->getNbGhostDofsCol();
2996
2997 for (int s = 0; s != 2; ++s)
2998 if (numered_dofs[s]) {
2999
3000 using NumeredDofEntity_it_view_multiIndex = multi_index_container<
3001
3002 NumeredDofEntity_multiIndex::iterator, indexed_by<sequenced<>>
3003
3004 >;
3005
3006 const auto bit_number = m_field.get_field_bit_number(field_name);
3007 NumeredDofEntity_it_view_multiIndex dofs_it_view;
3008
3009 // Set -1 to global and local dofs indices
3010 for (auto pit = ents.const_pair_begin(); pit != ents.const_pair_end();
3011 ++pit) {
3012 auto lo = numered_dofs[s]->get<Unique_mi_tag>().lower_bound(
3013 DofEntity::getLoFieldEntityUId(bit_number, pit->first));
3014 auto hi = numered_dofs[s]->get<Unique_mi_tag>().upper_bound(
3015 DofEntity::getHiFieldEntityUId(bit_number, pit->second));
3016
3017 for (; lo != hi; ++lo)
3018 if ((*lo)->getDofCoeffIdx() >= lo_coeff &&
3019 (*lo)->getDofCoeffIdx() <= hi_coeff &&
3020 (*lo)->getDofOrder() >= lo_order &&
3021 (*lo)->getDofOrder() <= hi_order)
3022 dofs_it_view.emplace_back(numered_dofs[s]->project<0>(lo));
3023 }
3024
3025 if (verb > QUIET) {
3026 for (auto &dof : dofs_it_view)
3027 MOFEM_LOG("SYNC", Sev::noisy) << **dof;
3028 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
3029 }
3030
3031 // create weak view
3032 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_weak_view;
3033 dofs_weak_view.reserve(dofs_it_view.size());
3034 for (auto dit : dofs_it_view)
3035 dofs_weak_view.push_back(*dit);
3036
3037 if (verb >= NOISY)
3038 MOFEM_LOG_C("SYNC", Sev::noisy,
3039 "Number of DOFs in multi-index %zu and to delete %zu\n",
3040 numered_dofs[s]->size(), dofs_it_view.size());
3041
3042 // erase dofs from problem
3043 for (auto weak_dit : dofs_weak_view)
3044 if (auto dit = weak_dit.lock()) {
3045 numered_dofs[s]->erase(dit->getLocalUniqueId());
3046 }
3047
3048 if (verb >= NOISY)
3049 MOFEM_LOG_C("SYNC", Sev::noisy,
3050 "Number of DOFs in multi-index after delete %zu\n",
3051 numered_dofs[s]->size());
3052
3053 // get current number of ghost dofs
3054 int nb_local_dofs = 0;
3055 int nb_ghost_dofs = 0;
3056 for (auto dit = numered_dofs[s]->get<PetscLocalIdx_mi_tag>().begin();
3057 dit != numered_dofs[s]->get<PetscLocalIdx_mi_tag>().end(); ++dit) {
3058 if ((*dit)->getPetscLocalDofIdx() >= 0 &&
3059 (*dit)->getPetscLocalDofIdx() < *(local_nbdof_ptr[s]))
3060 ++nb_local_dofs;
3061 else if ((*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[s]))
3062 ++nb_ghost_dofs;
3063 else
3064 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3065 "Impossible case. You could run problem on no distributed "
3066 "mesh. That is not implemented. Dof local index is %d",
3067 (*dit)->getPetscLocalDofIdx());
3068 }
3069
3070 // get indices
3071 auto get_indices_by_tag = [&](auto tag, auto &indices, bool only_local) {
3072 const int nb_dofs = numered_dofs[s]->size();
3073 indices.clear();
3074 indices.reserve(nb_dofs);
3075 for (auto dit = numered_dofs[s]->get<decltype(tag)>().begin();
3076 dit != numered_dofs[s]->get<decltype(tag)>().end(); ++dit) {
3077 bool add = true;
3078 if (only_local) {
3079 if ((*dit)->getPetscLocalDofIdx() < 0 ||
3080 (*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[s])) {
3081 add = false;
3082 }
3083 }
3084 if (add)
3085 indices.push_back(decltype(tag)::get_index(dit));
3086 }
3087 };
3088
3089 auto get_indices_by_uid = [&](auto tag, auto &indices) {
3090 const int nb_dofs = numered_dofs[s]->size();
3091 indices.clear();
3092 indices.reserve(nb_dofs);
3093 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3094 ++dit)
3095 indices.push_back(decltype(tag)::get_index(dit));
3096 };
3097
3098 auto get_sub_ao = [&](auto sub_data) {
3099 if (s == 0) {
3100 return sub_data->getSmartRowMap();
3101 } else {
3102 return sub_data->getSmartColMap();
3103 }
3104 };
3105
3106 auto set_sub_is_and_ao = [&s, &prb_ptr](auto sub_data, auto is, auto ao) {
3107 if (s == 0) {
3108 sub_data->rowIs = is;
3109 sub_data->rowMap = ao;
3110 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
3111 sub_data->colIs = is;
3112 sub_data->colMap = ao;
3113 }
3114 } else {
3115 sub_data->colIs = is;
3116 sub_data->colMap = ao;
3117 }
3118 };
3119
3120 auto apply_symmetry = [&s, &prb_ptr](auto sub_data) {
3121 if (s == 0) {
3122 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
3123 sub_data->colIs = sub_data->getSmartRowIs();
3124 sub_data->colMap = sub_data->getSmartRowMap();
3125 }
3126 }
3127 };
3128
3129 auto concatenate_dofs = [&](auto tag, auto &indices,
3130 const auto local_only) {
3132 get_indices_by_tag(tag, indices, local_only);
3133
3134 auto indices_ptr = [](auto &indices) {
3135 return indices.empty() ? nullptr : indices.data();
3136 };
3137
3139 // Create AO from app indices (i.e. old), to pestc indices (new after
3140 // remove)
3141 if (local_only)
3142 ao = createAOMapping(m_field.get_comm(), indices.size(),
3143 indices_ptr(indices), PETSC_NULLPTR);
3144 else
3145 ao = createAOMapping(PETSC_COMM_SELF, indices.size(),
3146 indices_ptr(indices), PETSC_NULLPTR);
3147
3148 // Set mapping to sub dm data
3149 if (local_only) {
3150 if (auto sub_data = prb_ptr->getSubData()) {
3151 // create is and then map it to main problem of sub-problem
3152 auto sub_is =
3153 createISGeneral(m_field.get_comm(), indices.size(),
3154 indices_ptr(indices), PETSC_COPY_VALUES);
3155 // get old app, i.e. oroginal befor sub indices, and ao, from app,
3156 // to petsc sub indices.
3157 auto sub_ao = get_sub_ao(sub_data);
3158 if (sub_ao.get()) {
3159 CHKERR AOPetscToApplicationIS(sub_ao, sub_is);
3160 sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
3161 } else {
3162 sub_ao = ao;
3163 }
3164 // set new sub ao
3165 set_sub_is_and_ao(sub_data, sub_is, sub_ao);
3166 apply_symmetry(sub_data);
3167 } else {
3168 // create sub data
3169 prb_ptr->getSubData() =
3170 boost::make_shared<Problem::SubProblemData>();
3171 auto sub_is =
3172 createISGeneral(m_field.get_comm(), indices.size(),
3173 indices_ptr(indices), PETSC_COPY_VALUES);
3174 // set sub is ao
3175 set_sub_is_and_ao(prb_ptr->getSubData(), sub_is, ao);
3176 apply_symmetry(prb_ptr->getSubData());
3177 }
3178 }
3179
3180 get_indices_by_uid(tag, indices);
3181 CHKERR AOApplicationToPetsc(ao, indices.size(), indices_ptr(indices));
3182
3184 };
3185
3186 // set indices index
3187 auto set_concatenated_indices = [&]() {
3188 std::vector<int> global_indices;
3189 std::vector<int> local_indices;
3191 CHKERR concatenate_dofs(PetscGlobalIdx_mi_tag(), global_indices, true);
3192 CHKERR concatenate_dofs(PetscLocalIdx_mi_tag(), local_indices, false);
3193 auto gi = global_indices.begin();
3194 auto li = local_indices.begin();
3195 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3196 ++dit) {
3198 (*dit)->getPart(), (*dit)->getDofIdx(), *gi, *li);
3199 bool success = numered_dofs[s]->modify(dit, mod);
3200 if (!success)
3201 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3202 "can not set negative indices");
3203 ++gi;
3204 ++li;
3205 }
3207 };
3208 CHKERR set_concatenated_indices();
3209
3210 MPI_Allreduce(&nb_local_dofs, nbdof_ptr[s], 1, MPI_INT, MPI_SUM,
3211 m_field.get_comm());
3212 *(local_nbdof_ptr[s]) = nb_local_dofs;
3213 *(ghost_nbdof_ptr[s]) = nb_ghost_dofs;
3214
3215 if (debug)
3216 for (auto dof : (*numered_dofs[s])) {
3217 if (dof->getPetscGlobalDofIdx() < 0) {
3218 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
3219 "Negative global idx");
3220 }
3221 if (dof->getPetscLocalDofIdx() < 0) {
3222 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
3223 "Negative local idx");
3224 }
3225 }
3226
3227 } else {
3228
3229 *(nbdof_ptr[1]) = *(nbdof_ptr[0]);
3230 *(local_nbdof_ptr[1]) = *(local_nbdof_ptr[0]);
3231 *(ghost_nbdof_ptr[1]) = *(ghost_nbdof_ptr[0]);
3232 }
3233
3234 if (verb > QUIET) {
3236 "WORLD", Sev::inform,
3237 "Removed DOFs from problem %s dofs [%d / %d (before %d / %d) global]",
3238 prb_ptr->getName().c_str(), prb_ptr->getNbDofsRow(),
3239 prb_ptr->getNbDofsCol(), nb_init_row_dofs, nb_init_col_dofs);
3240 MOFEM_LOG_C("SYNC", Sev::verbose,
3241 "Removed DOFs from problem %s dofs [ %d / %d "
3242 "(before %d / %d) local, %d / %d (before %d / %d)]",
3243 prb_ptr->getName().c_str(), prb_ptr->getNbLocalDofsRow(),
3244 prb_ptr->getNbLocalDofsCol(), nb_init_loc_row_dofs,
3245 nb_init_loc_col_dofs, prb_ptr->getNbGhostDofsRow(),
3246 prb_ptr->getNbGhostDofsCol(), nb_init_ghost_row_dofs,
3247 nb_init_ghost_col_dofs);
3248 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
3249 }
3250
3252}
3253
3255 const std::string problem_name, const std::string field_name,
3256 const Range ents, const int lo_coeff, const int hi_coeff,
3257 const int lo_order, const int hi_order, int verb, const bool debug) {
3258
3259 MoFEM::Interface &m_field = cOre;
3261
3262 const Problem *prb_ptr;
3263 CHKERR m_field.get_problem(problem_name, &prb_ptr);
3264
3265 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
3266 prb_ptr->numeredRowDofsPtr, nullptr};
3267 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
3268 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
3269
3270 int *nbdof_ptr[] = {&prb_ptr->nbDofsRow, &prb_ptr->nbDofsCol};
3271 int *local_nbdof_ptr[] = {&prb_ptr->nbLocDofsRow, &prb_ptr->nbLocDofsCol};
3272 int *ghost_nbdof_ptr[] = {&prb_ptr->nbGhostDofsRow, &prb_ptr->nbGhostDofsCol};
3273
3274 const int nb_init_row_dofs = prb_ptr->getNbDofsRow();
3275 const int nb_init_col_dofs = prb_ptr->getNbDofsCol();
3276 const int nb_init_loc_row_dofs = prb_ptr->getNbLocalDofsRow();
3277 // const int nb_init_loc_col_dofs = prb_ptr->getNbLocalDofsCol();
3278 const int nb_init_ghost_row_dofs = prb_ptr->getNbGhostDofsRow();
3279 const int nb_init_ghost_col_dofs = prb_ptr->getNbGhostDofsCol();
3280
3281 const std::array<int, 2> nb_init_dofs = {nb_init_row_dofs, nb_init_col_dofs};
3282
3283 for (int s = 0; s != 2; ++s)
3284 if (numered_dofs[s]) {
3285
3286 typedef multi_index_container<
3287
3288 NumeredDofEntity_multiIndex::iterator, indexed_by<sequenced<>>
3289
3290 >
3291 NumeredDofEntity_it_view_multiIndex;
3292
3293 const auto bit_number = m_field.get_field_bit_number(field_name);
3294 NumeredDofEntity_it_view_multiIndex dofs_it_view;
3295
3296 // Set -1 to global and local dofs indices
3297 for (auto pit = ents.const_pair_begin(); pit != ents.const_pair_end();
3298 ++pit) {
3299 auto lo = numered_dofs[s]->get<Unique_mi_tag>().lower_bound(
3300 DofEntity::getLoFieldEntityUId(bit_number, pit->first));
3301 auto hi = numered_dofs[s]->get<Unique_mi_tag>().upper_bound(
3302 DofEntity::getHiFieldEntityUId(bit_number, pit->second));
3303
3304 for (; lo != hi; ++lo)
3305 if ((*lo)->getDofCoeffIdx() >= lo_coeff &&
3306 (*lo)->getDofCoeffIdx() <= hi_coeff &&
3307 (*lo)->getDofOrder() >= lo_order &&
3308 (*lo)->getDofOrder() <= hi_order)
3309 dofs_it_view.emplace_back(numered_dofs[s]->project<0>(lo));
3310 }
3311
3312 if (verb > QUIET) {
3313 for (auto &dof : dofs_it_view)
3314 MOFEM_LOG("SYNC", Sev::noisy) << **dof;
3315 }
3316
3317 // set negative index
3318 auto mod = NumeredDofEntity_part_and_all_indices_change(-1, -1, -1, -1);
3319 for (auto dit : dofs_it_view) {
3320 bool success = numered_dofs[s]->modify(dit, mod);
3321 if (!success)
3322 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3323 "can not set negative indices");
3324 }
3325
3326 // create weak view
3327 std::vector<boost::weak_ptr<NumeredDofEntity>> dosf_weak_view;
3328 dosf_weak_view.reserve(dofs_it_view.size());
3329 for (auto dit : dofs_it_view)
3330 dosf_weak_view.push_back(*dit);
3331
3332 if (verb >= NOISY)
3333 MOFEM_LOG_C("SYNC", Sev::noisy,
3334 "Number of DOFs in multi-index %zu and to delete %zu\n",
3335 numered_dofs[s]->size(), dofs_it_view.size());
3336
3337 // erase dofs from problem
3338 for (auto weak_dit : dosf_weak_view)
3339 if (auto dit = weak_dit.lock()) {
3340 numered_dofs[s]->erase(dit->getLocalUniqueId());
3341 }
3342
3343 if (verb >= NOISY)
3344 MOFEM_LOG_C("SYNC", Sev::noisy,
3345 "Number of DOFs in multi-index after delete %zu\n",
3346 numered_dofs[s]->size());
3347
3348 // get current number of ghost dofs
3349 int nb_global_dof = 0;
3350 int nb_local_dofs = 0;
3351 int nb_ghost_dofs = 0;
3352
3353 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3354 ++dit) {
3355
3356 if ((*dit)->getDofIdx() >= 0) {
3357
3358 if ((*dit)->getPetscLocalDofIdx() >= 0 &&
3359 (*dit)->getPetscLocalDofIdx() < *(local_nbdof_ptr[s]))
3360 ++nb_local_dofs;
3361 else if ((*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[s]))
3362 ++nb_ghost_dofs;
3363
3364 ++nb_global_dof;
3365 }
3366 }
3367
3368 if (debug) {
3369 MPI_Allreduce(&nb_local_dofs, nbdof_ptr[s], 1, MPI_INT, MPI_SUM,
3370 m_field.get_comm());
3371 if (*(nbdof_ptr[s]) != nb_global_dof)
3372 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3373 "Number of local DOFs do not add up %d != %d",
3374 *(nbdof_ptr[s]), nb_global_dof);
3375 }
3376
3377 *(nbdof_ptr[s]) = nb_global_dof;
3378 *(local_nbdof_ptr[s]) = nb_local_dofs;
3379 *(ghost_nbdof_ptr[s]) = nb_ghost_dofs;
3380
3381 // get indices
3382 auto get_indices_by_tag = [&](auto tag) {
3383 std::vector<int> indices;
3384 indices.resize(nb_init_dofs[s], -1);
3385 for (auto dit = numered_dofs[s]->get<Idx_mi_tag>().lower_bound(0);
3386 dit != numered_dofs[s]->get<Idx_mi_tag>().end(); ++dit) {
3387 indices[(*dit)->getDofIdx()] = decltype(tag)::get_index(dit);
3388 }
3389 return indices;
3390 };
3391
3392 auto renumber = [&](auto tag, auto &indices) {
3394 int idx = 0;
3395 for (auto dit = numered_dofs[s]->get<decltype(tag)>().lower_bound(0);
3396 dit != numered_dofs[s]->get<decltype(tag)>().end(); ++dit) {
3397 indices[(*dit)->getDofIdx()] = idx++;
3398 }
3400 };
3401
3402 auto get_sub_ao = [&](auto sub_data) {
3403 if (s == 0) {
3404 return sub_data->getSmartRowMap();
3405 } else {
3406 return sub_data->getSmartColMap();
3407 }
3408 };
3409
3410 auto set_sub_is_and_ao = [&s, &prb_ptr](auto sub_data, auto is, auto ao) {
3411 if (s == 0) {
3412 sub_data->rowIs = is;
3413 sub_data->rowMap = ao;
3414 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
3415 sub_data->colIs = is;
3416 sub_data->colMap = ao;
3417 }
3418 } else {
3419 sub_data->colIs = is;
3420 sub_data->colMap = ao;
3421 }
3422 };
3423
3424 auto apply_symmetry = [&s, &prb_ptr](auto sub_data) {
3425 if (s == 0) {
3426 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
3427 sub_data->colIs = sub_data->getSmartRowIs();
3428 sub_data->colMap = sub_data->getSmartRowMap();
3429 }
3430 }
3431 };
3432
3433 auto set_sub_data = [&](auto &indices) {
3435 auto indices_ptr = [](auto &indices) {
3436 return indices.empty() ? nullptr : indices.data();
3437 };
3438 if (auto sub_data = prb_ptr->getSubData()) {
3439 // create is and then map it to main problem of sub-problem
3440 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
3441 indices_ptr(indices), PETSC_COPY_VALUES);
3442 // get old app, i.e. oroginal befor sub indices, and ao, from
3443 // app, to petsc sub indices.
3444 auto sub_ao = get_sub_ao(sub_data);
3445 if (sub_ao.get())
3446 CHKERR AOPetscToApplicationIS(sub_ao, sub_is);
3447 sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
3448 // set new sub ao
3449 set_sub_is_and_ao(sub_data, sub_is, sub_ao);
3450 apply_symmetry(sub_data);
3451 } else {
3452 prb_ptr->getSubData() = boost::make_shared<Problem::SubProblemData>();
3453 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
3454 indices_ptr(indices), PETSC_COPY_VALUES);
3455 auto sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
3456 // set sub is ao
3457 set_sub_is_and_ao(prb_ptr->getSubData(), sub_is, sub_ao);
3458 apply_symmetry(prb_ptr->getSubData());
3459 }
3461 };
3462
3463 auto global_indices = get_indices_by_tag(PetscGlobalIdx_mi_tag());
3464 auto local_indices = get_indices_by_tag(PetscLocalIdx_mi_tag());
3465 CHKERR set_sub_data(global_indices);
3466 CHKERR renumber(PetscGlobalIdx_mi_tag(), global_indices);
3467 CHKERR renumber(PetscLocalIdx_mi_tag(), local_indices);
3468
3469 int i = 0;
3470 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3471 ++dit) {
3472 auto idx = (*dit)->getDofIdx();
3473 if (idx >= 0) {
3475 (*dit)->getPart(), i++, global_indices[idx], local_indices[idx]);
3476 bool success = numered_dofs[s]->modify(dit, mod);
3477 if (!success)
3478 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3479 "can not set negative indices");
3480 } else {
3482 (*dit)->getPart(), -1, -1, -1);
3483 bool success = numered_dofs[s]->modify(dit, mod);
3484 if (!success)
3485 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3486 "can not set negative indices");
3487 }
3488 };
3489
3490 if (debug) {
3491 for (auto dof : (*numered_dofs[s])) {
3492 if (dof->getDofIdx() >= 0 && dof->getPetscGlobalDofIdx() < 0) {
3493 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3494 "Negative global idx");
3495 }
3496 }
3497 }
3498
3499 } else {
3500
3501 *(nbdof_ptr[1]) = *(nbdof_ptr[0]);
3502 *(local_nbdof_ptr[1]) = *(local_nbdof_ptr[0]);
3503 *(ghost_nbdof_ptr[1]) = *(ghost_nbdof_ptr[0]);
3504 }
3505
3506 if (verb >= NOISY)
3508
3509 if (verb > QUIET) {
3511 "WORLD", Sev::inform,
3512 "Removed DOFs from problem %s dofs [%d / %d (before %d / %d) global]",
3513 prb_ptr->getName().c_str(), prb_ptr->getNbDofsRow(),
3514 prb_ptr->getNbDofsCol(), nb_init_row_dofs, nb_init_col_dofs);
3515 MOFEM_LOG_C("SYNC", Sev::verbose,
3516 "Removed DOFs from problem %s dofs [ %d / %d "
3517 "(before %d / %d) local, %d / %d (before %d / %d)]",
3518 prb_ptr->getName().c_str(), prb_ptr->getNbLocalDofsRow(),
3519 prb_ptr->getNbLocalDofsCol(), nb_init_loc_row_dofs,
3520 nb_init_loc_row_dofs, prb_ptr->getNbGhostDofsRow(),
3521 prb_ptr->getNbGhostDofsCol(), nb_init_ghost_row_dofs,
3522 nb_init_ghost_col_dofs);
3524 }
3526}
3527
3529 const std::string problem_name, const std::string field_name,
3530 const BitRefLevel bit_ref_level, const BitRefLevel bit_ref_mask,
3531 Range *ents_ptr, const int lo_coeff, const int hi_coeff, const int lo_order,
3532 const int hi_order, int verb, const bool debug) {
3533 MoFEM::Interface &m_field = cOre;
3535
3536 auto bit_manager = m_field.getInterface<BitRefManager>();
3537
3538 Range ents;
3539 if (ents_ptr) {
3540 ents = *ents_ptr;
3541 CHKERR bit_manager->filterEntitiesByRefLevel(bit_ref_level, bit_ref_mask,
3542 ents, verb);
3543 } else {
3544 CHKERR bit_manager->getEntitiesByRefLevel(bit_ref_level, bit_ref_mask, ents,
3545 verb);
3546 }
3547
3548 CHKERR removeDofsOnEntities(problem_name, field_name, ents, lo_coeff,
3549 hi_coeff, lo_order, hi_order, verb, debug);
3550
3552}
3553
3555 const std::string problem_name, const std::string field_name,
3556 const BitRefLevel bit_ref_level, const BitRefLevel bit_ref_mask,
3557 Range *ents_ptr, const int lo_coeff, const int hi_coeff, const int lo_order,
3558 const int hi_order, int verb, const bool debug) {
3559 MoFEM::Interface &m_field = cOre;
3561
3562 auto bit_manager = m_field.getInterface<BitRefManager>();
3563
3564 Range ents;
3565 if (ents_ptr) {
3566 ents = *ents_ptr;
3567 CHKERR bit_manager->filterEntitiesByRefLevel(bit_ref_level, bit_ref_mask,
3568 ents, verb);
3569 } else {
3570 CHKERR bit_manager->getEntitiesByRefLevel(bit_ref_level, bit_ref_mask, ents,
3571 verb);
3572 }
3573
3575 lo_coeff, hi_coeff, lo_order,
3576 hi_order, verb, debug);
3577
3579}
3580
3582ProblemsManager::markDofs(const std::string problem_name, RowColData rc,
3583 const enum MarkOP op, const Range ents,
3584 std::vector<unsigned char> &marker) const {
3585
3586 Interface &m_field = cOre;
3587 const Problem *problem_ptr;
3589 CHKERR m_field.get_problem(problem_name, &problem_ptr);
3590 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs;
3591 switch (rc) {
3592 case ROW:
3593 dofs = problem_ptr->getNumeredRowDofsPtr();
3594 break;
3595 case COL:
3596 dofs = problem_ptr->getNumeredColDofsPtr();
3597 default:
3598 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Should be row or column");
3599 }
3600 marker.resize(dofs->size(), 0);
3601 std::vector<unsigned char> marker_tmp;
3602
3603 switch (op) {
3604 case MarkOP::OR:
3605 for (auto p = ents.pair_begin(); p != ents.pair_end(); ++p) {
3606 auto lo = dofs->get<Ent_mi_tag>().lower_bound(p->first);
3607 auto hi = dofs->get<Ent_mi_tag>().upper_bound(p->second);
3608 for (; lo != hi; ++lo) {
3609 if ((*lo)->getPetscLocalDofIdx() < 0)
3610 continue;
3611 marker[(*lo)->getPetscLocalDofIdx()] |= 1;
3612 }
3613 }
3614 break;
3615 case MarkOP::AND:
3616 marker_tmp.resize(dofs->size(), 0);
3617 for (auto p = ents.pair_begin(); p != ents.pair_end(); ++p) {
3618 auto lo = dofs->get<Ent_mi_tag>().lower_bound(p->first);
3619 auto hi = dofs->get<Ent_mi_tag>().upper_bound(p->second);
3620 for (; lo != hi; ++lo) {
3621 if ((*lo)->getPetscLocalDofIdx() < 0)
3622 continue;
3623 marker_tmp[(*lo)->getPetscLocalDofIdx()] = 1;
3624 }
3625 }
3626 for (int i = 0; i != marker.size(); ++i) {
3627 marker[i] &= marker_tmp[i];
3628 }
3629 break;
3630 }
3631
3633}
3634
3636 const std::string problem_name, RowColData rc, const std::string field_name,
3637 const int lo, const int hi, const enum ProblemsManager::MarkOP op,
3638 const unsigned char c, std::vector<unsigned char> &marker) const {
3639
3640 Interface &m_field = cOre;
3641 const Problem *problem_ptr;
3643 CHKERR m_field.get_problem(problem_name, &problem_ptr);
3644 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs;
3645 switch (rc) {
3646 case ROW:
3647 dofs = problem_ptr->getNumeredRowDofsPtr();
3648 break;
3649 case COL:
3650 dofs = problem_ptr->getNumeredColDofsPtr();
3651 default:
3652 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Should be row or column");
3653 }
3654 marker.resize(dofs->size(), 0);
3655
3656 auto dof_lo = dofs->get<Unique_mi_tag>().lower_bound(
3658 auto dof_hi = dofs->get<Unique_mi_tag>().upper_bound(
3660
3661 switch (op) {
3662 case MarkOP::OR:
3663 for (; dof_lo != dof_hi; ++dof_lo) {
3664 if ((*dof_lo)->getPetscLocalDofIdx() < 0)
3665 continue;
3666 if ((*dof_lo)->getDofCoeffIdx() >= lo &&
3667 (*dof_lo)->getDofCoeffIdx() <= hi)
3668 marker[(*dof_lo)->getPetscLocalDofIdx()] |= c;
3669 }
3670 break;
3671 case MarkOP::AND:
3672 for (; dof_lo != dof_hi; ++dof_lo) {
3673 if ((*dof_lo)->getPetscLocalDofIdx() < 0)
3674 continue;
3675 if ((*dof_lo)->getDofCoeffIdx() >= lo &&
3676 (*dof_lo)->getDofCoeffIdx() <= hi)
3677 marker[(*dof_lo)->getPetscLocalDofIdx()] &= c;
3678 }
3679 break;
3680 }
3681
3683}
3684
3686
3687 const std::string problem_name, RowColData rc,
3688 std::vector<boost::weak_ptr<NumeredDofEntity>> &vec_dof_view,
3689 const enum MarkOP op, std::vector<unsigned char> &marker
3690
3691) const {
3692 Interface &m_field = cOre;
3694
3695 const Problem *problem_ptr;
3696 CHKERR m_field.get_problem(problem_name, &problem_ptr);
3697 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs;
3698 switch (rc) {
3699 case ROW:
3700 dofs = problem_ptr->getNumeredRowDofsPtr();
3701 break;
3702 case COL:
3703 dofs = problem_ptr->getNumeredColDofsPtr();
3704 break;
3705 default:
3706 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Should be row or column");
3707 }
3708 marker.resize(dofs->size(), 0);
3709
3710 for (auto &dof : vec_dof_view) {
3711 if (auto dof_ptr = dof.lock()) {
3712 if (dof_ptr->getPetscLocalDofIdx() < 0)
3713 continue;
3714 if (op == MarkOP::OR)
3715 marker[dof_ptr->getPetscLocalDofIdx()] |= 1;
3716 else
3717 marker[dof_ptr->getPetscLocalDofIdx()] &= 1;
3718 }
3719 }
3720
3722}
3723
3725ProblemsManager::addFieldToEmptyFieldBlocks(const std::string problem_name,
3726 const std::string row_field,
3727 const std::string col_field) const {
3728
3729 Interface &m_field = cOre;
3731
3732 const auto problem_ptr = m_field.get_problem(problem_name);
3733 auto get_field_id = [&](const std::string field_name) {
3734 return m_field.get_field_structure(field_name)->getId();
3735 };
3736 const auto row_id = get_field_id(row_field);
3737 const auto col_id = get_field_id(col_field);
3738
3739 problem_ptr->addFieldToEmptyFieldBlocks(BlockFieldPair(row_id, col_id));
3740
3742}
3743
3744} // namespace MoFEM
MPI_Comm comm
std::string type
#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,...)
#define ProblemManagerFunctionBegin
PetscInt size
std::string name
Core & cOre
constexpr double a
@ VERY_VERBOSE
@ QUIET
@ NOISY
@ VERBOSE
RowColData
RowColData.
@ COL
@ ROW
#define MAX_DOFS_ON_ENTITY
Maximal number of DOFs on entity.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_NOT_FOUND
Definition definitions.h:33
@ MOFEM_IMPOSSIBLE_CASE
Definition definitions.h:35
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_INVALID_DATA
Definition definitions.h:36
#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 ...
static const bool debug
multi_index_container< boost::shared_ptr< FieldEntity >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< FieldEntity, UId, &FieldEntity::getGlobalUniqueId > > > > FieldEntity_multiIndex_global_uid_view
multi-index view on DofEntity by uid
multi_index_container< boost::shared_ptr< DofEntity >, indexed_by< ordered_unique< const_mem_fun< DofEntity, UId, &DofEntity::getLocalUniqueId > >, ordered_non_unique< const_mem_fun< DofEntity, char, &DofEntity::getActive > > > > DofEntity_multiIndex_active_view
multi-index view on DofEntity activity
NumeredDofEntity_multiIndex::index< Unique_mi_tag >::type NumeredDofEntityByUId
Numbered DoF multi-index by UId.
multi_index_container< boost::shared_ptr< NumeredDofEntity >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, UId, &NumeredDofEntity::getLocalUniqueId > >, ordered_non_unique< tag< Part_mi_tag >, member< NumeredDofEntity, unsigned int, &NumeredDofEntity::pArt > >, ordered_non_unique< tag< Idx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::dofIdx > >, ordered_non_unique< tag< PetscGlobalIdx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::petscGloablDofIdx > >, ordered_non_unique< tag< PetscLocalIdx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::petscLocalDofIdx > >, ordered_non_unique< tag< Ent_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, EntityHandle, &NumeredDofEntity::getEnt > > > > NumeredDofEntity_multiIndex
MultiIndex container keeps NumeredDofEntity.
multi_index_container< boost::shared_ptr< DofEntity >, indexed_by< ordered_unique< const_mem_fun< DofEntity, UId, &DofEntity::getGlobalUniqueId > > > > DofEntity_multiIndex_global_uid_view
multi-index view on DofEntity by uid
multi_index_container< boost::shared_ptr< NumeredEntFiniteElement >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< NumeredEntFiniteElement::interface_type_EntFiniteElement, UId, &NumeredEntFiniteElement::getLocalUniqueId > >, ordered_non_unique< tag< Part_mi_tag >, member< NumeredEntFiniteElement, unsigned int, &NumeredEntFiniteElement::part > >, ordered_non_unique< tag< Ent_mi_tag >, const_mem_fun< NumeredEntFiniteElement::interface_type_RefEntity, EntityHandle, &NumeredEntFiniteElement::getEnt > >, ordered_non_unique< tag< Composite_Name_And_Part_mi_tag >, composite_key< NumeredEntFiniteElement, const_mem_fun< NumeredEntFiniteElement::interface_type_FiniteElement, boost::string_ref, &NumeredEntFiniteElement::getNameRef >, member< NumeredEntFiniteElement, unsigned int, &NumeredEntFiniteElement::part > > > > > NumeredEntFiniteElement_multiIndex
MultiIndex for entities for NumeredEntFiniteElement.
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 MoFEMErrorCode get_ents_elements_adjacency(const FieldEntityEntFiniteElementAdjacencyMap_multiIndex **dofs_elements_adjacency) const =0
Get the dofs elements adjacency object.
virtual const FiniteElement_multiIndex * get_finite_elements() const =0
Get the finite elements object.
virtual const DofEntity_multiIndex * get_dofs() const =0
Get the dofs object.
virtual const Problem_multiIndex * get_problems() const =0
Get the problems object.
virtual const EntFiniteElement_multiIndex * get_ents_finite_elements() const =0
Get the ents finite elements object.
virtual const Field_multiIndex * get_fields() const =0
Get the fields object.
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
#define MOFEM_LOG(channel, severity)
Log.
MoFEMErrorCode buildProblemOnDistributedMesh(const std::string name, const bool square_matrix, int verb=VERBOSE)
build problem data structures, assuming that mesh is distributed (collective)
MoFEMErrorCode partitionGhostDofs(const std::string name, int verb=VERBOSE)
determine ghost nodes
MoFEMErrorCode printPartitionedProblem(const Problem *problem_ptr, int verb=VERBOSE)
Print partition information for debugging.
MoFEMErrorCode addFieldToEmptyFieldBlocks(const std::string problem_name, const std::string row_field, const std::string col_field) const
Add empty field blocks to optimize matrix storage.
MoFEMErrorCode modifyMarkDofs(const std::string problem_name, RowColData rc, const std::string field_name, const int lo, const int hi, const enum MarkOP op, const unsigned char c, std::vector< unsigned char > &marker) const
Modify DOF markers for specific field and coefficient range.
MoFEMErrorCode partitionSimpleProblem(const std::string name, int verb=VERBOSE)
partition problem dofs
MoFEMErrorCode buildComposedProblem(const std::string out_name, const std::vector< std::string > add_row_problems, const std::vector< std::string > add_col_problems, const bool square_matrix=true, int verb=1)
build composite problem
MoFEMErrorCode getSideDofsOnBrokenSpaceEntities(std::vector< boost::weak_ptr< NumeredDofEntity > > &vec_dof_view, const std::string problem_name, RowColData rc, const std::string field_name, const Range ents, int bridge_dim, const int lo_coeff=0, const int hi_coeff=MAX_DOFS_ON_ENTITY, const int lo_order=0, const int hi_order=100, int verb=VERBOSE, const bool debug=false) const
Get DOFs on side entities for broken space.
MoFEMErrorCode buildProblem(const std::string name, const bool square_matrix, int verb=VERBOSE)
build problem data structures
DEPRECATED 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 buildSubProblem(const std::string out_name, const std::vector< std::string > &fields_row, const std::vector< std::string > &fields_col, const std::string main_problem, const bool square_matrix=true, const map< std::string, boost::shared_ptr< Range > > *entityMapRow=nullptr, const map< std::string, boost::shared_ptr< Range > > *entityMapCol=nullptr, int verb=VERBOSE)
build sub problem
MoFEMErrorCode partitionProblem(const std::string name, int verb=VERBOSE)
partition problem dofs (collective)
MoFEMErrorCode removeDofs(const std::string problem_name, RowColData rc, std::vector< boost::weak_ptr< NumeredDofEntity > > &vec_dof_view, int verb=VERBOSE, const bool debug=false)
Remove DOFs from problem on broken space.
MoFEMErrorCode partitionGhostDofsOnDistributedMesh(const std::string name, int verb=VERBOSE)
determine ghost nodes on distributed meshes
MoFEMErrorCode getProblemElementsLayout(const std::string name, const std::string &fe_name, PetscLayout *layout) const
Get layout of elements in the problem.
MoFEMErrorCode getFEMeshset(const std::string prb_name, const std::string &fe_name, EntityHandle *meshset) const
Create finite element meshset for the problem.
MoFEMErrorCode inheritPartition(const std::string name, const std::string problem_for_rows, bool copy_rows, const std::string problem_for_cols, bool copy_cols, int verb=VERBOSE)
build indexing and partition problem inheriting indexing and partitioning from two other problems
MoFEMErrorCode partitionFiniteElements(const std::string name, bool part_from_moab=false, int low_proc=-1, int hi_proc=-1, int verb=VERBOSE)
partition finite elements
MoFEMErrorCode debugPartitionedProblem(const Problem *problem_ptr, int verb=VERBOSE)
Debug partition information.
MoFEMErrorCode removeDofsOnEntities(const std::string problem_name, const std::string field_name, const Range ents, const int lo_coeff=0, const int hi_coeff=MAX_DOFS_ON_ENTITY, const int lo_order=0, const int hi_order=100, int verb=VERBOSE, const bool debug=false)
Remove DOFs from problem.
MoFEMErrorCode getOptions()
Get command line options for ProblemsManager.
virtual MoFEMErrorCode clear_problem(const std::string name, int verb=DEFAULT_VERBOSITY)=0
clear problem
auto marker
set bit to marker
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
int DofIdx
Index of DOF.
Definition Types.hpp:18
std::bitset< BITFIELDID_SIZE > BitFieldId
Field Id.
Definition Types.hpp:42
uint128_t UId
Unique Id.
Definition Types.hpp:31
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
auto createISGeneral(MPI_Comm comm, PetscInt n, const PetscInt idx[], PetscCopyMode mode)
Creates a data structure for an index set containing a list of integers.
auto createAOMapping(MPI_Comm comm, PetscInt napp, const PetscInt myapp[], const PetscInt mypetsc[])
Creates an application mapping using two integer arrays.
auto createAOMappingIS(IS isapp, IS ispetsc)
Creates an application mapping using two index sets.
auto field_bit_from_bit_number(const int bit_number)
get field bit id from bit number
Problem::BlockFieldPair BlockFieldPair
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
multi_index_container< boost::shared_ptr< NumeredDofEntity >, indexed_by< ordered_unique< const_mem_fun< NumeredDofEntity::interface_type_DofEntity, UId, &NumeredDofEntity::getLocalUniqueId > > > > NumeredDofEntity_multiIndex_uid_view_ordered
constexpr auto field_name
FTensor::Index< 'm', 3 > m
Managing BitRefLevels.
Managing BitRefLevels.
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 MPI_Comm & get_comm() const =0
virtual std::string get_field_name(const BitFieldId id) const =0
get field name from id
virtual int get_comm_rank() const =0
Core (interface) class.
Definition Core.hpp:83
int & getBuildMoFEM() const
Get flags/semaphores for different stages.
Definition Core.hpp:230
Deprecated interface functions.
static UId getLoFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
static UId getHiFieldEntityUId(const FieldBitNumber bit, const EntityHandle ent)
UId getLocalUniqueIdCalculate() const
Generate UId for finite element entity.
static MoFEMErrorCode getDofView(const FE_ENTS &fe_ents_view, const MOFEM_DOFS &mofem_dofs, MOFEM_DOFS_VIEW &dofs_view, INSERTER &&inserter)
static UId getHiBitNumberUId(const FieldBitNumber bit_number)
static auto getHandleFromUniqueId(const UId uid)
Get the Handle From Unique Id.
static auto getFieldBitNumberFromUniqueId(const UId uid)
Get the Field Bit Number From Unique Id.
UId getLocalUniqueIdCalculate()
Get the Local Unique Id Calculate object.
static UId getLoBitNumberUId(const FieldBitNumber bit_number)
static auto getOwnerFromUniqueId(const UId uid)
UId getGlobalUniqueIdCalculate() const
Calculate global UId.
FieldCoefficientsNumber getNbOfCoeffs() const
Get number of field coefficients per DOF.
std::map< int, BaseFunction::DofsSideMap > & getDofSideMap() const
Get DOF side mapping for broken spaces.
const BitFieldId & getId() const
Get unique field identifier.
IdxDataTypePtr(const int *ptr)
IdxDataType(const UId uid, const int dof)
Matrix manager is used to build and partition problems.
keeps information about indexed dofs for the problem
Partitioned (Indexed) Finite Element in Problem.
keeps basic data about problem
DofIdx getNbLocalDofsRow() const
MoFEMErrorCode getNumberOfElementsByNameAndPart(MPI_Comm comm, const std::string name, PetscLayout *layout) const
Get number of finite elements by name on processors.
DofIdx getNbDofsRow() const
BitRefLevel getBitRefLevel() const
auto & getColDofsSequence() const
Get reference to sequence data numbered dof container.
BitRefLevel getBitRefLevelMask() const
boost::shared_ptr< SubProblemData > & getSubData() const
Get main problem of sub-problem is.
DofIdx nbGhostDofsCol
Number of ghost DOFs in col.
boost::shared_ptr< NumeredDofEntity_multiIndex > numeredRowDofsPtr
store DOFs on rows for this problem
boost::shared_ptr< NumeredEntFiniteElement_multiIndex > numeredFiniteElementsPtr
store finite elements
DofIdx getNbGhostDofsCol() const
DofIdx nbLocDofsRow
Local number of DOFs in row.
BitFEId getBitFEId() const
Get the BitFEIDs in problem
DofIdx nbDofsCol
Global number of DOFs in col.
DofIdx getNbDofsCol() const
DofIdx getNbLocalDofsCol() const
DofIdx nbGhostDofsRow
Number of ghost DOFs in row.
auto & getNumeredColDofsPtr() const
get access to numeredColDofsPtr storing DOFs on cols
DofIdx nbLocDofsCol
Local number of DOFs in colIs.
DofIdx nbDofsRow
Global number of DOFs in row.
DofIdx getNbGhostDofsRow() const
boost::shared_ptr< NumeredDofEntity_multiIndex > numeredColDofsPtr
store DOFs on columns for this problem
auto & getNumeredRowDofsPtr() const
get access to numeredRowDofsPtr storing DOFs on rows
auto & getRowDofsSequence() const
Get reference to sequence data numbered dof container.
Problem manager is used to build and partition problems.
MoFEMErrorCode markDofs(const std::string problem_name, RowColData rc, const enum MarkOP op, const Range ents, std::vector< unsigned char > &marker) const
Create vector with marked indices.
ProblemsManager(const MoFEM::Core &core)
PetscLogEvent MOFEM_EVENT_ProblemsManager
PetscBool synchroniseProblemEntities
DOFs in fields, not from DOFs on elements.
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
MoFEMErrorCode removeDofsOnEntitiesNotDistributed(const std::string problem_name, const std::string field_name, const Range ents, const int lo_coeff=0, const int hi_coeff=MAX_DOFS_ON_ENTITY, const int lo_order=0, const int hi_order=100, int verb=VERBOSE, const bool debug=false)
Remove DOFs from problem.
intrusive_ptr for managing petsc objects
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.