14static char help[] =
"DG Projection Test - validates discontinuous Galerkin "
15 "projection accuracy\n\n";
29auto fun = [](
const double x,
const double y,
const double z) {
30 return x + y + x * x + y * y;
70auto save_range = [](moab::Interface &moab,
const std::string name,
71 const Range r, std::vector<Tag> tags = {}) {
74 CHKERR moab.add_entities(*out_meshset, r);
76 CHKERR moab.write_file(name.c_str(),
"VTK",
"", out_meshset->get_ptr(), 1,
77 tags.data(), tags.size());
79 MOFEM_LOG(
"SELF", Sev::warning) <<
"Empty range for " << name;
87 OpError(boost::shared_ptr<MatrixDouble> data_ptr)
93 const int nb_integration_pts = getGaussPts().size2();
95 auto t_val = getFTensor1FromMat<1>(*(
dataPtr));
96 auto t_coords = getFTensor1CoordsAtGaussPts();
98 for (
int gg = 0; gg != nb_integration_pts; ++gg) {
100 double projected_value = t_val(0);
101 double analytical_value =
fun(t_coords(0), t_coords(1), t_coords(2));
102 double error = projected_value - analytical_value;
104 constexpr double eps = 1e-8;
105 if (std::abs(error) >
eps) {
107 <<
"Projection error too large: " << error <<
" at point ("
108 << t_coords(0) <<
", " << t_coords(1) <<
")"
109 <<
" projected=" << projected_value
110 <<
" analytical=" << analytical_value;
112 "DG projection failed accuracy test");
119 MOFEM_LOG(
"SELF", Sev::noisy) <<
"DG projection accuracy validation passed";
159 char mesh_File_Name[255];
161 mesh_File_Name, 255, PETSC_NULLPTR);
187 auto rule = [](
int,
int,
int p) ->
int {
return 2 * p; };
211 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Solving DG projection system";
214 CHKERR KSPSetFromOptions(solver);
223 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
224 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
239 pipeline_mng->getDomainLhsFE().reset();
240 pipeline_mng->getDomainRhsFE().reset();
241 pipeline_mng->getOpDomainRhsPipeline().clear();
243 auto rule = [](int, int,
int p) ->
int {
return 2 * p; };
244 CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule);
249 auto get_child_op = [&](
auto &pip) {
251 mField,
simple->getDomainFEName(), child_bit, child_bit, Sev::noisy);
252 auto fe_child_ptr = op_this_child->getThisFEPtr();
253 fe_child_ptr->getRuleHook = [] (int, int,
int p) {
return -1; };
256 child_bit, child_bit, MBEDGE, child_edges);
258 CHKERR setDGSetIntegrationPoints<SPACE_DIM>(
259 fe_child_ptr->setRuleHook, [](
int,
int,
int p) { return 2 * p; },
260 boost::make_shared<Range>(child_edges));
261 pip.push_back(op_this_child);
267 auto get_filed_eval_op = [&](
auto fe_child_ptr) {
279 auto data_ptr = boost::make_shared<MatrixDouble>();
280 auto eval_data_ptr = boost::make_shared<MatrixDouble>();
282 if (
auto fe_eval_ptr = field_eval_data->feMethodPtr.lock()) {
283 fe_eval_ptr->getRuleHook = [] (int, int,
int p) {
return -1; };
284 fe_eval_ptr->getOpPtrVector().push_back(
289 op_test->doWorkRhsHook =
290 [](
DataOperator *base_op_ptr,
int side, EntityType type,
294 auto op_ptr =
static_cast<DomainEleOp *
>(base_op_ptr);
297 <<
"Field evaluator method pointer is valid";
299 << op_ptr->getGaussPts();
301 <<
"Loop size " << op_ptr->getPtrFE()->getLoopSize();
303 <<
"Coords at gauss pts: " << op_ptr->getCoordsAtGaussPts();
308 fe_eval_ptr->getOpPtrVector().push_back(op_test);
312 "Field evaluator method pointer is expired");
315 auto op_ptr = field_eval_ptr->getDataOperator<
SPACE_DIM>(
320 fe_child_ptr->getOpPtrVector().push_back(op_ptr);
325 auto dg_projection_base = [&](
auto fe_child_ptr,
auto data_ptr) {
327 constexpr int projection_order =
order;
328 auto entity_data_l2 = boost::make_shared<EntitiesFieldData>(MBENTITYSET);
329 auto mass_ptr = boost::make_shared<MatrixDouble>();
330 auto coeffs_ptr = boost::make_shared<MatrixDouble>();
332 fe_child_ptr->getOpPtrVector().push_back(
343 fe_child_ptr->getOpPtrVector().push_back(
new OpError(data_ptr));
347 op_set_coeffs->doWorkRhsHook =
348 [coeffs_ptr](
DataOperator *base_op_ptr,
int side, EntityType type,
351 auto field_ents = data.getFieldEntities();
352 if (!field_ents.size())
354 if (
auto e_ptr = field_ents[0]) {
355 auto field_ent_data = e_ptr->getEntFieldData();
356 std::copy(coeffs_ptr->data().begin(), coeffs_ptr->data().end(),
357 field_ent_data.begin());
361 fe_child_ptr->getOpPtrVector().push_back(op_set_coeffs);
367 auto fe_child_ptr = get_child_op(pipeline_mng->getOpDomainRhsPipeline());
370 CHKERR dg_projection_base(fe_child_ptr, get_filed_eval_op(fe_child_ptr));
373 auto test_data_ptr = boost::make_shared<MatrixDouble>();
374 pipeline_mng->getOpDomainRhsPipeline().push_back(
376 pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpError(test_data_ptr));
378 CHKERR pipeline_mng->loopFiniteElements();
391 auto post_proc_fe = boost::make_shared<PostProcFaceEle>(
mField);
393 post_proc_fe->getOpPtrVector(), {H1});
395 auto u_ptr = boost::make_shared<VectorDouble>();
396 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
397 post_proc_fe->getOpPtrVector().push_back(
400 post_proc_fe->getOpPtrVector().push_back(
405 post_proc_fe->getOpPtrVector().push_back(
408 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
424 CHKERR post_proc_fe->writeFile(file_name);
437 auto make_edge_flip = [&](
auto edge,
auto adj_faces,
Range &new_tris) {
444 CHKERR moab.get_connectivity(e, conn, num_nodes,
true);
445 std::copy(conn, conn + num_nodes, conn_cpy);
449 std::array<EntityHandle, 6> adj_conn;
450 CHKERR get_conn(adj_faces[0], &adj_conn[0]);
451 CHKERR get_conn(adj_faces[1], &adj_conn[3]);
452 std::array<EntityHandle, 2> edge_conn;
453 CHKERR get_conn(edge, edge_conn.data());
454 std::array<EntityHandle, 2> new_edge_conn;
457 for (
int i = 0;
i != 6; ++
i) {
458 if (adj_conn[
i] != edge_conn[0] && adj_conn[
i] != edge_conn[1]) {
459 new_edge_conn[
j] = adj_conn[
i];
464 auto &new_conn = adj_conn;
465 for (
int t = 0;
t != 2; ++
t) {
466 for (
int i = 0;
i != 3; ++
i) {
469 (adj_conn[3 *
t +
i % 3] == edge_conn[0] &&
470 adj_conn[3 *
t + (
i + 1) % 3] == edge_conn[1])
474 (adj_conn[3 *
t +
i % 3] == edge_conn[1] &&
475 adj_conn[3 *
t + (
i + 1) % 3] == edge_conn[0])
478 new_conn[3 *
t + (
i + 1) % 3] = new_edge_conn[
t];
484 for (
int t = 0;
t != 2; ++
t) {
491 new_tris.insert(tri);
494 if (rtri.size() != 1) {
496 <<
"Multiple tries created during edge flip for edge " << edge
497 <<
" adjacent faces " << std::endl
500 "Multiple tries created during edge flip");
503 new_tris.merge(rtri);
509 moab::Interface::UNION);
524 CHKERR skin.find_skin(0, tris,
false, skin_edges);
526 CHKERR moab.get_adjacencies(skin_edges,
SPACE_DIM,
false, adj_skin_tris);
533 Range new_tris, flipped_tris;
535 for (
auto edge : edges) {
537 CHKERR moab.get_adjacencies(&edge, 1,
SPACE_DIM,
false, adjacent_tris);
540 adjacent_tris = subtract(adjacent_tris, adj_skin_tris);
541 adjacent_tris = subtract(adjacent_tris, flipped_tris);
542 if (adjacent_tris.size() == 2) {
543 CHKERR make_edge_flip(edge, adjacent_tris, new_tris);
544 flipped_tris.merge(adjacent_tris);
551 Range not_flipped_tris = subtract(all_tris, flipped_tris);
554 <<
"Flipped " << flip_count <<
" edges with two adjacent faces.";
560 child_bit,
BitRefLevel().set(),
"edge_flips_before_refinement.vtk",
"VTK",
576int main(
int argc,
char *argv[]) {
583 DMType dm_name =
"DMMOFEM";
588 moab::Core mb_instance;
589 moab::Interface &moab = mb_instance;
void simple(double P1[], double P2[], double P3[], double c[], const int N)
constexpr char FIELD_NAME[]
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
constexpr char FIELD_NAME[]
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, FIELD_DIM > OpDomainSource
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, FIELD_DIM > OpDomainMass
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#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 int order
Order displacement.
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.
auto createDMVector(DM dm)
Get smart vector from DM.
MoFEMErrorCode loopFiniteElements(SmartPetscObj< DM > dm=nullptr)
Iterate finite elements.
boost::ptr_deque< UserDataOperator > & getOpDomainLhsPipeline()
Get the Op Domain Lhs Pipeline object.
SmartPetscObj< KSP > createKSP(SmartPetscObj< DM > dm=nullptr)
Create KSP (linear) solver.
boost::ptr_deque< UserDataOperator > & getOpDomainRhsPipeline()
Get the Op Domain Rhs Pipeline object.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
implementation of Data Operators for Forces and Sources
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr double t
plate stiffness
constexpr auto field_name
SmartPetscObj< Vec > L2Vec
boost::shared_ptr< VectorDouble > approxVals
boost::shared_ptr< MatrixDouble > invJacPtr
boost::shared_ptr< MatrixDouble > approxGradVals
boost::shared_ptr< MatrixDouble > approxHessianVals
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
boost::shared_ptr< MatrixDouble > dataPtr
boost::shared_ptr< CommonData > commonDataPtr
OpError(boost::shared_ptr< MatrixDouble > data_ptr)
MoFEMErrorCode assembleSystem()
MoFEMErrorCode readMesh()
MoFEMErrorCode projectResults(BitRefLevel parent_bit, BitRefLevel child_bit)
[Solve]
MoFEMErrorCode reSetupProblem(BitRefLevel child_bit)
[Edge flips]
MoFEMErrorCode edgeFlips(BitRefLevel parent_bit, BitRefLevel child_bit)
[Output results]
MoFEMErrorCode solveSystem()
Example(MoFEM::Interface &m_field)
MoFEMErrorCode runProblem()
MoFEM::Interface & mField
Reference to MoFEM interface.
MoFEMErrorCode setupProblem()
MoFEMErrorCode outputResults()
[Solve]
Add operators pushing bases from local to physical configuration.
virtual int get_comm_size() const =0
virtual moab::Interface & get_moab()=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)
Field evaluator interface.
boost::shared_ptr< SPD > getData(const double *ptr=nullptr, const int nb_eval_points=0, const double eps=1e-12, VERBOSITY_LEVELS verb=QUIET)
Get the Data object.
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 double precision vector field values calculation.
Execute "this" element in the operator.
Post post-proc data at points from hash maps.
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
std::map< std::string, boost::shared_ptr< VectorDouble > > DataMapVec
Template struct for dimension-specific finite element types.
PipelineManager interface.
boost::shared_ptr< FEMethod > & getDomainRhsFE()
Get domain right-hand side finite element.
boost::shared_ptr< FEMethod > & getDomainLhsFE()
Get domain left-hand side finite element.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain left-hand side finite element.
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.
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
MoFEMErrorCode reSetUp(bool only_dm=false)
Rebuild internal MoFEM data structures.
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.
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
const std::string getDomainFEName() const
Get the Domain FE Name.
BitRefLevel & getBitRefLevel()
Get the BitRefLevel.
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
DomainEle::UserDataOperator DomainEleOp
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle DomainEle