12 using namespace MoFEM;
14 static char help[] =
"...\n\n";
27 PETSC>::LinearForm<GAUSS>::OpSource<1, 1>;
29 inline double sqr(
double x) {
return x * x; }
51 return exp(-100. * (
sqr(x) +
sqr(y))) * cos(M_PI * x) * cos(M_PI * y);
60 res[0] = -exp(-100. * (
sqr(x) +
sqr(y))) *
61 (200. * x * cos(M_PI * x) + M_PI * sin(M_PI * x)) * cos(M_PI * y);
62 res[1] = -exp(-100. * (
sqr(x) +
sqr(y))) *
63 (200. * y * cos(M_PI * y) + M_PI * sin(M_PI * y)) * cos(M_PI * x);
69 static double sourceFunction(
const double x,
const double y,
const double z) {
70 return -exp(-100. * (
sqr(x) +
sqr(y))) *
72 (x * cos(M_PI * y) * sin(M_PI * x) +
73 y * cos(M_PI * x) * sin(M_PI * y)) +
74 2. * (20000. * (
sqr(x) +
sqr(y)) - 200. -
sqr(M_PI)) *
75 cos(M_PI * x) * cos(M_PI * y));
80 const char *name, DataType
type,
84 double double_val = 0;
88 name, 1,
type, tag_handle, MB_TAG_CREAT | MB_TAG_SPARSE, &int_val);
92 name, 1,
type, tag_handle, MB_TAG_CREAT | MB_TAG_SPARSE, &double_val);
96 "Wrong data type %d for tag",
type);
132 OpError(boost::shared_ptr<CommonData> &common_data_ptr,
134 :
DomainEleOp(
"U", OPROW), commonDataPtr(common_data_ptr),
136 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE],
false);
137 doEntities[MBTRI] = doEntities[MBQUAD] =
true;
148 CHKERR createCommonData();
157 CHKERR mField.getInterface(simpleInterface);
158 CHKERR simpleInterface->getOptions();
159 CHKERR simpleInterface->loadFile();
171 CHKERR mField.get_moab().get_number_entities_by_type(0, MBQUAD, nb_quads);
181 CHKERR simpleInterface->addDomainField(
"Q",
HCURL, base, 1);
186 indicTolerance = 1e-3;
192 CHKERR simpleInterface->setFieldOrder(
"U", initOrder);
193 CHKERR simpleInterface->setFieldOrder(
"Q", initOrder + 1);
194 CHKERR simpleInterface->setUp();
196 CHKERR mField.get_moab().get_entities_by_dimension(0, 2, domainEntities);
198 CHKERR getTagHandle(mField,
"ORDER", MB_TYPE_INTEGER, th_order);
199 for (
auto ent : domainEntities) {
200 CHKERR mField.get_moab().tag_set_data(th_order, &ent, 1, &initOrder);
210 auto rule = [](
int,
int,
int p) ->
int {
return 2 * p; };
223 commonDataPtr = boost::make_shared<CommonData>();
224 PetscInt ghosts[3] = {0, 1, 2};
225 if (!mField.get_comm_rank())
226 commonDataPtr->petscVec =
229 commonDataPtr->petscVec =
231 commonDataPtr->approxVals = boost::make_shared<VectorDouble>();
232 commonDataPtr->approxValsGrad = boost::make_shared<MatrixDouble>();
233 commonDataPtr->approxFlux = boost::make_shared<MatrixDouble>();
252 auto unity = []() {
return 1; };
254 new OpHdivU(
"Q",
"U", unity,
true));
255 auto source = [&](
const double x,
const double y,
const double z) {
256 return -sourceFunction(x, y, z);
269 CHKERR KSPSetFromOptions(solver);
272 auto dm = simpleInterface->getDM();
278 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
279 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
288 Tag th_error_ind, th_order;
289 CHKERR getTagHandle(mField,
"ERROR_INDICATOR", MB_TYPE_DOUBLE, th_error_ind);
290 CHKERR getTagHandle(mField,
"ORDER", MB_TYPE_INTEGER, th_order);
292 std::vector<Range> refinement_levels;
293 refinement_levels.resize(iter_num + 1);
294 for (
auto ent : domainEntities) {
295 double err_indic = 0;
296 CHKERR mField.get_moab().tag_get_data(th_error_ind, &ent, 1, &err_indic);
298 int order, new_order;
299 CHKERR mField.get_moab().tag_get_data(th_order, &ent, 1, &
order);
300 new_order =
order + 1;
302 if (err_indic > thetaParam * maxErrorIndicator) {
303 refined_ents.insert(ent);
305 CHKERR mField.get_moab().get_adjacencies(&ent, 1, 1,
false, adj,
306 moab::Interface::UNION);
307 refined_ents.merge(adj);
308 refinement_levels[new_order - initOrder].merge(refined_ents);
309 CHKERR mField.get_moab().tag_set_data(th_order, &ent, 1, &new_order);
313 for (
int ll = 1; ll < refinement_levels.size(); ll++) {
315 refinement_levels[ll]);
317 if (initOrder + ll > 8) {
319 <<
"setting approximation order higher than 8 is not currently "
323 CHKERR mField.set_field_order(refinement_levels[ll],
"U", initOrder + ll);
324 CHKERR mField.set_field_order(refinement_levels[ll],
"Q",
331 CHKERR mField.build_fields();
332 CHKERR mField.build_finite_elements();
333 CHKERR mField.build_adjacencies(simpleInterface->getBitRefLevel());
334 mField.getInterface<
ProblemsManager>()->buildProblemFromFields = PETSC_TRUE;
344 CHKERR setIntegrationRules();
350 while (fabs(indicTolerance) > DBL_EPSILON &&
351 totErrorIndicator > indicTolerance) {
352 MOFEM_LOG(
"EXAMPLE", Sev::inform) <<
"Refinement iteration " << iter_num;
354 CHKERR refineOrder(iter_num);
356 CHKERR setIntegrationRules();
358 CHKERR checkError(iter_num);
359 CHKERR outputResults(iter_num);
364 "Too many refinement iterations");
385 commonDataPtr->approxValsGrad));
389 new OpError(commonDataPtr, mField));
391 commonDataPtr->maxErrorIndicator = 0;
392 CHKERR VecZeroEntries(commonDataPtr->petscVec);
394 CHKERR VecAssemblyBegin(commonDataPtr->petscVec);
395 CHKERR VecAssemblyEnd(commonDataPtr->petscVec);
396 CHKERR VecGhostUpdateBegin(commonDataPtr->petscVec, INSERT_VALUES,
398 CHKERR VecGhostUpdateEnd(commonDataPtr->petscVec, INSERT_VALUES,
401 MPI_Allreduce(&commonDataPtr->maxErrorIndicator, &maxErrorIndicator, 1,
402 MPI_DOUBLE, MPI_MAX, mField.get_comm());
405 CHKERR VecGetArrayRead(commonDataPtr->petscVec, &array);
407 <<
"Global error indicator (max): " << commonDataPtr->maxErrorIndicator;
409 <<
"Global error indicator (total): "
410 << std::sqrt(array[CommonData::ERROR_INDICATOR_TOTAL]);
412 <<
"Global error L2 norm: "
413 << std::sqrt(array[CommonData::ERROR_L2_NORM]);
415 <<
"Global error H1 seminorm: "
416 << std::sqrt(array[CommonData::ERROR_H1_SEMINORM]);
418 totErrorIndicator = std::sqrt(array[CommonData::ERROR_INDICATOR_TOTAL]);
419 CHKERR VecRestoreArrayRead(commonDataPtr->petscVec, &array);
421 std::vector<Tag> tag_handles;
422 tag_handles.resize(4);
423 CHKERR getTagHandle(mField,
"ERROR_L2_NORM", MB_TYPE_DOUBLE, tag_handles[0]);
424 CHKERR getTagHandle(mField,
"ERROR_H1_SEMINORM", MB_TYPE_DOUBLE,
426 CHKERR getTagHandle(mField,
"ERROR_INDICATOR", MB_TYPE_DOUBLE,
428 CHKERR getTagHandle(mField,
"ORDER", MB_TYPE_INTEGER, tag_handles[3]);
430 ParallelComm *pcomm =
435 tag_handles.push_back(pcomm->part_tag());
436 std::ostringstream strm;
437 strm <<
"error_" << iter_num <<
".h5m";
438 CHKERR mField.get_moab().write_file(strm.str().c_str(),
"MOAB",
439 "PARALLEL=WRITE_PART", 0, 0,
440 tag_handles.data(), tag_handles.size());
453 auto post_proc_fe = boost::make_shared<PostProcEle>(mField);
457 auto u_ptr = boost::make_shared<VectorDouble>();
458 auto flux_ptr = boost::make_shared<MatrixDouble>();
459 post_proc_fe->getOpPtrVector().push_back(
461 post_proc_fe->getOpPtrVector().push_back(
466 post_proc_fe->getOpPtrVector().push_back(
468 new OpPPMap(post_proc_fe->getPostProcMesh(),
469 post_proc_fe->getMapGaussPts(),
483 pipeline_mng->getDomainRhsFE() = post_proc_fe;
484 CHKERR pipeline_mng->loopFiniteElements();
486 std::ostringstream strm;
487 strm <<
"out_" << iter_num <<
".h5m";
488 CHKERR post_proc_fe->writeFile(strm.str().c_str());
497 const int nb_integration_pts = getGaussPts().size2();
498 const double area = getMeasure();
499 auto t_w = getFTensor0IntegrationWeight();
501 auto t_val_grad = getFTensor1FromMat<2>(*(
commonDataPtr->approxValsGrad));
502 auto t_flux = getFTensor1FromMat<3>(*(
commonDataPtr->approxFlux));
503 auto t_coords = getFTensor1CoordsAtGaussPts();
509 double error_ind = 0;
510 for (
int gg = 0; gg != nb_integration_pts; ++gg) {
511 const double alpha = t_w * area;
514 t_coords(0), t_coords(1), t_coords(2));
515 error_l2 += alpha *
sqr(diff);
518 t_coords(0), t_coords(1), t_coords(2));
519 auto t_fun_grad = getFTensor1FromArray<2, 2>(vec);
520 t_diff(
i) = t_val_grad(
i) - t_fun_grad(
i);
521 error_h1 += alpha * t_diff(
i) * t_diff(
i);
523 t_diff(
i) = t_val_grad(
i) - t_flux(
i);
524 error_ind += alpha * t_diff(
i) * t_diff(
i);
534 Tag th_error_l2, th_error_h1, th_error_ind;
542 double error_l2_norm = sqrt(error_l2);
543 double error_h1_seminorm = sqrt(error_h1);
544 double error_ind_local = sqrt(error_ind);
555 constexpr std::array<int, CommonData::LAST_ELEMENT> indices = {
558 std::array<double, CommonData::LAST_ELEMENT> values;
559 values[0] = error_l2;
560 values[1] = error_h1;
561 values[2] = error_ind;
563 indices.data(), values.data(), ADD_VALUES);
568 int main(
int argc,
char *argv[]) {
570 const char param_file[] =
"param_file.petsc";
574 auto core_log = logging::core::get();
576 LogManager::createSink(LogManager::getStrmWorld(),
"EXAMPLE"));
577 LogManager::setLog(
"EXAMPLE");
582 DMType dm_name =
"DMMOFEM";