47 return cos(2 * x * M_PI) * cos(2 * y * M_PI);
56 -2 * M_PI * cos(2 * M_PI * y) * sin(2 * M_PI * x),
57 -2 * M_PI * cos(2 * M_PI * x) * sin(2 * M_PI * y)
64 return -(2 * x * x + 2 * y * y);
66 return 8 * M_PI * M_PI * cos(2 * x * M_PI) * cos(2 * y * M_PI);
72static char help[] =
"...\n\n";
148 [[maybe_unused]]
auto save_shared = [&](
auto meshset, std::string prefix) {
179 auto add_base_ops = [&](
auto &pipeline) {
180 auto det_ptr = boost::make_shared<VectorDouble>();
181 auto jac_ptr = boost::make_shared<MatrixDouble>();
182 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
188 add_base_ops(pipeline_mng->getOpDomainLhsPipeline());
191 [](
const double,
const double,
const double) {
return 1; }));
192 pipeline_mng->getOpDomainRhsPipeline().push_back(
196 auto side_fe_ptr = boost::make_shared<FaceSideEle>(
mField);
197 add_base_ops(side_fe_ptr->getOpPtrVector());
198 side_fe_ptr->getOpPtrVector().push_back(
202 pipeline_mng->getOpSkeletonLhsPipeline().push_back(
206 pipeline_mng->getOpBoundaryLhsPipeline().push_back(
208 pipeline_mng->getOpBoundaryRhsPipeline().push_back(
219 auto rule_lhs = [](int, int,
int p) ->
int {
return 2 * p; };
220 auto rule_rhs = [](int, int,
int p) ->
int {
return 2 * p; };
221 auto rule_2 = [
this](int, int, int) {
return 2 *
oRder; };
225 CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule_rhs);
227 CHKERR pipeline_mng->setSkeletonLhsIntegrationRule(rule_2);
228 CHKERR pipeline_mng->setSkeletonRhsIntegrationRule(rule_2);
229 CHKERR pipeline_mng->setBoundaryLhsIntegrationRule(rule_2);
230 CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(rule_2);
242 auto ksp_solver = pipeline_mng->
createKSP();
243 CHKERR KSPSetFromOptions(ksp_solver);
244 CHKERR KSPSetUp(ksp_solver);
253 ksp_solver,
"poisson 2d discontinuous Galerkin");
256 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
257 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
269 auto rule = [](int, int,
int p) ->
int {
return 2 * p; };
271 auto rule_2 = [
this](int, int, int) {
return 2 *
oRder; };
272 auto &evaluation_pipeline = pipeline_mng->getOpEvaluationPipeline();
274 auto add_base_ops = [&](
auto &pipeline) {
275 auto det_ptr = boost::make_shared<VectorDouble>();
276 auto jac_ptr = boost::make_shared<MatrixDouble>();
277 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
283 auto u_vals_ptr = boost::make_shared<VectorDouble>();
284 auto u_grad_ptr = boost::make_shared<MatrixDouble>();
286 add_base_ops(evaluation_pipeline);
287 evaluation_pipeline.push_back(
289 evaluation_pipeline.push_back(
292 enum NORMS {
L2 = 0, SEMI_NORM,
H1, LAST_NORM };
293 std::array<int, LAST_NORM> error_indices;
294 for (
int i = 0;
i != LAST_NORM; ++
i)
295 error_indices[
i] =
i;
300 error_op->doWorkRhsHook = [&](
DataOperator *op_ptr,
int side, EntityType
type,
307 if (
const size_t nb_dofs = data.getIndices().size()) {
309 const int nb_integration_pts = o->getGaussPts().size2();
310 auto t_w = o->getFTensor0IntegrationWeight();
312 auto t_grad = getFTensor1FromMat<2>(*u_grad_ptr);
313 auto t_coords = o->getFTensor1CoordsAtGaussPts();
315 std::array<double, LAST_NORM> error;
316 std::fill(error.begin(), error.end(), 0);
318 for (
int gg = 0; gg != nb_integration_pts; ++gg) {
320 const double alpha = t_w * o->getMeasure();
322 t_val -
u_exact(t_coords(0), t_coords(1), t_coords(2));
324 auto t_exact_grad =
u_grad_exact(t_coords(0), t_coords(1), t_coords(2));
326 const double diff_grad =
327 (t_grad(
i) - t_exact_grad(
i)) * (t_grad(
i) - t_exact_grad(
i));
329 error[
L2] += alpha * pow(diff, 2);
330 error[SEMI_NORM] += alpha * diff_grad;
338 error[
H1] = error[
L2] + error[SEMI_NORM];
347 auto side_fe_ptr = boost::make_shared<FaceSideEle>(
mField);
348 add_base_ops(side_fe_ptr->getOpPtrVector());
349 side_fe_ptr->getOpPtrVector().push_back(
351 std::array<VectorDouble, 2> side_vals;
352 std::array<double, 2> area_map;
353 std::array<EntityHandle, 2> side_ents = {0, 0};
356 side_vals_op->doWorkRhsHook = [&](
DataOperator *op_ptr,
int side,
362 const auto nb_in_loop = o->getFEMethod()->nInTheLoop;
363 area_map[nb_in_loop] = o->getMeasure();
364 side_vals[nb_in_loop] = *u_vals_ptr;
365 side_ents[nb_in_loop] = o->getFEEntityHandle();
368 side_vals[1].clear();
374 side_fe_ptr->getOpPtrVector().push_back(side_vals_op);
376 auto do_work_rhs_error = [&](
DataOperator *op_ptr,
int side, EntityType
type,
381 CHKERR o->loopSideFaces(
"dFE", *side_fe_ptr);
382 const auto in_the_loop = side_fe_ptr->nInTheLoop;
384 if (
auto side_ptr_fe = o->getSidePtrFE()) {
385 if (side_ptr_fe->numeredEntFiniteElementPtr->getEnt() != side_ents[0]) {
392 const std::array<std::string, 2> ele_type_name = {
"BOUNDARY",
"SKELETON"};
394 <<
"do_work_rhs_error in_the_loop " << ele_type_name[in_the_loop];
397 const double s = o->getMeasure() / (area_map[0] + area_map[1]);
400 std::array<double, LAST_NORM> error;
401 std::fill(error.begin(), error.end(), 0);
403 const int nb_integration_pts = o->getGaussPts().size2();
406 side_vals[1].resize(nb_integration_pts,
false);
407 auto t_coords = o->getFTensor1CoordsAtGaussPts();
409 for (
size_t gg = 0; gg != nb_integration_pts; ++gg) {
410 t_val_m =
u_exact(t_coords(0), t_coords(1), t_coords(2));
418 auto t_w = o->getFTensor0IntegrationWeight();
420 for (
size_t gg = 0; gg != nb_integration_pts; ++gg) {
422 const double alpha = o->getMeasure() * t_w;
423 const auto diff = t_val_p - t_val_m;
424 error[SEMI_NORM] += alpha * p * diff * diff;
432 error[
H1] = error[SEMI_NORM];
440 skeleton_error_op->doWorkRhsHook = do_work_rhs_error;
442 boundary_error_op->doWorkRhsHook = do_work_rhs_error;
444 evaluation_pipeline.push_back(error_op);
446 auto add_side_error_op = [&](
const std::string &fe_name,
auto error_op) {
449 op_loop_side->getSideFEPtr()->getRuleHook = rule_2;
450 op_loop_side->getOpPtrVector().push_back(error_op);
451 evaluation_pipeline.push_back(op_loop_side);
457 CHKERR pipeline_mng->loopFiniteElementsEvaluation();
459 CHKERR VecAssemblyBegin(l2_vec);
460 CHKERR VecAssemblyEnd(l2_vec);
464 CHKERR VecGetArrayRead(l2_vec, &array);
465 MOFEM_LOG_C(
"SELF", Sev::inform,
"Error Norm L2 %6.4e",
466 std::sqrt(array[
L2]));
467 MOFEM_LOG_C(
"SELF", Sev::inform,
"Error Norm Energetic %6.4e",
468 std::sqrt(array[SEMI_NORM]));
469 MOFEM_LOG_C(
"SELF", Sev::inform,
"Error Norm H1 %6.4e",
470 std::sqrt(array[
H1]));
473 constexpr double eps = 1e-12;
474 if (std::sqrt(array[
H1]) >
eps)
478 CHKERR VecRestoreArrayRead(l2_vec, &array);
494 auto post_proc_fe = boost::make_shared<PostProcEle>(
mField);
496 auto u_ptr = boost::make_shared<VectorDouble>();
497 post_proc_fe->getOpPtrVector().push_back(
502 post_proc_fe->getOpPtrVector().push_back(
506 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
519 CHKERR pipeline_mng->loopFiniteElementsPostProc();
520 CHKERR post_proc_fe->writeFile(
"out_result.h5m");
544int main(
int argc,
char *argv[]) {
547 const char param_file[] =
"param_file.petsc";
553 DMType dm_name =
"DMMOFEM";
557 moab::Core mb_instance;
558 moab::Interface &moab = mb_instance;
#define MOFEM_LOG_C(channel, severity, format,...)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, FIELD_DIM > OpDomainSource
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
#define CATCH_ERRORS
Catch errors.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ L2
field with C-1 continuity
#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.
constexpr auto domainField
PetscErrorCode DMMoFEMGetProblemPtr(DM dm, const MoFEM::Problem **problem_ptr)
Get pointer to problem data structure.
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.
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
SmartPetscObj< KSP > createKSP(SmartPetscObj< DM > dm=nullptr)
Create KSP (linear) solver.
#define MOFEM_LOG(channel, severity)
Log.
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradGrad< 1, 1, SPACE_DIM > OpDomainGradGrad
PipelineManager::ElementsAndOpsByDim< FE_DIM >::FaceSideEle FaceSideEle
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
OpCalculateHOJacForFaceImpl< 2 > OpCalculateHOJacForFace
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, 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.
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
MoFEMErrorCode VecSetValues(Vec V, const EntitiesFieldData::EntData &data, const double *ptr, InsertMode iora)
Assemble PETSc vector.
FTensor::Index< 'i', SPACE_DIM > i
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
DomainEle::UserDataOperator DomainEleOp
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradGrad< BASE_DIM, FIELD_DIM, SPACE_DIM > OpDomainGradGrad
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< BASE_DIM, FIELD_DIM > OpDomainSource
BoundaryEle::UserDataOperator BoundaryEleOp
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)
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for double precision scalar field values calculation.
Operator for inverting matrices at integration points.
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
Template struct for dimension-specific finite element types.
PipelineManager interface.
MoFEMErrorCode setEvaluationIntegrationRule(RuleHookFun rule)
Set integration rule for domain evaluation finite element.
boost::shared_ptr< FEMethod > & getDomainPostProcFE()
Get domain postprocessing finite element.
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain left-hand side finite element.
keeps basic data about problem
DofIdx getNbDofsRow() const
Simple interface for fast problem set-up.
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
bool & getAddBoundaryFE()
Get the addBoundaryFE flag.
const std::string getBoundaryFEName() const
Get the Boundary FE Name.
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
const std::string getSkeletonFEName() const
Get the Skeleton FE Name.
MoFEMErrorCode getOptions()
get options
MoFEMErrorCode getDM(DM *dm)
Get DM.
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
bool & getAddSkeletonFE()
Get the addSkeletonFE flag.
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Operator tp collect data from elements on the side of Edge/Face.
Operator to evaluate Dirichlet boundary conditions using DG.
Operator the left hand side matrix.
MoFEM::Interface & mField
MoFEMErrorCode boundaryCondition()
[Setup problem]
MoFEMErrorCode checkResults()
[Solve system]
MoFEMErrorCode setupProblem()
[Read mesh]
MoFEMErrorCode setIntegrationRules()
[Assemble system]
MoFEMErrorCode assembleSystem()
[Boundary condition]
Poisson2DiscontGalerkin(MoFEM::Interface &m_field)
MoFEMErrorCode solveSystem()
[Set integration rules]
MoFEMErrorCode readMesh()
[Read mesh]
MoFEMErrorCode outputResults()
[Output results]
MoFEMErrorCode runProgram()
[Output results]