v0.15.0
Loading...
Searching...
No Matches
PCMGSetUpViaApproxOrders.cpp
Go to the documentation of this file.
1/** \file PCMGSetUpViaApproxOrders.cpp
2 * \brief implementation of multi-grid solver for p- adaptivity
3 */
4
5
6#undef PETSC_VERSION_RELEASE
7#define PETSC_VERSION_RELEASE 1
8
9#if PETSC_VERSION_GE(3, 6, 0)
10#include <petsc/private/petscimpl.h>
11#else
12#include <petsc-private/petscimpl.h>
13#endif
14
15#if PETSC_VERSION_GE(3, 6, 0)
16#include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
17// #include <petsc/private/vecimpl.h> /*I "petscdm.h" I*/
18#else
19#include <petsc-private/dmimpl.h> /*I "petscdm.h" I*/
20#include <petsc-private/vecimpl.h> /*I "petscdm.h" I*/
21#endif
22
23#include <DMMoFEM.hpp>
24#include <DMCtxImpl.hpp>
26
27namespace MoFEM {
28
30
31 PCMGSubMatrixCtx(Mat a, IS is);
32 virtual ~PCMGSubMatrixCtx() = default;
33
34 template <InsertMode MODE>
35 friend MoFEMErrorCode sub_mat_mult_generic(Mat a, Vec x, Vec f);
36 friend MoFEMErrorCode sub_mat_sor(Mat mat, Vec b, PetscReal omega,
37 MatSORType flag, PetscReal shift,
38 PetscInt its, PetscInt lits, Vec x);
39
41
47
48 PetscLogEvent MOFEM_EVENT_mult;
49 PetscLogEvent MOFEM_EVENT_sor;
50};
51
52PCMGSubMatrixCtx::PCMGSubMatrixCtx(Mat a, IS is) : A(a, true), iS(is, true) {
53 PetscLogEventRegister("PCMGSubMatrixCtx_mult", 0, &MOFEM_EVENT_mult);
54 PetscLogEventRegister("PCMGSubMatrixCtx_sor", 0, &MOFEM_EVENT_sor);
55}
56
59 if (sCat.use_count() == 0) {
60 auto [x_tmp, f_tmp] = matCreateVecs(A);
61 X = x_tmp;
62 F = f_tmp;
63 sCat = createVecScatter(X, iS, x, PETSC_NULLPTR);
64 }
66}
67
68/**
69 * \brief Structure for DM for multi-grid via approximation orders
70 * \ingroup dm
71 */
73
74 MoFEMErrorCode query_interface(boost::typeindex::type_index type_index,
75 MoFEM::UnknownInterface **iface) const;
76
79
81
84 std::vector<SmartPetscObj<IS>> coarseningIS; ///< Coarsening IS
85 std::vector<SmartPetscObj<Mat>> kspOperators; ///< Get KSP operators
86 boost::ptr_vector<PCMGSubMatrixCtx>
87 shellMatrixCtxPtr; ///< Shell sub-matrix context
88};
89
90/* \brief Set data structures of MG pre-conditioner via approximation orders
91 */
93
94 PCMGSetUpViaApproxOrdersCtx(DM dm, Mat a, bool shell_sub_a)
95 : dM(dm), A(a), nbLevels(2), coarseOrder(2), orderAtLastLevel(1000),
96 shellSubA(shell_sub_a), verboseLevel(0) {}
97
98 virtual ~PCMGSetUpViaApproxOrdersCtx() = default;
99
100 /**
101 * \brief get options from line command
102 * @return error code
103 */
104 virtual MoFEMErrorCode getOptions();
105
106 /**
107 * \brief Set IS for levels
108 * @param kk level
109 * @param is pointer to IS
110 * @return error code
111 */
112 virtual MoFEMErrorCode createIsAtLevel(int kk, IS *is);
113
114 /**
115 * \brief Destroy IS if internally created
116 * @param kk level
117 * @param is pointer to is
118 * @return error code
119 */
120 virtual MoFEMErrorCode destroyIsAtLevel(int kk, IS *is);
121
122 /**
123 * \brief Set up data structures for MG
124 * @param pc MG pre-conditioner
125 * <http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/PC/PCMG.html>
126 * @param verb verbosity level
127 * @return error code
128 */
129 virtual MoFEMErrorCode buildProlongationOperator(bool use_mat_a,
130 int verb = 0);
131
132 DM dM; ///< Distributed mesh manager
133 Mat A; ///< Matrix at fine level
134
135 int nbLevels; ///< number of multi-grid levels
136 int coarseOrder; ///< approximation order of coarse level
137 int orderAtLastLevel; ///< set maximal evaluated order
138
141};
142
143template <InsertMode MODE>
145 void *void_ctx;
147 CHKERR MatShellGetContext(a, &void_ctx);
148 PCMGSubMatrixCtx *ctx = (PCMGSubMatrixCtx *)void_ctx;
149 PetscLogEventBegin(ctx->MOFEM_EVENT_mult, 0, 0, 0, 0);
150 CHKERR ctx->initData(x);
151 CHKERR VecScatterBegin(ctx->sCat, x, ctx->X, INSERT_VALUES, SCATTER_REVERSE);
152 CHKERR VecScatterEnd(ctx->sCat, x, ctx->X, INSERT_VALUES, SCATTER_REVERSE);
153 CHKERR MatMult(ctx->A, ctx->X, ctx->F);
154 CHKERR VecScatterBegin(ctx->sCat, ctx->F, f, MODE, SCATTER_FORWARD);
155 CHKERR VecScatterEnd(ctx->sCat, ctx->F, f, MODE, SCATTER_FORWARD);
156 PetscLogEventEnd(ctx->MOFEM_EVENT_mult, 0, 0, 0, 0);
158}
159
160MoFEMErrorCode sub_mat_mult(Mat a, Vec x, Vec f) {
162}
163
166}
167
168MoFEMErrorCode sub_mat_sor(Mat mat, Vec b, PetscReal omega, MatSORType flag,
169 PetscReal shift, PetscInt its, PetscInt lits,
170 Vec x) {
171
172 //FIXME: that is crap implementation of SOR
173
174 void *void_ctx;
176 CHKERR MatShellGetContext(mat, &void_ctx);
177 PCMGSubMatrixCtx *ctx = (PCMGSubMatrixCtx *)void_ctx;
178 PetscLogEventBegin(ctx->MOFEM_EVENT_sor, 0, 0, 0, 0);
179 CHKERR ctx->initData(x);
180 CHKERR VecScatterBegin(ctx->sCat, b, ctx->X, INSERT_VALUES, SCATTER_REVERSE);
181 CHKERR VecScatterEnd(ctx->sCat, b, ctx->X, INSERT_VALUES, SCATTER_REVERSE);
182 CHKERR MatSOR(ctx->A, ctx->X, omega, flag, shift, its, lits, ctx->F);
183 CHKERR VecScatterBegin(ctx->sCat, ctx->F, x, INSERT_VALUES, SCATTER_FORWARD);
184 CHKERR VecScatterEnd(ctx->sCat, ctx->F, x, INSERT_VALUES, SCATTER_FORWARD);
185 PetscLogEventEnd(ctx->MOFEM_EVENT_sor, 0, 0, 0, 0);
187}
188
190
193 CHKERRABORT(PETSC_COMM_WORLD, ierr);
194}
195
205
207DMMGViaApproxOrdersCtx::query_interface(boost::typeindex::type_index type_index,
208 MoFEM::UnknownInterface **iface) const {
209 *iface = static_cast<DMMGViaApproxOrdersCtx *>(
210 const_cast<DMMGViaApproxOrdersCtx *>(this));
211 return 0;
212}
213
214#define GET_DM_FIELD(DM) \
215 auto dm_field = \
216 static_cast<DMCtx *>(DM->data)->getInterface<DMMGViaApproxOrdersCtx>(); \
217 NOT_USED(dm_field)
218
220 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
222 GET_DM_FIELD(dm);
223 dm_field->aO = SmartPetscObj<AO>(ao, true);
225}
226
228 bool create_sub_matrix,
229 bool shell_sub_a) {
230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
232 GET_DM_FIELD(dm);
233 dm_field->coarseningIS.emplace_back(SmartPetscObj<IS>(is, true));
234 dm_field->shellMatrixCtxPtr.push_back(new PCMGSubMatrixCtx(A, is));
235 if (is) {
236 auto is2 = SmartPetscObj<IS>(is, true);
237 if (dm_field->aO) {
238 is2 = isDuplicate(is);
239 CHKERR ISCopy(is, is2);
240 CHKERR AOApplicationToPetscIS(dm_field->aO, is2);
241 }
242 if (create_sub_matrix) {
243 if (shell_sub_a) {
244 int n, N;
245 CHKERR ISGetSize(is, &N);
246 CHKERR ISGetLocalSize(is, &n);
247 MPI_Comm comm;
248 CHKERR PetscObjectGetComm((PetscObject)A, &comm);
249 Mat sub_a_raw;
250 CHKERR MatCreateShell(comm, n, n, N, N,
251 &(dm_field->shellMatrixCtxPtr.back()),
252 &sub_a_raw);
253 CHKERR MatShellSetOperation(sub_a_raw, MATOP_MULT,
254 (void (*)(void))sub_mat_mult);
255 CHKERR MatShellSetOperation(sub_a_raw, MATOP_MULT_ADD,
256 (void (*)(void))sub_mat_mult_add);
257 CHKERR MatShellSetOperation(sub_a_raw, MATOP_SOR,
258 (void (*)(void))sub_mat_sor);
259 dm_field->kspOperators.emplace_back(
260 SmartPetscObj<Mat>(sub_a_raw, false));
261 } else {
262 Mat sub_a_raw;
263#if PETSC_VERSION_GE(3, 8, 0)
264 CHKERR MatCreateSubMatrix(A, is2, is2, MAT_INITIAL_MATRIX, &sub_a_raw);
265#else
266 CHKERR MatGetSubMatrix(A, is2, is2, MAT_INITIAL_MATRIX, &sub_a_raw);
267#endif
268 dm_field->kspOperators.emplace_back(
269 SmartPetscObj<Mat>(sub_a_raw, false));
270 }
271 } else {
272 dm_field->kspOperators.emplace_back(SmartPetscObj<Mat>(A, true));
273 }
274 } else {
275 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
276 }
277 PetscInfo(dm, "Push back IS to DMMGViaApproxOrders\n");
279}
280
282 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
284 GET_DM_FIELD(dm);
285 if (dm_field->coarseningIS.back()) {
286 dm_field->coarseningIS.pop_back();
287 }
288 dm_field->kspOperators.pop_back();
289 PetscInfo(dm, "Pop back IS to DMMGViaApproxOrders\n");
291}
292
294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
296 GET_DM_FIELD(dm);
297 CHKERR dm_field->destroyCoarseningIS();
298 PetscInfo(dm, "Clear DMs data structures\n");
300}
301
307
308static MoFEMErrorCode ksp_set_operators(KSP ksp, Mat A, Mat B, void *ctx) {
311}
312
314 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
316 if (!dm->data) {
317 dm->data = new DMMGViaApproxOrdersCtx();
318 } else {
319 ((DMCtxImpl *)(dm->data))->incrementReference();
320 }
322
323 dm->ops->creatematrix = DMCreateMatrix_MGViaApproxOrders;
324 dm->ops->createglobalvector = DMCreateGlobalVector_MGViaApproxOrders;
325 dm->ops->coarsen = DMCoarsen_MGViaApproxOrders;
326 dm->ops->createinterpolation = DMCreateInterpolation_MGViaApproxOrders;
327 dm->ops->destroy = DMDestroy_MGViaApproxOrders;
328
329 CHKERR DMKSPSetComputeOperators(dm, ksp_set_operators, NULL);
330#if PETSC_VERSION_GE(3, 17, 0)
331 PetscInfo(dm, "Create DMMGViaApproxOrders reference = %d\n",
332 ((DMCtxImpl *)(dm->data))->useCount());
333#else
334 PetscInfo1(dm, "Create DMMGViaApproxOrders reference = %d\n",
335 ((DMCtxImpl *)(dm->data))->useCount());
336#endif
338}
339
340PetscErrorCode DMDestroy_MGViaApproxOrders(DM dm) {
341 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
342 GET_DM_FIELD(dm);
344 CHKERR dm_field->destroyCoarseningIS();
347}
348
350
351 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
353 GET_DM_FIELD(dm);
354
355 int leveldown = dm->leveldown;
356
357 if (dm_field->kspOperators.empty()) {
359 } else {
360 MPI_Comm comm;
361 CHKERR PetscObjectGetComm((PetscObject)dm, &comm);
362 if (dm_field->kspOperators.empty()) {
363 SETERRQ(comm, MOFEM_DATA_INCONSISTENCY,
364 "data inconsistency, operator can not be set");
365 }
366 if (static_cast<int>(dm_field->kspOperators.size()) < leveldown) {
367 SETERRQ(comm, MOFEM_DATA_INCONSISTENCY,
368 "data inconsistency, no IS for that level");
369 }
370 *M = dm_field->kspOperators[dm_field->kspOperators.size() - 1 - leveldown];
371 CHKERR PetscObjectReference((PetscObject)*M);
372 CHKERR MatSetDM(*M, dm);
373 }
374
375#if PETSC_VERSION_GE(3, 17, 0)
376 PetscInfo(dm, "Create Matrix DMMGViaApproxOrders leveldown = %d\n",
377 leveldown);
378#else
379 PetscInfo1(dm, "Create Matrix DMMGViaApproxOrders leveldown = %d\n",
380 leveldown);
381#endif
382
384}
385
386MoFEMErrorCode DMCoarsen_MGViaApproxOrders(DM dm, MPI_Comm comm, DM *dmc) {
387 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
389 GET_DM_FIELD(dm);
390 CHKERR PetscObjectGetComm((PetscObject)dm, &comm);
391 CHKERR DMCreate(comm, dmc);
392 (*dmc)->data = dm->data;
393 DMType type;
394 CHKERR DMGetType(dm, &type);
395 CHKERR DMSetType(*dmc, type);
396 dm_field->coarsenDM = SmartPetscObj<DM>(*dmc, false);
397#if PETSC_VERSION_GE(3, 17, 0)
398 PetscInfo(dm, "Coarsen DMMGViaApproxOrders leveldown = %d\n", dm->leveldown);
399#else
400 PetscInfo1(dm, "Coarsen DMMGViaApproxOrders leveldown = %d\n", dm->leveldown);
401#endif
403}
404
406 Vec *vec) {
407 PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
408 PetscValidHeaderSpecific(dm2, DM_CLASSID, 1);
410
411 MPI_Comm comm;
412 CHKERR PetscObjectGetComm((PetscObject)dm1, &comm);
413
414 int m, n, M, N;
415
416 DM dm_down = dm1;
417 DM dm_up = dm2;
418
419 int dm_down_leveldown = dm_down->leveldown;
420 int dm_up_leveldown = dm_up->leveldown;
421#if PETSC_VERSION_GE(3, 17, 0)
422 PetscInfo(dm1,
423 "Create interpolation DMMGViaApproxOrders dm1_leveldown = %d "
424 "dm2_leveldown = %d\n",
425 dm_down_leveldown, dm_up_leveldown);
426#else
427 PetscInfo2(dm1,
428 "Create interpolation DMMGViaApproxOrders dm1_leveldown = %d "
429 "dm2_leveldown = %d\n",
430 dm_down_leveldown, dm_up_leveldown);
431#endif
432
433 IS is_down, is_up;
434 {
435 // Coarser mesh
436 GET_DM_FIELD(dm_down);
437 if (static_cast<int>(dm_field->coarseningIS.size()) < dm_down_leveldown) {
438 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
439 }
440 is_down = dm_field->coarseningIS[dm_field->coarseningIS.size() - 1 -
441 dm_down_leveldown];
442 CHKERR ISGetSize(is_down, &M);
443 CHKERR ISGetLocalSize(is_down, &m);
444 }
445 {
446 // Finer mesh
447 GET_DM_FIELD(dm_up);
448 if (static_cast<int>(dm_field->coarseningIS.size()) < dm_up_leveldown) {
449 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
450 }
451 is_up =
452 dm_field
453 ->coarseningIS[dm_field->coarseningIS.size() - 1 - dm_up_leveldown];
454 CHKERR ISGetSize(is_up, &N);
455 CHKERR ISGetLocalSize(is_up, &n);
456 }
457
458 // is_dow rows
459 // is_up columns
460
461 CHKERR MatCreate(comm, mat);
462 CHKERR MatSetSizes(*mat, m, n, M, N);
463 CHKERR MatSetType(*mat, MATMPIAIJ);
464 CHKERR MatMPIAIJSetPreallocation(*mat, 1, PETSC_NULLPTR, 0, PETSC_NULLPTR);
465
466 // get matrix layout
467 PetscLayout rmap, cmap;
468 CHKERR MatGetLayouts(*mat, &rmap, &cmap);
469 int rstart, rend, cstart, cend;
470 CHKERR PetscLayoutGetRange(rmap, &rstart, &rend);
471 CHKERR PetscLayoutGetRange(cmap, &cstart, &cend);
472
473 const int *row_indices_ptr, *col_indices_ptr;
474 CHKERR ISGetIndices(is_down, &row_indices_ptr);
475 CHKERR ISGetIndices(is_up, &col_indices_ptr);
476
477 map<int, int> idx_map;
478 for (int ii = 0; ii < m; ii++) {
479 idx_map[row_indices_ptr[ii]] = rstart + ii;
480 }
481
482 CHKERR MatZeroEntries(*mat);
483 // FIXME: Use MatCreateMPIAIJWithArrays and set array directly
484 for (int jj = 0; jj < n; jj++) {
485 map<int, int>::iterator mit = idx_map.find(col_indices_ptr[jj]);
486 if (mit != idx_map.end()) {
487 CHKERR MatSetValue(*mat, mit->second, cstart + jj, 1, INSERT_VALUES);
488 }
489 }
490
491 CHKERR ISRestoreIndices(is_down, &row_indices_ptr);
492 CHKERR ISRestoreIndices(is_up, &col_indices_ptr);
493
494 CHKERR MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY);
495 CHKERR MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY);
496
497 if (vec != NULL) {
498 *vec = PETSC_NULLPTR;
499 }
500
502}
503
505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
507 int leveldown = dm->leveldown;
508 GET_DM_FIELD(dm);
509 if (dm_field->kspOperators.empty()) {
511 } else {
512#if PETSC_VERSION_GE(3, 5, 3)
513 CHKERR MatCreateVecs(
514 dm_field->kspOperators[dm_field->kspOperators.size() - 1 - leveldown],
515 g, NULL);
516#else
517 CHKERR MatGetVecs(
518 dm_field->kspOperators[dm_field->kspOperators.size() - 1 - leveldown],
519 g, NULL);
520#endif
521 CHKERR VecSetDM(*g, dm);
522 }
523#if PETSC_VERSION_GE(3, 17, 0)
524 PetscInfo(dm, "Create global vector DMMGViaApproxOrders leveldown = %d\n",
525 dm->leveldown);
526#else
527 PetscInfo1(dm, "Create global vector DMMGViaApproxOrders leveldown = %d\n",
528 dm->leveldown);
529#endif
531}
532
535 PetscOptionsBegin(PETSC_COMM_WORLD, "",
536 "MOFEM Multi-Grid (Orders) pre-conditioner", "none");
537
538 CHKERR PetscOptionsInt("-mofem_mg_levels", "nb levels of multi-grid solver",
539 "", 2, &nbLevels, PETSC_NULLPTR);
540 CHKERR PetscOptionsInt("-mofem_mg_coarse_order",
541 "approximation order of coarse level", "", 2,
542 &coarseOrder, PETSC_NULLPTR);
543 CHKERR PetscOptionsInt("-mofem_mg_order_at_last_level", "order at last level",
544 "", 100, &orderAtLastLevel, PETSC_NULLPTR);
545 CHKERR PetscOptionsInt("-mofem_mg_verbose", "nb levels of multi-grid solver",
546 "", 0, &verboseLevel, PETSC_NULLPTR);
547 PetscBool shell_sub_a = shellSubA ? PETSC_TRUE : PETSC_FALSE;
548 CHKERR PetscOptionsBool("-mofem_mg_shell_a", "use shell matrix as sub matrix",
549 "", shell_sub_a, &shell_sub_a, NULL);
550 shellSubA = (shellSubA == PETSC_TRUE);
551
552 PetscOptionsEnd();
554}
555
557 MoFEM::Interface *m_field_ptr;
558 MoFEM::ISManager *is_manager_ptr;
560 // if is last level, take all remaining orders dofs, if any left
561 CHKERR DMoFEMGetInterfacePtr(dM, &m_field_ptr);
562 CHKERR m_field_ptr->getInterface(is_manager_ptr);
563 const Problem *problem_ptr;
564 CHKERR DMMoFEMGetProblemPtr(dM, &problem_ptr);
565 int order_at_next_level = kk + coarseOrder;
566 if (kk == nbLevels - 1) {
567 int first = problem_ptr->getNumeredRowDofsPtr()
568 ->get<PetscGlobalIdx_mi_tag>()
569 .lower_bound(0)
570 ->get()
571 ->getPetscGlobalDofIdx();
572 CHKERR ISCreateStride(PETSC_COMM_WORLD, problem_ptr->getNbLocalDofsRow(),
573 first, 1, is);
575 // order_at_next_level = orderAtLastLevel;
576 }
577 string problem_name = problem_ptr->getName();
578 CHKERR is_manager_ptr->isCreateProblemOrder(problem_name, ROW, 0,
579 order_at_next_level, is);
581}
582
588
591 int verb) {
593 verb = verb > verboseLevel ? verb : verboseLevel;
594
595 MPI_Comm comm;
596 CHKERR PetscObjectGetComm((PetscObject)dM, &comm);
597
598 MOFEM_LOG_C("PCMGViaApproximationOrders", Sev::inform, "set MG levels %u\n",
599 nbLevels);
600
601 MOFEM_LOG_CHANNEL("SYNC");
602 MOFEM_LOG_TAG("SYNC", "PCMGViaApproximationOrders")
603
604 std::vector<IS> is_vec(nbLevels + 1);
605 std::vector<int> is_glob_size(nbLevels + 1), is_loc_size(nbLevels + 1);
606
607 for (int kk = 0; kk < nbLevels; kk++) {
608
609 // get indices up to up to give approximation order
610 CHKERR createIsAtLevel(kk, &is_vec[kk]);
611 CHKERR ISGetSize(is_vec[kk], &is_glob_size[kk]);
612 CHKERR ISGetLocalSize(is_vec[kk], &is_loc_size[kk]);
613
614 MOFEM_LOG_C("SYNC", Sev::inform,
615 "Nb. dofs at level [ %d ] global %u local %d\n", kk,
616 is_glob_size[kk], is_loc_size[kk]);
617
618 // if no dofs on level kk finish here
619 if (is_glob_size[kk] == 0) {
620 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "no dofs at level");
621 }
622 }
623
624 for (int kk = 0; kk != nbLevels; kk++) {
625 if (kk == nbLevels - 1 && use_mat_a) {
627 false);
628 } else {
629 if (kk > 0) {
630 // Not coarse level
632 shellSubA);
633 } else {
634 // Coarse lave is compressed matrix allowing for factorization when
635 // needed
637 false);
638 }
639 }
640 }
641
642 for (unsigned int kk = 0; kk < is_vec.size(); kk++) {
643 CHKERR destroyIsAtLevel(kk, &is_vec[kk]);
644 }
645
646 MOFEM_LOG_SEVERITY_SYNC(comm, Sev::inform);
647 MOFEM_LOG_CHANNEL("SYNC");
648
650}
651
652boost::shared_ptr<PCMGSetUpViaApproxOrdersCtx>
653createPCMGSetUpViaApproxOrdersCtx(DM dm, Mat A, bool use_shell_mat) {
654 return boost::make_shared<PCMGSetUpViaApproxOrdersCtx>(dm, A, use_shell_mat);
655}
656
658 PC pc, boost::shared_ptr<PCMGSetUpViaApproxOrdersCtx> ctx, int verb) {
659
660 PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
662
663 auto core_log = logging::core::get();
665 "PCMGViaApproximationOrders"));
666 LogManager::setLog("PCMGViaApproximationOrders");
667 MOFEM_LOG_TAG("PCMGViaApproximationOrders", "PCMGViaApproximationOrders");
668
669 MOFEM_LOG("PCMGViaApproximationOrders", Sev::verbose)
670 << "Setup PCMGSetUpViaApproxOrders";
671
672 CHKERR ctx->getOptions();
673 CHKERR ctx->buildProlongationOperator(true, verb);
674
675#if PETSC_VERSION_GE(3, 8, 0)
676 CHKERR PCMGSetGalerkin(pc, PC_MG_GALERKIN_NONE);
677#else
678 CHKERR PCMGSetGalerkin(pc, PETSC_FALSE);
679#endif
680
681 CHKERR PCMGSetLevels(pc, ctx->nbLevels, NULL);
682
683 MOFEM_LOG("PCMGViaApproximationOrders", Sev::noisy)
684 << "Setup PCMGSetUpViaApproxOrders <- end";
685
687}
688
689} // namespace MoFEM
Implementation of DM context. You should not use it directly.
Discrete manager interface for MoFEM.
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_LOG_C(channel, severity, format,...)
#define GET_DM_FIELD(DM)
header of multi-grid solver for p- adaptivity
constexpr double a
@ ROW
#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_DATA_INCONSISTENCY
Definition definitions.h:31
#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 ...
constexpr double omega
Save field DOFS on vertices/tags.
MoFEMErrorCode DMMGViaApproxOrdersPopBackCoarseningIS(DM dm)
Pop IS form MG via approximation orders.
PetscErrorCode DMDestroy_MoFEM(DM dm)
Destroys dm with MoFEM data structure.
Definition DMMoFEM.cpp:79
MoFEMErrorCode DMMGViaApproxOrdersPushBackCoarseningIS(DM dm, IS is, Mat A, bool create_sub_matrix, bool shell_sub_a)
Push back coarsening level to MG via approximation orders.
PetscErrorCode DMMoFEMGetProblemPtr(DM dm, const MoFEM::Problem **problem_ptr)
Get pointer to problem data structure.
Definition DMMoFEM.cpp:422
MoFEMErrorCode DMCoarsen_MGViaApproxOrders(DM dm, MPI_Comm comm, DM *dmc)
Coarsen DM.
PetscErrorCode DMCreateMatrix_MoFEM(DM dm, Mat *M)
Definition DMMoFEM.cpp:1187
MoFEMErrorCode DMRegister_MGViaApproxOrders(const char sname[])
Register DM for Multi-Grid via approximation orders.
PetscErrorCode DMoFEMGetInterfacePtr(DM dm, MoFEM::Interface **m_field_ptr)
Get pointer to MoFEM::Interface.
Definition DMMoFEM.cpp:410
PetscErrorCode DMCreateGlobalVector_MoFEM(DM dm, Vec *g)
DMShellSetCreateGlobalVector.
Definition DMMoFEM.cpp:1157
MoFEMErrorCode DMMGViaApproxOrdersClearCoarseningIS(DM dm)
Clear approximation orders.
MoFEMErrorCode DMCreateMatrix_MGViaApproxOrders(DM dm, Mat *M)
Create matrix for Multi-Grid via approximation orders.
PetscErrorCode DMSetOperators_MoFEM(DM dm)
Set operators for MoFEM dm.
Definition DMMoFEM.cpp:49
MoFEMErrorCode isCreateProblemOrder(const std::string problem_name, RowColData rc, int min_order, int max_order, IS *is) const
create IS for given order range (collective)
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
const double n
refractive index of diffusive medium
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto isDuplicate(IS is)
MoFEMErrorCode sub_mat_sor(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
MoFEMErrorCode DMCreateInterpolation_MGViaApproxOrders(DM dm1, DM dm2, Mat *mat, Vec *vec)
Create interpolation matrix between data managers dm1 and dm2.
static MoFEMErrorCode ksp_set_operators(KSP ksp, Mat A, Mat B, void *ctx)
MoFEMErrorCode sub_mat_mult_generic(Mat a, Vec x, Vec f)
MoFEMErrorCode DMCreateGlobalVector_MGViaApproxOrders(DM dm, Vec *g)
Create global vector for DMGViaApproxOrders.
MoFEMErrorCode DMMGViaApproxOrdersSetAO(DM dm, AO ao)
Set DM ordering.
auto matCreateVecs(Mat mat)
boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > createPCMGSetUpViaApproxOrdersCtx(DM dm, Mat A, bool use_shell_mat)
createPCMGSetUpViaApproxOrdersCtx
auto createVecScatter(Vec x, IS ix, Vec y, IS iy)
Create a Vec Scatter object.
MoFEMErrorCode DMCreate_MGViaApproxOrders(DM dm)
Create DM data structure for Multi-Grid via approximation orders.
PetscErrorCode DMDestroy_MGViaApproxOrders(DM dm)
Destroy DM.
MoFEMErrorCode PCMGSetUpViaApproxOrders(PC pc, boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > ctx, int verb)
Function build MG structure.
MoFEMErrorCode sub_mat_mult_add(Mat a, Vec x, Vec f)
MoFEMErrorCode sub_mat_mult(Mat a, Vec x, Vec f)
constexpr double g
FTensor::Index< 'm', 3 > m
const int N
Definition speed_test.cpp:3
Structure for DM for multi-grid via approximation orders.
std::vector< SmartPetscObj< Mat > > kspOperators
Get KSP operators.
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, MoFEM::UnknownInterface **iface) const
std::vector< SmartPetscObj< IS > > coarseningIS
Coarsening IS.
boost::ptr_vector< PCMGSubMatrixCtx > shellMatrixCtxPtr
Shell sub-matrix context.
Deprecated interface functions.
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
int orderAtLastLevel
set maximal evaluated order
virtual ~PCMGSetUpViaApproxOrdersCtx()=default
virtual MoFEMErrorCode destroyIsAtLevel(int kk, IS *is)
Destroy IS if internally created.
int coarseOrder
approximation order of coarse level
virtual MoFEMErrorCode createIsAtLevel(int kk, IS *is)
Set IS for levels.
virtual MoFEMErrorCode getOptions()
get options from line command
PCMGSetUpViaApproxOrdersCtx(DM dm, Mat a, bool shell_sub_a)
virtual MoFEMErrorCode buildProlongationOperator(bool use_mat_a, int verb=0)
Set up data structures for MG.
friend MoFEMErrorCode sub_mat_mult_generic(Mat a, Vec x, Vec f)
virtual ~PCMGSubMatrixCtx()=default
friend MoFEMErrorCode sub_mat_sor(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
SmartPetscObj< VecScatter > sCat
keeps basic data about problem
DofIdx getNbLocalDofsRow() const
auto & getNumeredRowDofsPtr() const
get access to numeredRowDofsPtr storing DOFs on rows
intrusive_ptr for managing petsc objects
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.