57 {
58
60
61 try {
62
63
64 DMType dm_name = "DMMOFEM";
66 DMType dm_name_mg = "DMMOFEM_MG";
68
69
70 moab::Core mb_instance;
71 moab::Interface &moab = mb_instance;
72
73
74 auto core_log = logging::core::get();
75 core_log->add_sink(
77 core_log->add_sink(
83
84
87
90 simple->getAddBoundaryFE() =
true;
92
93 auto add_shared_entities_on_skeleton = [&]() {
95 auto boundary_meshset =
simple->getBoundaryMeshSet();
96 auto skeleton_meshset =
simple->getSkeletonMeshSet();
99 bdy_ents, true);
102 0,
simple->getDim() - 1, skeleton_ents,
true);
103 skeleton_ents = subtract(skeleton_ents, bdy_ents);
105 CHKERR m_field.
get_moab().add_entities(skeleton_meshset, skeleton_ents);
107 };
108
109 CHKERR add_shared_entities_on_skeleton();
110
111
112 enum bases {
113 AINSWORTH,
114 AINSWORTH_LOBATTO,
115 DEMKOWICZ,
116 BERNSTEIN,
117 LASBASETOP
118 };
119 const char *list_bases[] = {"ainsworth", "ainsworth_lobatto", "demkowicz",
120 "bernstein"};
121 PetscBool flg;
122 PetscInt choice_base_value = AINSWORTH;
124 LASBASETOP, &choice_base_value, &flg);
125
126 if (flg != PETSC_TRUE)
129 if (choice_base_value == AINSWORTH)
131 if (choice_base_value == AINSWORTH_LOBATTO)
133 else if (choice_base_value == DEMKOWICZ)
135 else if (choice_base_value == BERNSTEIN)
137
138 enum spaces { hdiv, hcurl, last_space };
139 const char *list_spaces[] = {"hdiv", "hcurl"};
140 PetscInt choice_space_value = hdiv;
142 last_space, &choice_space_value, &flg);
143 if (flg != PETSC_TRUE)
146 if (choice_space_value == hdiv)
148 else if (choice_space_value == hcurl)
150
152 PETSC_NULLPTR);
153
154 CHKERR simple->addDomainBrokenField(
"BROKEN", space, base, 1);
157
164 : u_order;
165
169
171
175
177
178 auto assemble_domain_lhs = [&](auto &pip) {
181
185 IT>::OpMixDivTimesScalar<SPACE_DIM>;
186
188 return 1;
189 };
190
191 pip.push_back(
new OpHdivHdiv(
"BROKEN",
"BROKEN", beta));
192 auto unity = []() constexpr { return 1; };
193 pip.push_back(
new OpHdivU(
"BROKEN",
"U", unity,
true));
194
195
196
201 op_loop_skeleton_side->getOpPtrVector(), {});
202
203
204
205 auto broken_data_ptr =
206 boost::make_shared<std::vector<BrokenBaseSideData>>();
207
211 op_loop_domain_side->getOpPtrVector(), {HDIV});
212 op_loop_domain_side->getOpPtrVector().push_back(
214
215 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
217 IT>::OpBrokenSpaceConstrain<1>;
218 op_loop_skeleton_side->getOpPtrVector().push_back(
219 new OpC("HYBRID", broken_data_ptr, 1., true, false));
220
222
223 constexpr int partition = 1;
225 op_print->doWorkRhsHook = [&](
DataOperator *base_op_ptr,
int side,
229 if (
auto op_ptr =
dynamic_cast<BdyEleOp *
>(base_op_ptr)) {
230 auto fe_method = op_ptr->getFEMethod();
231 auto num_fe = fe_method->numeredEntFiniteElementPtr;
232
234 if (num_fe->getPStatus() & PSTATUS_SHARED)
235 MOFEM_LOG(
"SELF", Sev::inform) <<
"Num FE: " << *num_fe;
236 }
237 }
239 };
240 op_loop_skeleton_side->getOpPtrVector().push_back(op_print);
241 };
242
243 pip.push_back(op_loop_skeleton_side);
244
246 };
247
248 auto assemble_domain_rhs = [&](auto &pip) {
253 auto source = [&](
const double x,
const double y,
254 const double z) constexpr {
255 return -1;
256 };
259 };
260
262
263 CHKERR assemble_domain_lhs(pip_mng->getOpDomainLhsPipeline());
264 CHKERR assemble_domain_rhs(pip_mng->getOpDomainRhsPipeline());
265
270
271 TetPolynomialBase::switchCacheBaseOn<HDIV>(
272 {pip_mng->getDomainLhsFE().get(), pip_mng->getDomainRhsFE().get()});
273 TetPolynomialBase::switchCacheBaseOn<L2>(
274 {pip_mng->getDomainLhsFE().get(), pip_mng->getDomainRhsFE().get()});
275
278 "pipeline_manager_graph.dot", pip_mng);
279
282
284 auto ksp = pip_mng->createKSP();
285
286 CHKERR KSPSetFromOptions(ksp);
287 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
288 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp";
290 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp <= Done";
291
292 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve";
293 CHKERR KSPSolve(ksp, f, x);
294 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve <= Done";
295
296 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
297 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
299 SCATTER_REVERSE);
300
302 DM dm;
303 CHKERR KSPGetDM(ksp, &dm);
306 }
307
308 } else {
309 auto ksp = pip_mng->createKSP();
311 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
312 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp";
313 CHKERR schur_ptr->setUp(ksp);
314 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSetUp <= Done";
315
316 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve";
317 CHKERR KSPSolve(ksp, f, x);
318 MOFEM_LOG(
"TIMER", Sev::inform) <<
"KSPSolve <= Done";
319
320 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
321 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
323 SCATTER_REVERSE);
324
326 DM dm;
327 CHKERR KSPGetDM(ksp, &dm);
330 }
331
332 }
333
334 auto check_residual = [&](
auto x,
auto f) {
338
339
340 auto &domain_rhs = pip_mng->getOpDomainRhsPipeline();
341
342 domain_rhs.clear();
343
345
346 auto div_flux_ptr = boost::make_shared<VectorDouble>();
348 "BROKEN", div_flux_ptr));
352 domain_rhs.push_back(new OpUDivFlux("U", div_flux_ptr, beta));
353 auto source = [&](
const double x,
const double y,
354 const double z) constexpr { return 1; };
358
360 IT>::OpMixDivTimesU<3, 1, SPACE_DIM>;
363 auto flux_ptr = boost::make_shared<MatrixDouble>();
364 domain_rhs.push_back(
366 boost::shared_ptr<VectorDouble> u_ptr =
367 boost::make_shared<VectorDouble>();
369 domain_rhs.push_back(
new OpHDivH(
"BROKEN", u_ptr, beta));
370 domain_rhs.push_back(
new OpHdivFlux(
"BROKEN", flux_ptr, beta));
371
372
373
378 op_loop_skeleton_side->getOpPtrVector(), {});
379
380
381
382 auto broken_data_ptr =
383 boost::make_shared<std::vector<BrokenBaseSideData>>();
384
388 op_loop_domain_side->getOpPtrVector(), {HDIV});
389 op_loop_domain_side->getOpPtrVector().push_back(
391 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
392 op_loop_domain_side->getOpPtrVector().push_back(
394 op_loop_domain_side->getOpPtrVector().push_back(
396
397
398 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
400 IT>::OpBrokenSpaceConstrainDHybrid<1>;
402 IT>::OpBrokenSpaceConstrainDFlux<1>;
403 op_loop_skeleton_side->getOpPtrVector().push_back(
404 new OpC_dHybrid("HYBRID", broken_data_ptr, 1.));
405 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
406 op_loop_skeleton_side->getOpPtrVector().push_back(
408 op_loop_skeleton_side->getOpPtrVector().push_back(
409 new OpC_dBroken(broken_data_ptr, hybrid_ptr, 1.));
410
411
412 domain_rhs.push_back(op_loop_skeleton_side);
413
415 CHKERR VecGhostUpdateBegin(f, INSERT_VALUES, SCATTER_FORWARD);
416 CHKERR VecGhostUpdateEnd(f, INSERT_VALUES, SCATTER_FORWARD);
417
418 pip_mng->getDomainRhsFE()->f =
f;
419 pip_mng->getSkeletonRhsFE()->f =
f;
420 pip_mng->getDomainRhsFE()->x = x;
421 pip_mng->getSkeletonRhsFE()->x = x;
422
424 simple->getDomainFEName(),
425 pip_mng->getDomainRhsFE());
426
427 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
428 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
429 CHKERR VecAssemblyBegin(f);
431
432 double fnrm;
433 CHKERR VecNorm(f, NORM_2, &fnrm);
434 MOFEM_LOG_C(
"AT", Sev::inform,
"Residual %3.4e", fnrm);
435
436 constexpr double eps = 1e-8;
439 "Residual norm larger than accepted");
440
442 "domain_rhs_graph.dot", "OpDomainRhsPipeline",
443 pip_mng->getOpDomainRhsPipeline());
444
446 };
447
448 auto calculate_error = [&]() {
450
451
452 auto &domain_rhs = pip_mng->getOpDomainRhsPipeline();
453
454 domain_rhs.clear();
455
457
458 auto u_grad_ptr = boost::make_shared<MatrixDouble>();
459 auto flux_val_ptr = boost::make_shared<MatrixDouble>();
460 auto div_val_ptr = boost::make_shared<VectorDouble>();
461 auto source_ptr = boost::make_shared<VectorDouble>();
462
463 domain_rhs.push_back(
465 domain_rhs.push_back(
468 "BROKEN", div_val_ptr));
469 auto source = [&](
const double x,
const double y,
470 const double z) constexpr { return -1; };
472
473 enum { DIV, GRAD, LAST };
476 domain_rhs.push_back(
479 u_grad_ptr, mpi_vec, GRAD, flux_val_ptr));
480
482 simple->getDomainFEName(),
483 pip_mng->getDomainRhsFE());
484 CHKERR VecAssemblyBegin(mpi_vec);
485 CHKERR VecAssemblyEnd(mpi_vec);
486
488 const double *error_ind;
489 CHKERR VecGetArrayRead(mpi_vec, &error_ind);
491 << "Approximation error ||div flux - source||: "
492 << std::sqrt(error_ind[DIV]);
493 MOFEM_LOG(
"AT", Sev::inform) <<
"Approximation error ||grad-flux||: "
494 << std::sqrt(error_ind[GRAD]);
495 CHKERR VecRestoreArrayRead(mpi_vec, &error_ind);
496 }
497
499 };
500
501 auto get_post_proc_fe = [&]() {
504 auto post_proc_fe = boost::make_shared<PostProcEle>(m_field);
505
508 boost::make_shared<
510 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
511
513 op_loop_side->getOpPtrVector(), {HDIV});
514 auto u_vec_ptr = boost::make_shared<VectorDouble>();
515 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
516 op_loop_side->getOpPtrVector().push_back(
518 op_loop_side->getOpPtrVector().push_back(
520 op_loop_side->getOpPtrVector().push_back(
521
523
524 post_proc_fe->getPostProcMesh(),
525
526 post_proc_fe->getMapGaussPts(),
527
528 {{"U", u_vec_ptr}},
529
530 {{"BROKEN", flux_mat_ptr}},
531
532 {}, {})
533
534 );
535
536 return post_proc_fe;
537 };
538
539 auto post_proc_fe = get_post_proc_fe();
541 simple->getBoundaryFEName(), post_proc_fe);
542 CHKERR post_proc_fe->writeFile(
"out_result.h5m");
543
545 CHKERR check_residual(x, f);
546 }
548
550}
#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 .
@ 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, RowColData rc=RowColData::COL)
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, RowColData rc=RowColData::COL)
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.
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 DOFs on side entities from problem.
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.
auto getDMKspCtx(DM dm)
Get KSP context data structure used by DM.
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 >::OpBaseTimesVector< 3, 3, 3 > OpHdivFlux
Integrating Rhs flux base (1/k) flux (FLUX)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpMixDivTimesU< 3, 1, SPACE_DIM > OpHDivH
Integrate Rhs div flux base times temperature (T)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 3, 3 > OpHdivHdiv
Integrate Lhs base of flux (1/k) base of flux (FLUX x FLUX)
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
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)
std::map< EntityHandle, std::vector< boost::weak_ptr< NumeredEntFiniteElement > > > AdjCache
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.
Operator for broken loop side.
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 field rank 0, i.e. vector field.
Specialization for double precision scalar field values calculation.
Specialization for MatrixDouble vector field values calculation.
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.
static MoFEMErrorCode writeKSPGraphGraphviz(KspCtx *ksp_ctx, std::string filename)
KSP graph to Graphviz file.
static MoFEMErrorCode writeGraphGraphviz(std::string filename, std::string pip_name, const boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
Pipeline graph to Graphviz file.
static MoFEMErrorCode writePiplineManagerGraphGraphviz(std::string filename, PipelineManager *pip_mng)
Write pipeline manager graph to Graphviz file.
PipelineManager interface.
Simple interface for fast problem set-up.
MoFEMErrorCode getOptions()
get options
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