v0.15.0
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 if (fe.getEntType() == MBENTITYSET) {
2263 fe.part = m_field.get_comm_rank();
2264 } else {
2265 // if partition is taken from moab partition
2266 int proc = fe.getPartProc();
2267 if (proc == -1 && fe.getEntType() == MBVERTEX)
2268 proc = fe.getOwnerProc();
2269 fe.part = proc;
2270 }
2271 }
2272 }
2273
2274 for (auto &fe : *numbered_good_elems_ptr) {
2275
2277 CHKERR fe.sPtr->getRowDofView(*(p_miit->numeredRowDofsPtr), rows_view);
2278
2279 if (!part_from_moab) {
2280 if (fe.getEntType() == MBENTITYSET) {
2281 fe.part = m_field.get_comm_rank();
2282 } else {
2283 std::vector<int> parts(m_field.get_comm_size(), 0);
2284 for (auto &dof_ptr : rows_view)
2285 parts[dof_ptr->pArt]++;
2286 std::vector<int>::iterator pos =
2287 max_element(parts.begin(), parts.end());
2288 const auto max_part = std::distance(parts.begin(), pos);
2289 fe.part = max_part;
2290 }
2291 }
2292 }
2293
2294 for (auto &fe : *numbered_good_elems_ptr) {
2295
2296 auto check_fields_and_dofs = [&]() {
2297 if (!part_from_moab) {
2298 if (fe.getBitFieldIdRow().none() && m_field.get_comm_size() == 0) {
2299 MOFEM_LOG("WORLD", Sev::warning)
2300 << "At least one field has to be added to element row to "
2301 "determine partition of finite element. Check element " +
2302 boost::lexical_cast<std::string>(fe.getName());
2303 }
2304 }
2305
2306 return true;
2307 };
2308
2309 if (check_fields_and_dofs()) {
2310 // Add element to the problem
2311 auto p = problem_finite_elements.insert(
2312 boost::shared_ptr<NumeredEntFiniteElement>(numbered_good_elems_ptr,
2313 &fe));
2314 if (!p.second)
2315 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_FOUND, "element is there");
2316 }
2317 }
2318
2319 if (verb >= VERBOSE) {
2320 auto elements_on_rank =
2321 problem_finite_elements.get<Part_mi_tag>().equal_range(
2322 m_field.get_comm_rank());
2323 MOFEM_LOG("SYNC", Sev::verbose)
2324 << p_miit->getName() << " nb. elems "
2325 << std::distance(elements_on_rank.first, elements_on_rank.second);
2326 auto fe_ptr = m_field.get_finite_elements();
2327 for (auto &fe : *fe_ptr) {
2328 auto e_range =
2329 problem_finite_elements.get<Composite_Name_And_Part_mi_tag>()
2330 .equal_range(
2331 boost::make_tuple(fe->getName(), m_field.get_comm_rank()));
2332 MOFEM_LOG("SYNC", Sev::noisy)
2333 << "Element " << fe->getName() << " nb. elems "
2334 << std::distance(e_range.first, e_range.second);
2335 }
2336
2338 }
2339
2342}
2343
2345 int verb) {
2346 MoFEM::Interface &m_field = cOre;
2347 auto problems_ptr = m_field.get_problems();
2349
2351 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2352 "partition of problem not build");
2354 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2355 "partitions finite elements not build");
2356
2357 // get problem pointer
2358 auto p_miit = problems_ptr->get<Problem_mi_tag>().find(name);
2359 if (p_miit == problems_ptr->get<Problem_mi_tag>().end())
2360 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA, "Problem %s not fond",
2361 name.c_str());
2362
2363 // get reference to number of ghost dofs
2364 int &nb_row_ghost_dofs = p_miit->nbGhostDofsRow;
2365 int &nb_col_ghost_dofs = p_miit->nbGhostDofsCol;
2366 nb_row_ghost_dofs = 0;
2367 nb_col_ghost_dofs = 0;
2368
2369 // do work if more than one processor
2370 if (m_field.get_comm_size() > 1) {
2371
2373 ghost_idx_col_view;
2374
2375 // get elements on this partition
2376 auto fe_range =
2377 p_miit->numeredFiniteElementsPtr->get<Part_mi_tag>().equal_range(
2378 m_field.get_comm_rank());
2379
2380 // get dofs on elements which are not part of this partition
2381
2382 struct Inserter {
2383 using Vec = std::vector<boost::shared_ptr<NumeredDofEntity>>;
2384 using It = Vec::iterator;
2385 It operator()(Vec &dofs_view, It &hint,
2386 boost::shared_ptr<NumeredDofEntity> &&dof) {
2387 dofs_view.emplace_back(dof);
2388 return dofs_view.end();
2389 }
2390 };
2391
2392 // rows
2393 std::vector<boost::shared_ptr<NumeredDofEntity>> fe_vec_view;
2394 auto hint_r = ghost_idx_row_view.begin();
2395 for (auto fe_ptr = fe_range.first; fe_ptr != fe_range.second; ++fe_ptr) {
2396
2397 fe_vec_view.clear();
2398 CHKERR EntFiniteElement::getDofView((*fe_ptr)->getRowFieldEnts(),
2399 *(p_miit->getNumeredRowDofsPtr()),
2400 fe_vec_view, Inserter());
2401
2402 for (auto &dof_ptr : fe_vec_view) {
2403 if (dof_ptr->getPart() != (unsigned int)m_field.get_comm_rank()) {
2404 hint_r = ghost_idx_row_view.emplace_hint(hint_r, dof_ptr);
2405 }
2406 }
2407 }
2408
2409 // columns
2410 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2411
2412 auto hint_c = ghost_idx_col_view.begin();
2413 for (auto fe_ptr = fe_range.first; fe_ptr != fe_range.second; ++fe_ptr) {
2414
2415 fe_vec_view.clear();
2416 CHKERR EntFiniteElement::getDofView((*fe_ptr)->getColFieldEnts(),
2417 *(p_miit->getNumeredColDofsPtr()),
2418 fe_vec_view, Inserter());
2419
2420 for (auto &dof_ptr : fe_vec_view) {
2421 if (dof_ptr->getPart() != (unsigned int)m_field.get_comm_rank()) {
2422 hint_c = ghost_idx_col_view.emplace_hint(hint_c, dof_ptr);
2423 }
2424 }
2425 }
2426 }
2427
2428 int *nb_ghost_dofs[2] = {&nb_row_ghost_dofs, &nb_col_ghost_dofs};
2429 int nb_local_dofs[2] = {p_miit->nbLocDofsRow, p_miit->nbLocDofsCol};
2430
2432 &ghost_idx_row_view, &ghost_idx_col_view};
2433 NumeredDofEntityByUId *dof_by_uid_no_const[2] = {
2434 &p_miit->numeredRowDofsPtr->get<Unique_mi_tag>(),
2435 &p_miit->numeredColDofsPtr->get<Unique_mi_tag>()};
2436
2437 int loop_size = 2;
2438 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2439 loop_size = 1;
2440 }
2441
2442 // set local ghost dofs indices
2443 for (int ss = 0; ss != loop_size; ++ss) {
2444 for (auto &gid : *ghost_idx_view[ss]) {
2445 NumeredDofEntityByUId::iterator dof =
2446 dof_by_uid_no_const[ss]->find(gid->getLocalUniqueId());
2447 if (PetscUnlikely((*dof)->petscLocalDofIdx != (DofIdx)-1))
2448 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2449 "inconsistent data, ghost dof already set");
2450 bool success = dof_by_uid_no_const[ss]->modify(
2451 dof, NumeredDofEntity_local_idx_change(nb_local_dofs[ss]++));
2452 if (PetscUnlikely(!success))
2453 SETERRQ(m_field.get_comm(), MOFEM_OPERATION_UNSUCCESSFUL,
2454 "modification unsuccessful");
2455 (*nb_ghost_dofs[ss])++;
2456 }
2457 }
2458 if (loop_size == 1) {
2459 (*nb_ghost_dofs[1]) = (*nb_ghost_dofs[0]);
2460 }
2461 }
2462
2463 if (verb > QUIET) {
2464 MOFEM_LOG("SYNC", Sev::inform)
2465 << " FEs ghost dofs on problem " << p_miit->getName()
2466 << " Nb. ghost dof " << p_miit->getNbGhostDofsRow() << " by "
2467 << p_miit->getNbGhostDofsCol() << " Nb. local dof "
2468 << p_miit->getNbLocalDofsCol() << " by " << p_miit->getNbLocalDofsCol();
2469
2471 }
2472
2475}
2476
2479 int verb) {
2480 MoFEM::Interface &m_field = cOre;
2481 auto problems_ptr = m_field.get_problems();
2483
2485 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2486 "partition of problem not build");
2488 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2489 "partitions finite elements not build");
2490
2491 // get problem pointer
2492 typedef Problem_multiIndex::index<Problem_mi_tag>::type ProblemsByName;
2493 // find p_miit
2494 ProblemsByName &problems_set =
2495 const_cast<ProblemsByName &>(problems_ptr->get<Problem_mi_tag>());
2496 ProblemsByName::iterator p_miit = problems_set.find(name);
2497
2498 // get reference to number of ghost dofs
2499 // get number of local dofs
2500 DofIdx *nb_ghost_dofs[2] = {&(p_miit->nbGhostDofsRow),
2501 &(p_miit->nbGhostDofsCol)};
2502 DofIdx nb_local_dofs[2] = {p_miit->nbLocDofsRow, p_miit->nbLocDofsCol};
2503 for (int ss = 0; ss != 2; ++ss) {
2504 (*nb_ghost_dofs[ss]) = 0;
2505 }
2506
2507 // do work if more than one processor
2508 if (m_field.get_comm_size() > 1) {
2509 // determine if rows on columns are different from dofs on rows
2510 int loop_size = 2;
2511 if (p_miit->numeredColDofsPtr == p_miit->numeredRowDofsPtr) {
2512 loop_size = 1;
2513 }
2514
2515 typedef decltype(p_miit->numeredRowDofsPtr) NumbDofTypeSharedPtr;
2516 NumbDofTypeSharedPtr numered_dofs[] = {p_miit->numeredRowDofsPtr,
2517 p_miit->numeredColDofsPtr};
2518
2519 // iterate over dofs on rows and dofs on columns
2520 for (int ss = 0; ss != loop_size; ++ss) {
2521
2522 // create dofs view by uid
2523 auto r = numered_dofs[ss]->get<PetscLocalIdx_mi_tag>().equal_range(-1);
2524
2525 std::vector<NumeredDofEntity_multiIndex::iterator> ghost_idx_view;
2526 ghost_idx_view.reserve(std::distance(r.first, r.second));
2527 for (; r.first != r.second; ++r.first)
2528 ghost_idx_view.emplace_back(numered_dofs[ss]->project<0>(r.first));
2529
2530 auto cmp = [](auto a, auto b) {
2531 return (*a)->getLocalUniqueId() < (*b)->getLocalUniqueId();
2532 };
2533 sort(ghost_idx_view.begin(), ghost_idx_view.end(), cmp);
2534
2535 // iterate over dofs which have negative local index
2536 for (auto gid_it : ghost_idx_view) {
2537 bool success = numered_dofs[ss]->modify(
2538 gid_it, NumeredDofEntity_local_idx_change((nb_local_dofs[ss])++));
2539 if (!success)
2540 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
2541 "modification unsuccessful");
2542 ++(*nb_ghost_dofs[ss]);
2543 }
2544 }
2545 if (loop_size == 1) {
2546 (*nb_ghost_dofs[1]) = (*nb_ghost_dofs[0]);
2547 }
2548 }
2549
2550 if (verb > QUIET) {
2551 MOFEM_LOG("SYNC", Sev::inform)
2552 << " FEs ghost dofs on problem " << p_miit->getName()
2553 << " Nb. ghost dof " << p_miit->getNbGhostDofsRow() << " by "
2554 << p_miit->getNbGhostDofsCol() << " Nb. local dof "
2555 << p_miit->getNbLocalDofsCol() << " by " << p_miit->getNbLocalDofsCol();
2556
2558 }
2559
2562}
2563
2565 const std::string &fe_name,
2566 EntityHandle *meshset) const {
2567 MoFEM::Interface &m_field = cOre;
2568 const Problem *problem_ptr;
2569 const FiniteElement_multiIndex *fes_ptr;
2571
2572 CHKERR m_field.get_moab().create_meshset(MESHSET_SET, *meshset);
2573 CHKERR m_field.get_problem(prb_name, &problem_ptr);
2574 CHKERR m_field.get_finite_elements(&fes_ptr);
2575
2576 auto fe_miit = fes_ptr->get<FiniteElement_name_mi_tag>().find(fe_name);
2577 if (fe_miit != fes_ptr->get<FiniteElement_name_mi_tag>().end()) {
2578 auto fit =
2579 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>().lower_bound(
2581 0, (*fe_miit)->getFEUId()));
2582 auto hi_fe_it =
2583 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>().upper_bound(
2585 get_id_for_max_type<MBENTITYSET>(), (*fe_miit)->getFEUId()));
2586 std::vector<EntityHandle> fe_vec;
2587 fe_vec.reserve(std::distance(fit, hi_fe_it));
2588 for (; fit != hi_fe_it; fit++)
2589 fe_vec.push_back(fit->get()->getEnt());
2590 CHKERR m_field.get_moab().add_entities(*meshset, &*fe_vec.begin(),
2591 fe_vec.size());
2592 }
2593
2595}
2596
2599 const std::string &fe_name,
2600 PetscLayout *layout) const {
2601 MoFEM::Interface &m_field = cOre;
2602 const Problem *problem_ptr;
2604 CHKERR m_field.get_problem(name, &problem_ptr);
2605 CHKERR problem_ptr->getNumberOfElementsByNameAndPart(PETSC_COMM_WORLD,
2606 fe_name, layout);
2608}
2609
2611
2612 std::vector<boost::weak_ptr<NumeredDofEntity>> &vec_dof_view,
2613
2614 const std::string problem_name, RowColData rc, const std::string field_name,
2615 const Range ents, int bridge_dim, const int lo_coeff, const int hi_coeff,
2616 const int lo_order, const int hi_order, int verb, const bool debug
2617
2618) const {
2619 MoFEM::Interface &m_field = cOre;
2621
2622 switch (rc) {
2623 case ROW:
2624 case COL:
2625 break;
2626 default:
2627 SETERRQ(m_field.get_comm(), MOFEM_INVALID_DATA, "invalid RowColData");
2628 break;
2629 }
2630
2631 const Problem *prb_ptr;
2632 CHKERR m_field.get_problem(problem_name, &prb_ptr);
2633
2634 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
2635 prb_ptr->numeredRowDofsPtr, nullptr};
2636 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
2637 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
2638
2639 Range bridge_ents;
2640 CHKERR m_field.get_moab().get_adjacencies(
2641 ents, bridge_dim, false, bridge_ents, moab::Interface::UNION);
2642
2643 auto &moab = m_field.get_moab();
2644 const auto bit_number = m_field.get_field_bit_number(field_name);
2645 const auto nb_coeffs =
2647 const auto &side_dof_map = m_field.get_field_structure(field_name)
2648 ->getDofSideMap();
2649
2650 using NumeredDofEntity_it_view_multiIndex = multi_index_container<
2651
2652 NumeredDofEntity_multiIndex::iterator, indexed_by<sequenced<>>
2653
2654 >;
2655 NumeredDofEntity_it_view_multiIndex dofs_it_view;
2656
2657 for (auto pit = bridge_ents.const_pair_begin();
2658 pit != bridge_ents.const_pair_end(); ++pit) {
2659 auto lo = numered_dofs[rc]->get<Unique_mi_tag>().lower_bound(
2660 DofEntity::getLoFieldEntityUId(bit_number, pit->first));
2661 auto hi = numered_dofs[rc]->get<Unique_mi_tag>().upper_bound(
2662 DofEntity::getHiFieldEntityUId(bit_number, pit->second));
2663
2664 auto bride_type = moab.type_from_handle(pit->first);
2665
2666 for (; lo != hi; ++lo) {
2667 if ((*lo)->getDofCoeffIdx() >= lo_coeff &&
2668 (*lo)->getDofCoeffIdx() <= hi_coeff &&
2669 (*lo)->getDofOrder() >= lo_order &&
2670 (*lo)->getDofOrder() <= hi_order) {
2671 auto ent_dof_index = (*lo)->getEntDofIdx();
2672 auto side_it = side_dof_map.at(bride_type)
2673 .get<EntDofIdx_mi_tag>()
2674 .find(std::floor(static_cast<double>(ent_dof_index) /
2675 nb_coeffs));
2676 if (side_it !=
2677 side_dof_map.at(bride_type).get<EntDofIdx_mi_tag>().end()) {
2678 auto bridge_ent = (*lo)->getEnt();
2679 auto type = side_it->type;
2680 auto side = side_it->side;
2681 auto dim = CN::Dimension(type);
2682 EntityHandle side_ent = 0;
2683 CHKERR moab.side_element(bridge_ent, dim, side, side_ent);
2684 if (ents.find(side_ent) != ents.end()) {
2685 dofs_it_view.emplace_back(numered_dofs[rc]->project<0>(lo));
2686 }
2687 } else {
2688#ifndef NDEBUG
2689 MOFEM_LOG("SELF", Sev::error)
2690 << *m_field.get_field_structure(field_name);
2691 MOFEM_LOG("SELF", Sev::error)
2692 << "side not found for entity " << CN::EntityTypeName(bride_type);
2693 MOFEM_LOG("SELF", Sev::error)
2694 << "ent_dof_index / nb_coeffs "
2695 << std::floor(static_cast<double>(ent_dof_index) / nb_coeffs);
2696 MOFEM_LOG("SELF", Sev::error)
2697 << "side_dof_map.size() " << side_dof_map.size();
2698#endif // NDEBUG
2699 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2700 "side not found - you will get more information in debug");
2701 }
2702 }
2703 }
2704 }
2705
2706 if (verb > QUIET) {
2707 for (auto &dof : dofs_it_view)
2708 MOFEM_LOG("SYNC", Sev::noisy) << **dof;
2709 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
2710 }
2711
2712 vec_dof_view.reserve(vec_dof_view.size() + dofs_it_view.size());
2713 for (auto dit : dofs_it_view)
2714 vec_dof_view.push_back(*dit);
2715
2717}
2718
2720 const std::string problem_name, RowColData rc,
2721 std::vector<boost::weak_ptr<NumeredDofEntity>> &vec_dof_view, int verb,
2722 const bool debug) {
2723
2724 MoFEM::Interface &m_field = cOre;
2726
2727 switch (rc) {
2728 case ROW:
2729 case COL:
2730 break;
2731 default:
2732 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Should be row or column");
2733 }
2734
2735 const Problem *prb_ptr;
2736 CHKERR m_field.get_problem(problem_name, &prb_ptr);
2737
2738 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
2739 prb_ptr->numeredRowDofsPtr, nullptr};
2740 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
2741 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
2742
2743 int *nbdof_ptr[] = {&prb_ptr->nbDofsRow, &prb_ptr->nbDofsCol};
2744 int *local_nbdof_ptr[] = {&prb_ptr->nbLocDofsRow, &prb_ptr->nbLocDofsCol};
2745 int *ghost_nbdof_ptr[] = {&prb_ptr->nbGhostDofsRow, &prb_ptr->nbGhostDofsCol};
2746
2747 const int nb_init_row_dofs = prb_ptr->getNbDofsRow();
2748 const int nb_init_col_dofs = prb_ptr->getNbDofsCol();
2749 const int nb_init_loc_row_dofs = prb_ptr->getNbLocalDofsRow();
2750 const int nb_init_ghost_row_dofs = prb_ptr->getNbGhostDofsRow();
2751 const int nb_init_ghost_col_dofs = prb_ptr->getNbGhostDofsCol();
2752
2753 if (numered_dofs[rc]) {
2754
2755 if (verb >= NOISY)
2756 MOFEM_LOG_C("SYNC", Sev::noisy,
2757 "Number of DOFs in multi-index %d and to delete %d\n",
2758 numered_dofs[rc]->size(), vec_dof_view.size());
2759
2760 // erase dofs from problem
2761 for (auto weak_dit : vec_dof_view)
2762 if (auto dit = weak_dit.lock()) {
2763 numered_dofs[rc]->erase(dit->getLocalUniqueId());
2764 }
2765
2766 if (verb >= NOISY)
2767 MOFEM_LOG_C("SYNC", Sev::noisy,
2768 "Number of DOFs in multi-index after delete %d\n",
2769 numered_dofs[rc]->size());
2770
2771 // get current number of ghost dofs
2772 int nb_local_dofs = 0;
2773 int nb_ghost_dofs = 0;
2774 for (auto dit = numered_dofs[rc]->get<PetscLocalIdx_mi_tag>().begin();
2775 dit != numered_dofs[rc]->get<PetscLocalIdx_mi_tag>().end(); ++dit) {
2776 if ((*dit)->getPetscLocalDofIdx() >= 0 &&
2777 (*dit)->getPetscLocalDofIdx() < *(local_nbdof_ptr[rc]))
2778 ++nb_local_dofs;
2779 else if ((*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[rc]))
2780 ++nb_ghost_dofs;
2781 else
2782 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2783 "Impossible case. You could run problem on no distributed "
2784 "mesh. That is not implemented. Dof local index is %d",
2785 (*dit)->getPetscLocalDofIdx());
2786 }
2787
2788 // get indices
2789 auto get_indices_by_tag = [&](auto tag, auto &indices, bool only_local) {
2790 const int nb_dofs = numered_dofs[rc]->size();
2791 indices.clear();
2792 indices.reserve(nb_dofs);
2793 for (auto dit = numered_dofs[rc]->get<decltype(tag)>().begin();
2794 dit != numered_dofs[rc]->get<decltype(tag)>().end(); ++dit) {
2795 bool add = true;
2796 if (only_local) {
2797 if ((*dit)->getPetscLocalDofIdx() < 0 ||
2798 (*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[rc])) {
2799 add = false;
2800 }
2801 }
2802 if (add)
2803 indices.push_back(decltype(tag)::get_index(dit));
2804 }
2805 };
2806
2807 auto get_indices_by_uid = [&](auto tag, auto &indices) {
2808 const int nb_dofs = numered_dofs[rc]->size();
2809 indices.clear();
2810 indices.reserve(nb_dofs);
2811 for (auto dit = numered_dofs[rc]->begin(); dit != numered_dofs[rc]->end();
2812 ++dit)
2813 indices.push_back(decltype(tag)::get_index(dit));
2814 };
2815
2816 auto get_sub_ao = [&](auto sub_data) {
2817 if (rc == 0) {
2818 return sub_data->getSmartRowMap();
2819 } else {
2820 return sub_data->getSmartColMap();
2821 }
2822 };
2823
2824 auto set_sub_is_and_ao = [&rc, &prb_ptr](auto sub_data, auto is, auto ao) {
2825 if (rc == ROW) {
2826 sub_data->rowIs = is;
2827 sub_data->rowMap = ao;
2828 sub_data->colIs = is; // if square problem col is equal to row
2829 sub_data->colMap = ao;
2830 } else {
2831 sub_data->colIs = is;
2832 sub_data->colMap = ao;
2833 }
2834 };
2835
2836 auto apply_symmetry = [&rc, &prb_ptr](auto sub_data) {
2837 if (rc == ROW) {
2838 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
2839 sub_data->colIs = sub_data->getSmartRowIs();
2840 sub_data->colMap = sub_data->getSmartRowMap();
2841 }
2842 }
2843 };
2844
2845 auto concatenate_dofs = [&](auto tag, auto &indices,
2846 const auto local_only) {
2848 get_indices_by_tag(tag, indices, local_only);
2849
2851 // Create AO from app indices (i.e. old), to pestc indices (new after
2852 // remove)
2853 if (local_only)
2854 ao = createAOMapping(m_field.get_comm(), indices.size(),
2855 &*indices.begin(), PETSC_NULLPTR);
2856 else
2857 ao = createAOMapping(PETSC_COMM_SELF, indices.size(), &*indices.begin(),
2858 PETSC_NULLPTR);
2859
2860 // Set mapping to sub dm data
2861 if (local_only) {
2862 if (auto sub_data = prb_ptr->getSubData()) {
2863 // create is and then map it to main problem of sub-problem
2864 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
2865 &*indices.begin(), PETSC_COPY_VALUES);
2866 // get old app, i.e. oroginal befor sub indices, and ao, from app,
2867 // to petsc sub indices.
2868 auto sub_ao = get_sub_ao(sub_data);
2869 CHKERR AOPetscToApplicationIS(sub_ao, sub_is);
2870 sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
2871 // set new sub ao
2872 set_sub_is_and_ao(sub_data, sub_is, sub_ao);
2873 apply_symmetry(sub_data);
2874 } else {
2875 // create sub data
2876 prb_ptr->getSubData() = boost::make_shared<Problem::SubProblemData>();
2877 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
2878 &*indices.begin(), PETSC_COPY_VALUES);
2879 // set sub is ao
2880 set_sub_is_and_ao(prb_ptr->getSubData(), sub_is, ao);
2881 apply_symmetry(prb_ptr->getSubData());
2882 }
2883 }
2884
2885 get_indices_by_uid(tag, indices);
2886 CHKERR AOApplicationToPetsc(ao, indices.size(), &*indices.begin());
2887
2889 };
2890
2891 // set indices index
2892 auto set_concatenated_indices = [&]() {
2893 std::vector<int> global_indices;
2894 std::vector<int> local_indices;
2896 CHKERR concatenate_dofs(PetscGlobalIdx_mi_tag(), global_indices, true);
2897 CHKERR concatenate_dofs(PetscLocalIdx_mi_tag(), local_indices, false);
2898 auto gi = global_indices.begin();
2899 auto li = local_indices.begin();
2900 for (auto dit = numered_dofs[rc]->begin(); dit != numered_dofs[rc]->end();
2901 ++dit) {
2903 (*dit)->getPart(), (*dit)->getDofIdx(), *gi, *li);
2904 bool success = numered_dofs[rc]->modify(dit, mod);
2905 if (!success)
2906 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
2907 "can not set negative indices");
2908 ++gi;
2909 ++li;
2910 }
2912 };
2913 CHKERR set_concatenated_indices();
2914
2915 MPI_Allreduce(&nb_local_dofs, nbdof_ptr[rc], 1, MPI_INT, MPI_SUM,
2916 m_field.get_comm());
2917 *(local_nbdof_ptr[rc]) = nb_local_dofs;
2918 *(ghost_nbdof_ptr[rc]) = nb_ghost_dofs;
2919
2920 if (debug)
2921 for (auto dof : (*numered_dofs[rc])) {
2922 if (dof->getPetscGlobalDofIdx() < 0) {
2923 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2924 "Negative global idx");
2925 }
2926 if (dof->getPetscLocalDofIdx() < 0) {
2927 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
2928 "Negative local idx");
2929 }
2930 }
2931
2932 } else {
2933
2934 *(nbdof_ptr[1]) = *(nbdof_ptr[0]);
2935 *(local_nbdof_ptr[1]) = *(local_nbdof_ptr[0]);
2936 *(ghost_nbdof_ptr[1]) = *(ghost_nbdof_ptr[0]);
2937 }
2938
2939 if (verb > QUIET) {
2941 "WORLD", Sev::inform,
2942 "Removed DOFs from problem %s dofs [%d / %d (before %d / %d) global]",
2943 prb_ptr->getName().c_str(), prb_ptr->getNbDofsRow(),
2944 prb_ptr->getNbDofsCol(), nb_init_row_dofs, nb_init_col_dofs);
2945 MOFEM_LOG_C("SYNC", Sev::verbose,
2946 "Removed DOFs from problem %s dofs [ %d / %d "
2947 "(before %d / %d) local, %d / %d (before %d / %d)]",
2948 prb_ptr->getName().c_str(), prb_ptr->getNbLocalDofsRow(),
2949 prb_ptr->getNbLocalDofsCol(), nb_init_loc_row_dofs,
2950 nb_init_loc_row_dofs, prb_ptr->getNbGhostDofsRow(),
2951 prb_ptr->getNbGhostDofsCol(), nb_init_ghost_row_dofs,
2952 nb_init_ghost_col_dofs);
2953 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
2954 }
2955
2957}
2958
2960 const std::string problem_name, const std::string field_name,
2961 const Range ents, const int lo_coeff, const int hi_coeff,
2962 const int lo_order, const int hi_order, int verb, const bool debug) {
2963
2964 MoFEM::Interface &m_field = cOre;
2966
2967 const Problem *prb_ptr;
2968 CHKERR m_field.get_problem(problem_name, &prb_ptr);
2969
2970 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
2971 prb_ptr->numeredRowDofsPtr, nullptr};
2972 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
2973 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
2974
2975 int *nbdof_ptr[] = {&prb_ptr->nbDofsRow, &prb_ptr->nbDofsCol};
2976 int *local_nbdof_ptr[] = {&prb_ptr->nbLocDofsRow, &prb_ptr->nbLocDofsCol};
2977 int *ghost_nbdof_ptr[] = {&prb_ptr->nbGhostDofsRow, &prb_ptr->nbGhostDofsCol};
2978
2979 const int nb_init_row_dofs = prb_ptr->getNbDofsRow();
2980 const int nb_init_col_dofs = prb_ptr->getNbDofsCol();
2981 const int nb_init_loc_row_dofs = prb_ptr->getNbLocalDofsRow();
2982 // const int nb_init_loc_col_dofs = prb_ptr->getNbLocalDofsCol();
2983 const int nb_init_ghost_row_dofs = prb_ptr->getNbGhostDofsRow();
2984 const int nb_init_ghost_col_dofs = prb_ptr->getNbGhostDofsCol();
2985
2986 for (int s = 0; s != 2; ++s)
2987 if (numered_dofs[s]) {
2988
2989 using NumeredDofEntity_it_view_multiIndex = multi_index_container<
2990
2991 NumeredDofEntity_multiIndex::iterator, indexed_by<sequenced<>>
2992
2993 >;
2994
2995 const auto bit_number = m_field.get_field_bit_number(field_name);
2996 NumeredDofEntity_it_view_multiIndex dofs_it_view;
2997
2998 // Set -1 to global and local dofs indices
2999 for (auto pit = ents.const_pair_begin(); pit != ents.const_pair_end();
3000 ++pit) {
3001 auto lo = numered_dofs[s]->get<Unique_mi_tag>().lower_bound(
3002 DofEntity::getLoFieldEntityUId(bit_number, pit->first));
3003 auto hi = numered_dofs[s]->get<Unique_mi_tag>().upper_bound(
3004 DofEntity::getHiFieldEntityUId(bit_number, pit->second));
3005
3006 for (; lo != hi; ++lo)
3007 if ((*lo)->getDofCoeffIdx() >= lo_coeff &&
3008 (*lo)->getDofCoeffIdx() <= hi_coeff &&
3009 (*lo)->getDofOrder() >= lo_order &&
3010 (*lo)->getDofOrder() <= hi_order)
3011 dofs_it_view.emplace_back(numered_dofs[s]->project<0>(lo));
3012 }
3013
3014 if (verb > QUIET) {
3015 for (auto &dof : dofs_it_view)
3016 MOFEM_LOG("SYNC", Sev::noisy) << **dof;
3017 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::noisy);
3018 }
3019
3020 // create weak view
3021 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_weak_view;
3022 dofs_weak_view.reserve(dofs_it_view.size());
3023 for (auto dit : dofs_it_view)
3024 dofs_weak_view.push_back(*dit);
3025
3026 if (verb >= NOISY)
3027 MOFEM_LOG_C("SYNC", Sev::noisy,
3028 "Number of DOFs in multi-index %d and to delete %d\n",
3029 numered_dofs[s]->size(), dofs_it_view.size());
3030
3031 // erase dofs from problem
3032 for (auto weak_dit : dofs_weak_view)
3033 if (auto dit = weak_dit.lock()) {
3034 numered_dofs[s]->erase(dit->getLocalUniqueId());
3035 }
3036
3037 if (verb >= NOISY)
3038 MOFEM_LOG_C("SYNC", Sev::noisy,
3039 "Number of DOFs in multi-index after delete %d\n",
3040 numered_dofs[s]->size());
3041
3042 // get current number of ghost dofs
3043 int nb_local_dofs = 0;
3044 int nb_ghost_dofs = 0;
3045 for (auto dit = numered_dofs[s]->get<PetscLocalIdx_mi_tag>().begin();
3046 dit != numered_dofs[s]->get<PetscLocalIdx_mi_tag>().end(); ++dit) {
3047 if ((*dit)->getPetscLocalDofIdx() >= 0 &&
3048 (*dit)->getPetscLocalDofIdx() < *(local_nbdof_ptr[s]))
3049 ++nb_local_dofs;
3050 else if ((*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[s]))
3051 ++nb_ghost_dofs;
3052 else
3053 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3054 "Impossible case. You could run problem on no distributed "
3055 "mesh. That is not implemented. Dof local index is %d",
3056 (*dit)->getPetscLocalDofIdx());
3057 }
3058
3059 // get indices
3060 auto get_indices_by_tag = [&](auto tag, auto &indices, bool only_local) {
3061 const int nb_dofs = numered_dofs[s]->size();
3062 indices.clear();
3063 indices.reserve(nb_dofs);
3064 for (auto dit = numered_dofs[s]->get<decltype(tag)>().begin();
3065 dit != numered_dofs[s]->get<decltype(tag)>().end(); ++dit) {
3066 bool add = true;
3067 if (only_local) {
3068 if ((*dit)->getPetscLocalDofIdx() < 0 ||
3069 (*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[s])) {
3070 add = false;
3071 }
3072 }
3073 if (add)
3074 indices.push_back(decltype(tag)::get_index(dit));
3075 }
3076 };
3077
3078 auto get_indices_by_uid = [&](auto tag, auto &indices) {
3079 const int nb_dofs = numered_dofs[s]->size();
3080 indices.clear();
3081 indices.reserve(nb_dofs);
3082 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3083 ++dit)
3084 indices.push_back(decltype(tag)::get_index(dit));
3085 };
3086
3087 auto get_sub_ao = [&](auto sub_data) {
3088 if (s == 0) {
3089 return sub_data->getSmartRowMap();
3090 } else {
3091 return sub_data->getSmartColMap();
3092 }
3093 };
3094
3095 auto set_sub_is_and_ao = [&s, &prb_ptr](auto sub_data, auto is, auto ao) {
3096 if (s == 0) {
3097 sub_data->rowIs = is;
3098 sub_data->rowMap = ao;
3099 sub_data->colIs = is; // if square problem col is equal to row
3100 sub_data->colMap = ao;
3101 } else {
3102 sub_data->colIs = is;
3103 sub_data->colMap = ao;
3104 }
3105 };
3106
3107 auto apply_symmetry = [&s, &prb_ptr](auto sub_data) {
3108 if (s == 0) {
3109 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
3110 sub_data->colIs = sub_data->getSmartRowIs();
3111 sub_data->colMap = sub_data->getSmartRowMap();
3112 }
3113 }
3114 };
3115
3116 auto concatenate_dofs = [&](auto tag, auto &indices,
3117 const auto local_only) {
3119 get_indices_by_tag(tag, indices, local_only);
3120
3122 // Create AO from app indices (i.e. old), to pestc indices (new after
3123 // remove)
3124 if (local_only)
3125 ao = createAOMapping(m_field.get_comm(), indices.size(),
3126 &*indices.begin(), PETSC_NULLPTR);
3127 else
3128 ao = createAOMapping(PETSC_COMM_SELF, indices.size(),
3129 &*indices.begin(), PETSC_NULLPTR);
3130
3131 // Set mapping to sub dm data
3132 if (local_only) {
3133 if (auto sub_data = prb_ptr->getSubData()) {
3134 // create is and then map it to main problem of sub-problem
3135 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
3136 &*indices.begin(), PETSC_COPY_VALUES);
3137 // get old app, i.e. oroginal befor sub indices, and ao, from app,
3138 // to petsc sub indices.
3139 auto sub_ao = get_sub_ao(sub_data);
3140 CHKERR AOPetscToApplicationIS(sub_ao, sub_is);
3141 sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
3142 // set new sub ao
3143 set_sub_is_and_ao(sub_data, sub_is, sub_ao);
3144 apply_symmetry(sub_data);
3145 } else {
3146 // create sub data
3147 prb_ptr->getSubData() =
3148 boost::make_shared<Problem::SubProblemData>();
3149 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
3150 &*indices.begin(), PETSC_COPY_VALUES);
3151 // set sub is ao
3152 set_sub_is_and_ao(prb_ptr->getSubData(), sub_is, ao);
3153 apply_symmetry(prb_ptr->getSubData());
3154 }
3155 }
3156
3157 get_indices_by_uid(tag, indices);
3158 CHKERR AOApplicationToPetsc(ao, indices.size(), &*indices.begin());
3159
3161 };
3162
3163 // set indices index
3164 auto set_concatenated_indices = [&]() {
3165 std::vector<int> global_indices;
3166 std::vector<int> local_indices;
3168 CHKERR concatenate_dofs(PetscGlobalIdx_mi_tag(), global_indices, true);
3169 CHKERR concatenate_dofs(PetscLocalIdx_mi_tag(), local_indices, false);
3170 auto gi = global_indices.begin();
3171 auto li = local_indices.begin();
3172 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3173 ++dit) {
3175 (*dit)->getPart(), (*dit)->getDofIdx(), *gi, *li);
3176 bool success = numered_dofs[s]->modify(dit, mod);
3177 if (!success)
3178 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3179 "can not set negative indices");
3180 ++gi;
3181 ++li;
3182 }
3184 };
3185 CHKERR set_concatenated_indices();
3186
3187 MPI_Allreduce(&nb_local_dofs, nbdof_ptr[s], 1, MPI_INT, MPI_SUM,
3188 m_field.get_comm());
3189 *(local_nbdof_ptr[s]) = nb_local_dofs;
3190 *(ghost_nbdof_ptr[s]) = nb_ghost_dofs;
3191
3192 if (debug)
3193 for (auto dof : (*numered_dofs[s])) {
3194 if (dof->getPetscGlobalDofIdx() < 0) {
3195 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
3196 "Negative global idx");
3197 }
3198 if (dof->getPetscLocalDofIdx() < 0) {
3199 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
3200 "Negative local idx");
3201 }
3202 }
3203
3204 } else {
3205
3206 *(nbdof_ptr[1]) = *(nbdof_ptr[0]);
3207 *(local_nbdof_ptr[1]) = *(local_nbdof_ptr[0]);
3208 *(ghost_nbdof_ptr[1]) = *(ghost_nbdof_ptr[0]);
3209 }
3210
3211 if (verb > QUIET) {
3213 "WORLD", Sev::inform,
3214 "Removed DOFs from problem %s dofs [%d / %d (before %d / %d) global]",
3215 prb_ptr->getName().c_str(), prb_ptr->getNbDofsRow(),
3216 prb_ptr->getNbDofsCol(), nb_init_row_dofs, nb_init_col_dofs);
3217 MOFEM_LOG_C("SYNC", Sev::verbose,
3218 "Removed DOFs from problem %s dofs [ %d / %d "
3219 "(before %d / %d) local, %d / %d (before %d / %d)]",
3220 prb_ptr->getName().c_str(), prb_ptr->getNbLocalDofsRow(),
3221 prb_ptr->getNbLocalDofsCol(), nb_init_loc_row_dofs,
3222 nb_init_loc_row_dofs, prb_ptr->getNbGhostDofsRow(),
3223 prb_ptr->getNbGhostDofsCol(), nb_init_ghost_row_dofs,
3224 nb_init_ghost_col_dofs);
3225 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
3226 }
3227
3229}
3230
3232 const std::string problem_name, const std::string field_name,
3233 const Range ents, const int lo_coeff, const int hi_coeff,
3234 const int lo_order, const int hi_order, int verb, const bool debug) {
3235
3236 MoFEM::Interface &m_field = cOre;
3238
3239 const Problem *prb_ptr;
3240 CHKERR m_field.get_problem(problem_name, &prb_ptr);
3241
3242 decltype(prb_ptr->numeredRowDofsPtr) numered_dofs[2] = {
3243 prb_ptr->numeredRowDofsPtr, nullptr};
3244 if (prb_ptr->numeredRowDofsPtr != prb_ptr->numeredColDofsPtr)
3245 numered_dofs[1] = prb_ptr->numeredColDofsPtr;
3246
3247 int *nbdof_ptr[] = {&prb_ptr->nbDofsRow, &prb_ptr->nbDofsCol};
3248 int *local_nbdof_ptr[] = {&prb_ptr->nbLocDofsRow, &prb_ptr->nbLocDofsCol};
3249 int *ghost_nbdof_ptr[] = {&prb_ptr->nbGhostDofsRow, &prb_ptr->nbGhostDofsCol};
3250
3251 const int nb_init_row_dofs = prb_ptr->getNbDofsRow();
3252 const int nb_init_col_dofs = prb_ptr->getNbDofsCol();
3253 const int nb_init_loc_row_dofs = prb_ptr->getNbLocalDofsRow();
3254 // const int nb_init_loc_col_dofs = prb_ptr->getNbLocalDofsCol();
3255 const int nb_init_ghost_row_dofs = prb_ptr->getNbGhostDofsRow();
3256 const int nb_init_ghost_col_dofs = prb_ptr->getNbGhostDofsCol();
3257
3258 const std::array<int, 2> nb_init_dofs = {nb_init_row_dofs, nb_init_col_dofs};
3259
3260 for (int s = 0; s != 2; ++s)
3261 if (numered_dofs[s]) {
3262
3263 typedef multi_index_container<
3264
3265 NumeredDofEntity_multiIndex::iterator, indexed_by<sequenced<>>
3266
3267 >
3268 NumeredDofEntity_it_view_multiIndex;
3269
3270 const auto bit_number = m_field.get_field_bit_number(field_name);
3271 NumeredDofEntity_it_view_multiIndex dofs_it_view;
3272
3273 // Set -1 to global and local dofs indices
3274 for (auto pit = ents.const_pair_begin(); pit != ents.const_pair_end();
3275 ++pit) {
3276 auto lo = numered_dofs[s]->get<Unique_mi_tag>().lower_bound(
3277 DofEntity::getLoFieldEntityUId(bit_number, pit->first));
3278 auto hi = numered_dofs[s]->get<Unique_mi_tag>().upper_bound(
3279 DofEntity::getHiFieldEntityUId(bit_number, pit->second));
3280
3281 for (; lo != hi; ++lo)
3282 if ((*lo)->getDofCoeffIdx() >= lo_coeff &&
3283 (*lo)->getDofCoeffIdx() <= hi_coeff &&
3284 (*lo)->getDofOrder() >= lo_order &&
3285 (*lo)->getDofOrder() <= hi_order)
3286 dofs_it_view.emplace_back(numered_dofs[s]->project<0>(lo));
3287 }
3288
3289 if (verb > QUIET) {
3290 for (auto &dof : dofs_it_view)
3291 MOFEM_LOG("SYNC", Sev::noisy) << **dof;
3292 }
3293
3294 // set negative index
3295 auto mod = NumeredDofEntity_part_and_all_indices_change(-1, -1, -1, -1);
3296 for (auto dit : dofs_it_view) {
3297 bool success = numered_dofs[s]->modify(dit, mod);
3298 if (!success)
3299 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3300 "can not set negative indices");
3301 }
3302
3303 // create weak view
3304 std::vector<boost::weak_ptr<NumeredDofEntity>> dosf_weak_view;
3305 dosf_weak_view.reserve(dofs_it_view.size());
3306 for (auto dit : dofs_it_view)
3307 dosf_weak_view.push_back(*dit);
3308
3309 if (verb >= NOISY)
3310 MOFEM_LOG_C("SYNC", Sev::noisy,
3311 "Number of DOFs in multi-index %d and to delete %d\n",
3312 numered_dofs[s]->size(), dofs_it_view.size());
3313
3314 // erase dofs from problem
3315 for (auto weak_dit : dosf_weak_view)
3316 if (auto dit = weak_dit.lock()) {
3317 numered_dofs[s]->erase(dit->getLocalUniqueId());
3318 }
3319
3320 if (verb >= NOISY)
3321 MOFEM_LOG_C("SYNC", Sev::noisy,
3322 "Number of DOFs in multi-index after delete %d\n",
3323 numered_dofs[s]->size());
3324
3325 // get current number of ghost dofs
3326 int nb_global_dof = 0;
3327 int nb_local_dofs = 0;
3328 int nb_ghost_dofs = 0;
3329
3330 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3331 ++dit) {
3332
3333 if ((*dit)->getDofIdx() >= 0) {
3334
3335 if ((*dit)->getPetscLocalDofIdx() >= 0 &&
3336 (*dit)->getPetscLocalDofIdx() < *(local_nbdof_ptr[s]))
3337 ++nb_local_dofs;
3338 else if ((*dit)->getPetscLocalDofIdx() >= *(local_nbdof_ptr[s]))
3339 ++nb_ghost_dofs;
3340
3341 ++nb_global_dof;
3342 }
3343 }
3344
3345 if (debug) {
3346 MPI_Allreduce(&nb_local_dofs, nbdof_ptr[s], 1, MPI_INT, MPI_SUM,
3347 m_field.get_comm());
3348 if (*(nbdof_ptr[s]) != nb_global_dof)
3349 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3350 "Number of local DOFs do not add up %d != %d",
3351 *(nbdof_ptr[s]), nb_global_dof);
3352 }
3353
3354 *(nbdof_ptr[s]) = nb_global_dof;
3355 *(local_nbdof_ptr[s]) = nb_local_dofs;
3356 *(ghost_nbdof_ptr[s]) = nb_ghost_dofs;
3357
3358 // get indices
3359 auto get_indices_by_tag = [&](auto tag) {
3360 std::vector<int> indices;
3361 indices.resize(nb_init_dofs[s], -1);
3362 for (auto dit = numered_dofs[s]->get<Idx_mi_tag>().lower_bound(0);
3363 dit != numered_dofs[s]->get<Idx_mi_tag>().end(); ++dit) {
3364 indices[(*dit)->getDofIdx()] = decltype(tag)::get_index(dit);
3365 }
3366 return indices;
3367 };
3368
3369 auto renumber = [&](auto tag, auto &indices) {
3371 int idx = 0;
3372 for (auto dit = numered_dofs[s]->get<decltype(tag)>().lower_bound(0);
3373 dit != numered_dofs[s]->get<decltype(tag)>().end(); ++dit) {
3374 indices[(*dit)->getDofIdx()] = idx++;
3375 }
3377 };
3378
3379 auto get_sub_ao = [&](auto sub_data) {
3380 if (s == 0) {
3381 return sub_data->getSmartRowMap();
3382 } else {
3383 return sub_data->getSmartColMap();
3384 }
3385 };
3386
3387 auto set_sub_is_and_ao = [&s, &prb_ptr](auto sub_data, auto is, auto ao) {
3388 if (s == 0) {
3389 sub_data->rowIs = is;
3390 sub_data->rowMap = ao;
3391 sub_data->colIs = is;
3392 sub_data->colMap = ao;
3393 } else {
3394 sub_data->colIs = is;
3395 sub_data->colMap = ao;
3396 }
3397 };
3398
3399 auto apply_symmetry = [&s, &prb_ptr](auto sub_data) {
3400 if (s == 0) {
3401 if (prb_ptr->numeredRowDofsPtr == prb_ptr->numeredColDofsPtr) {
3402 sub_data->colIs = sub_data->getSmartRowIs();
3403 sub_data->colMap = sub_data->getSmartRowMap();
3404 }
3405 }
3406 };
3407
3408 auto set_sub_data = [&](auto &indices) {
3410 if (auto sub_data = prb_ptr->getSubData()) {
3411 // create is and then map it to main problem of sub-problem
3412 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
3413 &*indices.begin(), PETSC_COPY_VALUES);
3414 // get old app, i.e. oroginal befor sub indices, and ao, from
3415 // app, to petsc sub indices.
3416 auto sub_ao = get_sub_ao(sub_data);
3417 CHKERR AOPetscToApplicationIS(sub_ao, sub_is);
3418 sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
3419 // set new sub ao
3420 set_sub_is_and_ao(sub_data, sub_is, sub_ao);
3421 apply_symmetry(sub_data);
3422 } else {
3423 prb_ptr->getSubData() = boost::make_shared<Problem::SubProblemData>();
3424 auto sub_is = createISGeneral(m_field.get_comm(), indices.size(),
3425 &*indices.begin(), PETSC_COPY_VALUES);
3426 auto sub_ao = createAOMappingIS(sub_is, PETSC_NULLPTR);
3427 // set sub is ao
3428 set_sub_is_and_ao(prb_ptr->getSubData(), sub_is, sub_ao);
3429 apply_symmetry(prb_ptr->getSubData());
3430 }
3432 };
3433
3434 auto global_indices = get_indices_by_tag(PetscGlobalIdx_mi_tag());
3435 auto local_indices = get_indices_by_tag(PetscLocalIdx_mi_tag());
3436 CHKERR set_sub_data(global_indices);
3437 CHKERR renumber(PetscGlobalIdx_mi_tag(), global_indices);
3438 CHKERR renumber(PetscLocalIdx_mi_tag(), local_indices);
3439
3440 int i = 0;
3441 for (auto dit = numered_dofs[s]->begin(); dit != numered_dofs[s]->end();
3442 ++dit) {
3443 auto idx = (*dit)->getDofIdx();
3444 if (idx >= 0) {
3446 (*dit)->getPart(), i++, global_indices[idx], local_indices[idx]);
3447 bool success = numered_dofs[s]->modify(dit, mod);
3448 if (!success)
3449 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3450 "can not set negative indices");
3451 } else {
3453 (*dit)->getPart(), -1, -1, -1);
3454 bool success = numered_dofs[s]->modify(dit, mod);
3455 if (!success)
3456 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
3457 "can not set negative indices");
3458 }
3459 };
3460
3461 if (debug) {
3462 for (auto dof : (*numered_dofs[s])) {
3463 if (dof->getDofIdx() >= 0 && dof->getPetscGlobalDofIdx() < 0) {
3464 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3465 "Negative global idx");
3466 }
3467 }
3468 }
3469
3470 } else {
3471
3472 *(nbdof_ptr[1]) = *(nbdof_ptr[0]);
3473 *(local_nbdof_ptr[1]) = *(local_nbdof_ptr[0]);
3474 *(ghost_nbdof_ptr[1]) = *(ghost_nbdof_ptr[0]);
3475 }
3476
3477 if (verb >= NOISY)
3479
3480 if (verb > QUIET) {
3482 "WORLD", Sev::inform,
3483 "Removed DOFs from problem %s dofs [%d / %d (before %d / %d) global]",
3484 prb_ptr->getName().c_str(), prb_ptr->getNbDofsRow(),
3485 prb_ptr->getNbDofsCol(), nb_init_row_dofs, nb_init_col_dofs);
3486 MOFEM_LOG_C("SYNC", Sev::verbose,
3487 "Removed DOFs from problem %s dofs [ %d / %d "
3488 "(before %d / %d) local, %d / %d (before %d / %d)]",
3489 prb_ptr->getName().c_str(), prb_ptr->getNbLocalDofsRow(),
3490 prb_ptr->getNbLocalDofsCol(), nb_init_loc_row_dofs,
3491 nb_init_loc_row_dofs, prb_ptr->getNbGhostDofsRow(),
3492 prb_ptr->getNbGhostDofsCol(), nb_init_ghost_row_dofs,
3493 nb_init_ghost_col_dofs);
3495 }
3497}
3498
3500 const std::string problem_name, const std::string field_name,
3501 const BitRefLevel bit_ref_level, const BitRefLevel bit_ref_mask,
3502 Range *ents_ptr, const int lo_coeff, const int hi_coeff, const int lo_order,
3503 const int hi_order, int verb, const bool debug) {
3504 MoFEM::Interface &m_field = cOre;
3506
3507 auto bit_manager = m_field.getInterface<BitRefManager>();
3508
3509 Range ents;
3510 if (ents_ptr) {
3511 ents = *ents_ptr;
3512 CHKERR bit_manager->filterEntitiesByRefLevel(bit_ref_level, bit_ref_mask,
3513 ents, verb);
3514 } else {
3515 CHKERR bit_manager->getEntitiesByRefLevel(bit_ref_level, bit_ref_mask, ents,
3516 verb);
3517 }
3518
3519 CHKERR removeDofsOnEntities(problem_name, field_name, ents, lo_coeff,
3520 hi_coeff, lo_order, hi_order, verb, debug);
3521
3523}
3524
3526 const std::string problem_name, const std::string field_name,
3527 const BitRefLevel bit_ref_level, const BitRefLevel bit_ref_mask,
3528 Range *ents_ptr, const int lo_coeff, const int hi_coeff, const int lo_order,
3529 const int hi_order, int verb, const bool debug) {
3530 MoFEM::Interface &m_field = cOre;
3532
3533 auto bit_manager = m_field.getInterface<BitRefManager>();
3534
3535 Range ents;
3536 if (ents_ptr) {
3537 ents = *ents_ptr;
3538 CHKERR bit_manager->filterEntitiesByRefLevel(bit_ref_level, bit_ref_mask,
3539 ents, verb);
3540 } else {
3541 CHKERR bit_manager->getEntitiesByRefLevel(bit_ref_level, bit_ref_mask, ents,
3542 verb);
3543 }
3544
3546 lo_coeff, hi_coeff, lo_order,
3547 hi_order, verb, debug);
3548
3550}
3551
3553ProblemsManager::markDofs(const std::string problem_name, RowColData rc,
3554 const enum MarkOP op, const Range ents,
3555 std::vector<unsigned char> &marker) const {
3556
3557 Interface &m_field = cOre;
3558 const Problem *problem_ptr;
3560 CHKERR m_field.get_problem(problem_name, &problem_ptr);
3561 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs;
3562 switch (rc) {
3563 case ROW:
3564 dofs = problem_ptr->getNumeredRowDofsPtr();
3565 break;
3566 case COL:
3567 dofs = problem_ptr->getNumeredColDofsPtr();
3568 default:
3569 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Should be row or column");
3570 }
3571 marker.resize(dofs->size(), 0);
3572 std::vector<unsigned char> marker_tmp;
3573
3574 switch (op) {
3575 case MarkOP::OR:
3576 for (auto p = ents.pair_begin(); p != ents.pair_end(); ++p) {
3577 auto lo = dofs->get<Ent_mi_tag>().lower_bound(p->first);
3578 auto hi = dofs->get<Ent_mi_tag>().upper_bound(p->second);
3579 for (; lo != hi; ++lo)
3580 marker[(*lo)->getPetscLocalDofIdx()] |= 1;
3581 }
3582 break;
3583 case MarkOP::AND:
3584 marker_tmp.resize(dofs->size(), 0);
3585 for (auto p = ents.pair_begin(); p != ents.pair_end(); ++p) {
3586 auto lo = dofs->get<Ent_mi_tag>().lower_bound(p->first);
3587 auto hi = dofs->get<Ent_mi_tag>().upper_bound(p->second);
3588 for (; lo != hi; ++lo)
3589 marker_tmp[(*lo)->getPetscLocalDofIdx()] = 1;
3590 }
3591 for (int i = 0; i != marker.size(); ++i) {
3592 marker[i] &= marker_tmp[i];
3593 }
3594 break;
3595 }
3596
3598}
3599
3601 const std::string problem_name, RowColData rc, const std::string field_name,
3602 const int lo, const int hi, const enum ProblemsManager::MarkOP op,
3603 const unsigned char c, std::vector<unsigned char> &marker) const {
3604
3605 Interface &m_field = cOre;
3606 const Problem *problem_ptr;
3608 CHKERR m_field.get_problem(problem_name, &problem_ptr);
3609 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs;
3610 switch (rc) {
3611 case ROW:
3612 dofs = problem_ptr->getNumeredRowDofsPtr();
3613 break;
3614 case COL:
3615 dofs = problem_ptr->getNumeredColDofsPtr();
3616 default:
3617 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Should be row or column");
3618 }
3619 marker.resize(dofs->size(), 0);
3620
3621 auto dof_lo = dofs->get<Unique_mi_tag>().lower_bound(
3623 auto dof_hi = dofs->get<Unique_mi_tag>().upper_bound(
3625
3626 auto marker_ref = [marker](auto &it) -> unsigned int & {
3627 return marker[(*it)->getPetscLocalDofIdx()];
3628 };
3629
3630 switch (op) {
3631 case MarkOP::OR:
3632 for (; dof_lo != dof_hi; ++dof_lo)
3633 if ((*dof_lo)->getDofCoeffIdx() >= lo &&
3634 (*dof_lo)->getDofCoeffIdx() <= hi)
3635 marker[(*dof_lo)->getPetscLocalDofIdx()] |= c;
3636 break;
3637 case MarkOP::AND:
3638 for (; dof_lo != dof_hi; ++dof_lo)
3639 if ((*dof_lo)->getDofCoeffIdx() >= lo &&
3640 (*dof_lo)->getDofCoeffIdx() <= hi)
3641 marker[(*dof_lo)->getPetscLocalDofIdx()] &= c;
3642 break;
3643 }
3644
3646}
3647
3649
3650 const std::string problem_name, RowColData rc,
3651 std::vector<boost::weak_ptr<NumeredDofEntity>> &vec_dof_view,
3652 const enum MarkOP op, std::vector<unsigned char> &marker
3653
3654) const {
3655 Interface &m_field = cOre;
3657
3658 const Problem *problem_ptr;
3659 CHKERR m_field.get_problem(problem_name, &problem_ptr);
3660 boost::shared_ptr<NumeredDofEntity_multiIndex> dofs;
3661 switch (rc) {
3662 case ROW:
3663 dofs = problem_ptr->getNumeredRowDofsPtr();
3664 break;
3665 case COL:
3666 dofs = problem_ptr->getNumeredColDofsPtr();
3667 break;
3668 default:
3669 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Should be row or column");
3670 }
3671 marker.resize(dofs->size(), 0);
3672
3673 for (auto &dof : vec_dof_view) {
3674 if (auto dof_ptr = dof.lock()) {
3675 if (op == MarkOP::OR)
3676 marker[dof_ptr->getPetscLocalDofIdx()] |= 1;
3677 else
3678 marker[dof_ptr->getPetscLocalDofIdx()] &= 1;
3679 }
3680 }
3681
3683}
3684
3686ProblemsManager::addFieldToEmptyFieldBlocks(const std::string problem_name,
3687 const std::string row_field,
3688 const std::string col_field) const {
3689
3690 Interface &m_field = cOre;
3692
3693 const auto problem_ptr = m_field.get_problem(problem_name);
3694 auto get_field_id = [&](const std::string field_name) {
3695 return m_field.get_field_structure(field_name)->getId();
3696 };
3697 const auto row_id = get_field_id(row_field);
3698 const auto col_id = get_field_id(col_field);
3699
3700 problem_ptr->addFieldToEmptyFieldBlocks(BlockFieldPair(row_id, col_id));
3701
3703}
3704
3705} // namespace MoFEM
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
#define ProblemManagerFunctionBegin
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 ...
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 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 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 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 add entities of finite element in 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 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.
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
static const bool debug
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:82
int & getBuildMoFEM() const
Get flags/semaphores for different stages.
Definition Core.hpp:225
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.
std::map< int, BaseFunction::DofsSideMap > & getDofSideMap() const
Get the dofs side map.
const BitFieldId & getId() const
Get unique field id.
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)
MoFEMErrorCode printPartitionedProblem(const Problem *problem_ptr, int verb=VERBOSE)
MoFEMErrorCode addFieldToEmptyFieldBlocks(const std::string problem_name, const std::string row_field, const std::string col_field) const
add empty block to problem
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
Mark DOFs.
PetscLogEvent MOFEM_EVENT_ProblemsManager
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 broke space.
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.
PetscBool synchroniseProblemEntities
DOFs in fields, not from DOFs on elements.
MoFEMErrorCode debugPartitionedProblem(const Problem *problem_ptr, int verb=VERBOSE)
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.
MoFEMErrorCode getOptions()
intrusive_ptr for managing petsc objects
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.