10 using namespace MoFEM;
12 static char help[] =
"...\n\n";
39 auto operator()(
const double x,
const double y,
const double z) {
40 return x * x + y * y + x * y * y + x * x * y;
49 auto operator()(
const double x,
const double y,
const double z) {
53 2 * y + 2 * x * y + x * x};
91 template <
typename PARENT_FE>
93 boost::shared_ptr<FEMethod> &fe_top,
104 boost::function<void(boost::shared_ptr<ForcesAndSourcesCore>,
int)>
106 [&](boost::shared_ptr<ForcesAndSourcesCore> parent_fe_pt,
int level) {
112 auto fe_ptr_current = boost::shared_ptr<ForcesAndSourcesCore>(
113 new PARENT_FE(m_field));
114 if (op == DomainEleOp::OPSPACE) {
118 fe_ptr_current->getOpPtrVector(), {H1});
123 boost::dynamic_pointer_cast<ForcesAndSourcesCore>(
128 if (op == DomainEleOp::OPSPACE) {
131 parent_fe_pt->getOpPtrVector().push_back(
135 H1, op, fe_ptr_current,
146 parent_fe_pt->getOpPtrVector().push_back(
161 add_parent_level(boost::dynamic_pointer_cast<ForcesAndSourcesCore>(fe_top),
174 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
209 boost::shared_ptr<VectorDouble> approxVals;
215 template <
int FIELD_DIM>
struct OpError;
225 boost::shared_ptr<CommonData> commonDataPtr;
226 OpError(boost::shared_ptr<CommonData> &common_data_ptr)
231 if (
const size_t nb_dofs = data.
getIndices().size()) {
235 const int nb_integration_pts = getGaussPts().size2();
236 auto t_w = getFTensor0IntegrationWeight();
239 getFTensor1FromMat<SPACE_DIM>(*(commonDataPtr->divApproxVals));
240 auto t_coords = getFTensor1CoordsAtGaussPts();
245 const double volume = getMeasure();
249 for (
int gg = 0; gg != nb_integration_pts; ++gg) {
251 const double alpha = t_w * volume;
257 t_grad_diff(
i) -= t_grad_val(
i);
259 error += alpha * (pow(diff, 2) + t_grad_diff(
i) * t_grad_diff(
i));
261 for (
size_t r = 0;
r != nb_dofs; ++
r) {
262 nf[
r] += alpha * t_row_base * diff;
273 CHKERR VecSetValue(commonDataPtr->L2Vec, index, error, ADD_VALUES);
290 const int nb_integration_pts = getGaussPts().size2();
291 auto t_w = getFTensor0IntegrationWeight();
293 auto t_coords = getFTensor1CoordsAtGaussPts();
295 const double volume = getMeasure();
298 for (
int gg = 0; gg != nb_integration_pts; ++gg) {
300 const double alpha = t_w * volume;
303 error2 += alpha * (pow(diff, 2));
310 MOFEM_LOG(
"SELF", Sev::verbose) <<
"Boundary error " << sqrt(error2);
312 constexpr
double eps = 1e-8;
313 if (sqrt(error2) >
eps)
315 "Error on boundary = %6.4e", sqrt(error2));
337 ParallelComm *pcomm =
339 Skinner skin(&mField.get_moab());
342 CHKERR mField.getInterface(simpleInterface);
343 CHKERR simpleInterface->getOptions();
344 CHKERR simpleInterface->loadFile();
346 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Dim " << simpleInterface->getDim();
348 auto &moab = mField.get_moab();
354 CHKERR skin.find_skin(0, level0_ents,
false, level0_skin);
355 CHKERR pcomm->filter_pstatus(level0_skin,
356 PSTATUS_SHARED | PSTATUS_MULTISHARED,
357 PSTATUS_NOT, -1,
nullptr);
359 auto refine_mesh = [&](
auto l) {
372 CHKERR moab.get_entities_by_dimension(*meshset_level0_ptr,
SPACE_DIM, els);
381 ele_to_refine.insert(
t);
382 std::vector<EntityHandle> adj_edges;
385 CHKERR moab.add_entities(*meshset_ref_edges_ptr, &*adj_edges.begin(),
392 CHKERR skin.find_skin(0, els,
false, level_skin);
393 CHKERR pcomm->filter_pstatus(level_skin,
394 PSTATUS_SHARED | PSTATUS_MULTISHARED,
395 PSTATUS_NOT, -1,
nullptr);
396 level_skin = subtract(level_skin, level0_skin);
399 adj, moab::Interface::UNION);
400 els = subtract(els, adj);
401 ele_to_refine.merge(els);
403 CHKERR mField.get_moab().get_adjacencies(
404 els,
SPACE_DIM - 1,
false, adj_edges, moab::Interface::UNION);
405 CHKERR moab.add_entities(*meshset_ref_edges_ptr, adj_edges);
408 CHKERR refine->addVerticesInTheMiddleOfEdges(*meshset_ref_edges_ptr,
bit(
l),
414 bit(
l),
BitRefLevel(), simpleInterface->getBoundaryMeshSet(), MBMAXTYPE,
419 (boost::lexical_cast<std::string>(
l) +
"_ref_mesh.vtk").c_str(),
"VTK",
423 (boost::lexical_cast<std::string>(
l) +
"_only_ref_mesh.vtk").c_str(),
429 auto mark_skins = [&](
auto l,
auto m) {
435 CHKERR skin.find_skin(0, ents,
false, level_skin);
436 CHKERR pcomm->filter_pstatus(level_skin,
437 PSTATUS_SHARED | PSTATUS_MULTISHARED,
438 PSTATUS_NOT, -1,
nullptr);
439 level_skin = subtract(level_skin, level0_skin);
440 CHKERR mField.get_moab().get_adjacencies(level_skin, 0,
false, level_skin,
441 moab::Interface::UNION);
455 simpleInterface->getBitRefLevel() = bit_sum;
456 simpleInterface->getBitRefLevelMask() =
BitRefLevel().set();
471 constexpr
int order = 3;
477 simpleInterface->getParentAdjacencies() =
true;
479 CHKERR simpleInterface->setUp();
501 auto rule = [](
int,
int,
int p) ->
int {
return 2 * p + 1; };
510 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainLhsFE(),
511 DomainEleOp::OPSPACE,
QUIET, Sev::noisy);
512 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainLhsFE(),
513 DomainEleOp::OPROW,
QUIET, Sev::noisy);
514 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainLhsFE(),
515 DomainEleOp::OPCOL,
QUIET, Sev::noisy);
521 field_op_row->doWorkRhsHook = [](
DataOperator *op_ptr,
int side,
525 if (
type == MBENTITYSET) {
528 <<
"ROW: side/type: " << side <<
"/" << CN::EntityTypeName(
type)
531 << data.getIndices() <<
" nb base functions " << data.getN().size2()
532 <<
" nb base functions integration points " << data.getN().size1();
534 for (
auto &field_ent : data.getFieldEntities()) {
536 <<
"\t" << CN::EntityTypeName(field_ent->getEntType());
542 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainRhsFE(),
543 DomainEleOp::OPSPACE,
NOISY, Sev::verbose);
544 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainRhsFE(),
545 DomainEleOp::OPROW,
NOISY, Sev::noisy);
560 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Solve problem";
563 CHKERR KSPSetFromOptions(solver);
566 auto dm = simpleInterface->getDM();
571 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
572 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
585 auto rule = [](
int,
int,
int p) ->
int {
return 2 * p + 1; };
591 auto common_data_ptr = boost::make_shared<CommonData>();
592 common_data_ptr->resVec =
createDMVector(simpleInterface->getDM());
594 mField.get_comm(), (!mField.get_comm_rank()) ? 1 : 0, 1);
595 common_data_ptr->approxVals = boost::make_shared<VectorDouble>();
596 common_data_ptr->divApproxVals = boost::make_shared<MatrixDouble>();
600 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainRhsFE(),
601 DomainEleOp::OPSPACE,
QUIET, Sev::noisy);
602 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainRhsFE(),
603 DomainEleOp::OPROW,
VERBOSE, Sev::noisy);
610 common_data_ptr->approxVals));
615 set_parent_dofs<BoundaryParentEle>(mField, pipeline_mng->
getBoundaryRhsFE(),
616 BoundaryEleOp::OPSPACE,
QUIET, Sev::noisy);
617 set_parent_dofs<BoundaryParentEle>(mField, pipeline_mng->
getBoundaryRhsFE(),
618 BoundaryEleOp::OPROW,
VERBOSE, Sev::noisy);
621 common_data_ptr->approxVals));
623 new OpErrorSkel<FIELD_DIM>(common_data_ptr));
625 CHKERR VecZeroEntries(common_data_ptr->L2Vec);
626 CHKERR VecZeroEntries(common_data_ptr->resVec);
630 CHKERR VecAssemblyBegin(common_data_ptr->L2Vec);
631 CHKERR VecAssemblyEnd(common_data_ptr->L2Vec);
632 CHKERR VecAssemblyBegin(common_data_ptr->resVec);
633 CHKERR VecAssemblyEnd(common_data_ptr->resVec);
635 CHKERR VecNorm(common_data_ptr->resVec, NORM_2, &nrm2);
637 CHKERR VecGetArrayRead(common_data_ptr->L2Vec, &array);
638 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Error %6.4e Vec norm %6.4e\n",
639 std::sqrt(array[0]), nrm2);
641 constexpr
double eps = 1e-8;
644 "Not converged solution err = %6.4e", nrm2);
645 if (std::sqrt(array[0]) >
eps)
647 "Error in approximation err = %6.4e", std::sqrt(array[0]));
649 CHKERR VecRestoreArrayRead(common_data_ptr->L2Vec, &array);
661 auto rule = [](
int,
int,
int p) ->
int {
return -1; };
684 auto approx_vals = boost::make_shared<VectorDouble>();
686 auto &moab = mField.get_moab();
688 double def_val[] = {0};
689 CHKERR moab.tag_get_handle(
"FIELD", 1, MB_TYPE_DOUBLE,
th,
690 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val);
692 field_op_row->doWorkRhsHook = [&](
DataOperator *base_op_ptr,
int side,
696 if (
type == MBVERTEX) {
701 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
702 if (nb_gauss_pts != 3)
704 "Should be three guass pts.");
705 auto conn = op_ptr->getConn();
706 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
707 const double v = t_field;
708 CHKERR moab.tag_set_data(
th, &conn[gg], 1, &
v);
715 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainRhsFE(),
716 DomainEleOp::OPSPACE,
VERBOSE, Sev::noisy);
717 set_parent_dofs<DomainParentEle>(mField, pipeline_mng->
getDomainRhsFE(),
718 DomainEleOp::OPROW,
VERBOSE, Sev::noisy);
730 int main(
int argc,
char *argv[]) {
738 DMType dm_name =
"DMMOFEM";