52 {
53
55
56 try {
57
58
59 DMType dm_name = "DMMOFEM";
61 DMType dm_name_mg = "DMMOFEM_MG";
63
64
65 moab::Core mb_instance;
66 moab::Interface &moab = mb_instance;
67
68
69 auto core_log = logging::core::get();
70 core_log->add_sink(
72 core_log->add_sink(
78
79
82
85 simple->getAddBoundaryFE() =
true;
87
88 auto add_shared_entities_on_skeleton = [&]() {
90 auto boundary_meshset =
simple->getBoundaryMeshSet();
91 auto skeleton_meshset =
simple->getSkeletonMeshSet();
94 bdy_ents, true);
97 0,
simple->getDim() - 1, skeleton_ents,
true);
98 skeleton_ents = subtract(skeleton_ents, bdy_ents);
100 CHKERR m_field.
get_moab().add_entities(skeleton_meshset, skeleton_ents);
102 };
103
104 CHKERR add_shared_entities_on_skeleton();
105
106
107 enum bases {
108 AINSWORTH,
109 AINSWORTH_LOBATTO,
110 DEMKOWICZ,
111 BERNSTEIN,
112 LASBASETOP
113 };
114 const char *list_bases[] = {"ainsworth", "ainsworth_lobatto", "demkowicz",
115 "bernstein"};
116 PetscBool flg;
117 PetscInt choice_base_value = AINSWORTH;
119 LASBASETOP, &choice_base_value, &flg);
120
121 if (flg != PETSC_TRUE)
124 if (choice_base_value == AINSWORTH)
126 if (choice_base_value == AINSWORTH_LOBATTO)
128 else if (choice_base_value == DEMKOWICZ)
130 else if (choice_base_value == BERNSTEIN)
132
133 enum spaces { hdiv, hcurl, last_space };
134 const char *list_spaces[] = {"hdiv", "hcurl"};
135 PetscInt choice_space_value = hdiv;
137 last_space, &choice_space_value, &flg);
138 if (flg != PETSC_TRUE)
141 if (choice_space_value == hdiv)
143 else if (choice_space_value == hcurl)
145
147 PETSC_NULL);
148
149 CHKERR simple->addDomainBrokenField(
"BROKEN", space, base, 1);
152
156
158
162
164
165 auto assemble_domain_lhs = [&](auto &pip) {
168
172 IT>::OpMixDivTimesScalar<SPACE_DIM>;
173
175 return 1;
176 };
177
178 pip.push_back(
new OpHdivHdiv(
"BROKEN",
"BROKEN", beta));
179 auto unity = []() constexpr { return 1; };
180 pip.push_back(
new OpHdivU(
"BROKEN",
"U", unity,
true));
181
182
183
188 op_loop_skeleton_side->getOpPtrVector(), {});
189
190
191
192 auto broken_data_ptr =
193 boost::make_shared<std::vector<BrokenBaseSideData>>();
194
198 op_loop_domain_side->getOpPtrVector(), {HDIV});
199 op_loop_domain_side->getOpPtrVector().push_back(
201
202 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
204 IT>::OpBrokenSpaceConstrain<1>;
205 op_loop_skeleton_side->getOpPtrVector().push_back(
206 new OpC("HYBRID", broken_data_ptr, 1., true, false));
207
209
210 constexpr int partition = 1;
212 op_print->doWorkRhsHook = [&](
DataOperator *base_op_ptr,
int side,
216 if (
auto op_ptr =
dynamic_cast<BdyEleOp *
>(base_op_ptr)) {
217 auto fe_method = op_ptr->getFEMethod();
218 auto num_fe = fe_method->numeredEntFiniteElementPtr;
219
221 if (num_fe->getPStatus() & PSTATUS_SHARED)
222 MOFEM_LOG(
"SELF", Sev::inform) <<
"Num FE: " << *num_fe;
223 }
224 }
226 };
227 op_loop_skeleton_side->getOpPtrVector().push_back(op_print);
228 };
229
230 pip.push_back(op_loop_skeleton_side);
231
233 };
234
235 auto assemble_domain_rhs = [&](auto &pip) {
240 auto source = [&](
const double x,
const double y,
241 const double z) constexpr {
242 return -1;
243 };
246 };
247
249
250 CHKERR assemble_domain_lhs(pip_mng->getOpDomainLhsPipeline());
251 CHKERR assemble_domain_rhs(pip_mng->getOpDomainRhsPipeline());
252
257
258 TetPolynomialBase::switchCacheBaseOn<HDIV>(
259 {pip_mng->getDomainLhsFE().get(), pip_mng->getDomainRhsFE().get()});
260 TetPolynomialBase::switchCacheBaseOn<L2>(
261 {pip_mng->getDomainLhsFE().get(), pip_mng->getDomainRhsFE().get()});
262
265
267 auto ksp = pip_mng->createKSP();
268
269 CHKERR KSPSetFromOptions(ksp);
270 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
271 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp";
273 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp <= Done";
274
275 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve";
276 CHKERR KSPSolve(ksp, f, x);
277 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve <= Done";
278
279 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
280 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
282 SCATTER_REVERSE);
283 } else {
284 auto ksp = pip_mng->createKSP();
286 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
287 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp";
288 CHKERR schur_ptr->setUp(ksp);
289 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp <= Done";
290
291 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve";
292 CHKERR KSPSolve(ksp, f, x);
293 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve <= Done";
294
295 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
296 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
298 SCATTER_REVERSE);
299 }
300
301 auto check_residual = [&](
auto x,
auto f) {
305
306
307 auto &domain_rhs = pip_mng->getOpDomainRhsPipeline();
308
309 domain_rhs.clear();
310
312
313 auto div_flux_ptr = boost::make_shared<VectorDouble>();
315 "BROKEN", div_flux_ptr));
319 domain_rhs.push_back(new OpUDivFlux("U", div_flux_ptr, beta));
320 auto source = [&](
const double x,
const double y,
321 const double z) constexpr { return 1; };
325
327 IT>::OpMixDivTimesU<3, 1, SPACE_DIM>;
330 auto flux_ptr = boost::make_shared<MatrixDouble>();
331 domain_rhs.push_back(
333 boost::shared_ptr<VectorDouble> u_ptr =
334 boost::make_shared<VectorDouble>();
336 domain_rhs.push_back(
new OpHDivH(
"BROKEN", u_ptr, beta));
337 domain_rhs.push_back(
new OpHdivFlux(
"BROKEN", flux_ptr, beta));
338
339
340
345 op_loop_skeleton_side->getOpPtrVector(), {});
346
347
348
349 auto broken_data_ptr =
350 boost::make_shared<std::vector<BrokenBaseSideData>>();
351
355 op_loop_domain_side->getOpPtrVector(), {HDIV});
356 op_loop_domain_side->getOpPtrVector().push_back(
358 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
359 op_loop_domain_side->getOpPtrVector().push_back(
361 op_loop_domain_side->getOpPtrVector().push_back(
363
364
365 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
367 IT>::OpBrokenSpaceConstrainDHybrid<1>;
369 IT>::OpBrokenSpaceConstrainDFlux<1>;
370 op_loop_skeleton_side->getOpPtrVector().push_back(
371 new OpC_dHybrid("HYBRID", broken_data_ptr, 1.));
372 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
373 op_loop_skeleton_side->getOpPtrVector().push_back(
375 op_loop_skeleton_side->getOpPtrVector().push_back(
376 new OpC_dBroken(broken_data_ptr, hybrid_ptr, 1.));
377
378
379 domain_rhs.push_back(op_loop_skeleton_side);
380
382 CHKERR VecGhostUpdateBegin(f, INSERT_VALUES, SCATTER_FORWARD);
383 CHKERR VecGhostUpdateEnd(f, INSERT_VALUES, SCATTER_FORWARD);
384
385 pip_mng->getDomainRhsFE()->f =
f;
386 pip_mng->getSkeletonRhsFE()->f =
f;
387 pip_mng->getDomainRhsFE()->x = x;
388 pip_mng->getSkeletonRhsFE()->x = x;
389
391 simple->getDomainFEName(),
392 pip_mng->getDomainRhsFE());
393
394 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
395 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
396 CHKERR VecAssemblyBegin(f);
398
399 double fnrm;
400 CHKERR VecNorm(f, NORM_2, &fnrm);
401 MOFEM_LOG_C(
"AT", Sev::inform,
"Residual %3.4e", fnrm);
402
403 constexpr double eps = 1e-8;
406 "Residual norm larger than accepted");
407
409 };
410
411 auto calculate_error = [&]() {
413
414
415 auto &domain_rhs = pip_mng->getOpDomainRhsPipeline();
416
417 domain_rhs.clear();
418
420
421 auto u_grad_ptr = boost::make_shared<MatrixDouble>();
422 auto flux_val_ptr = boost::make_shared<MatrixDouble>();
423 auto div_val_ptr = boost::make_shared<VectorDouble>();
424 auto source_ptr = boost::make_shared<VectorDouble>();
425
426 domain_rhs.push_back(
428 domain_rhs.push_back(
431 "BROKEN", div_val_ptr));
432 auto source = [&](
const double x,
const double y,
433 const double z) constexpr { return -1; };
435
436 enum { DIV, GRAD,
LAST };
439 domain_rhs.push_back(
442 u_grad_ptr, mpi_vec, GRAD, flux_val_ptr));
443
445 simple->getDomainFEName(),
446 pip_mng->getDomainRhsFE());
447 CHKERR VecAssemblyBegin(mpi_vec);
448 CHKERR VecAssemblyEnd(mpi_vec);
449
451 const double *error_ind;
452 CHKERR VecGetArrayRead(mpi_vec, &error_ind);
454 << "Approximation error ||div flux - source||: "
455 << std::sqrt(error_ind[DIV]);
456 MOFEM_LOG(
"AT", Sev::inform) <<
"Approximation error ||grad-flux||: "
457 << std::sqrt(error_ind[GRAD]);
458 CHKERR VecRestoreArrayRead(mpi_vec, &error_ind);
459 }
460
462 };
463
464 auto get_post_proc_fe = [&]() {
467 auto post_proc_fe = boost::make_shared<PostProcEle>(m_field);
468
471 boost::make_shared<
472 ForcesAndSourcesCore::UserDataOperator::AdjCache>());
473 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
474
476 op_loop_side->getOpPtrVector(), {HDIV});
477 auto u_vec_ptr = boost::make_shared<VectorDouble>();
478 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
479 op_loop_side->getOpPtrVector().push_back(
481 op_loop_side->getOpPtrVector().push_back(
483 op_loop_side->getOpPtrVector().push_back(
484
486
487 post_proc_fe->getPostProcMesh(),
488
489 post_proc_fe->getMapGaussPts(),
490
491 {{"U", u_vec_ptr}},
492
493 {{"BROKEN", flux_mat_ptr}},
494
495 {}, {})
496
497 );
498
499 return post_proc_fe;
500 };
501
502 auto post_proc_fe = get_post_proc_fe();
504 simple->getBoundaryFEName(), post_proc_fe);
505 CHKERR post_proc_fe->writeFile(
"out_result.h5m");
506
508 CHKERR check_residual(x, f);
509 }
511
513}
#define MOFEM_LOG_C(channel, severity, format,...)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, FIELD_DIM > OpDomainSource
#define CATCH_ERRORS
Catch errors.
FieldApproximationBase
approximation base
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base nme:nme847.
@ AINSWORTH_BERNSTEIN_BEZIER_BASE
FieldSpace
approximation spaces
@ L2
field with C-1 continuity
@ HCURL
field with continuous tangents
@ HDIV
field with continuous normal traction
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_ATOM_TEST_INVALID
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
MoFEMErrorCode DMRegister_MGViaApproxOrders(const char sname[])
Register DM for Multi-Grid via approximation orders.
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
auto createDMVector(DM dm)
Get smart vector from DM.
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.
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMixDivTimesScalar< 2 > OpHdivU
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpMixDivTimesU< 3, 1, 2 > OpHDivH
Integrate Rhs div flux base times temperature (T)
Add operators pushing bases from local to physical configuration.
Simple interface for fast problem set-up.
MoFEMErrorCode removeSideDOFs(const std::string problem_name, const std::string block_name, const std::string field_name, int bridge_dim, int lo, int hi, bool is_distributed_mesh=true)
Remove side DOFs.
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
base operator to do operations at Gauss Pt. level
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
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.
Get norm of input VectorDouble for Tensor0.
Get norm of input MatrixDouble for Tensor1.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Get vector field for H-div approximation.
Calculate divergence of vector field.
Get field gradients at integration pts for scalar filed rank 0, i.e. vector field.
Get value at integration points for scalar field.
Get values at integration pts for tensor filed rank 1, i.e. vector field.
Get values from scalar function at integration points and save them to VectorDouble for Tensor0.
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
PipelineManager interface.
Simple interface for fast problem set-up.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)
constexpr AssemblyType AT
constexpr IntegrationType IT
BoundaryEle::UserDataOperator BdyEleOp
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesVector< 3, SPACE_DIM, 1 > OpHdivFlux
Integrating Rhs flux base (1/k) flux (FLUX)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 3, SPACE_DIM > OpHdivHdiv
[Linear elastic problem]