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);
69 using namespace MoFEM;
72 static char help[] =
"...\n\n";
148 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; };
224 CHKERR pipeline_mng->setDomainLhsIntegrationRule(rule_lhs);
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);
254 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
255 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
267 pipeline_mng->getDomainLhsFE().reset();
268 pipeline_mng->getSkeletonRhsFE().reset();
269 pipeline_mng->getSkeletonLhsFE().reset();
270 pipeline_mng->getBoundaryRhsFE().reset();
271 pipeline_mng->getBoundaryLhsFE().reset();
273 auto rule = [](
int,
int,
int p) ->
int {
return 2 * p; };
274 CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule);
276 CHKERR pipeline_mng->setSkeletonRhsIntegrationRule(rule_2);
278 auto add_base_ops = [&](
auto &pipeline) {
279 auto det_ptr = boost::make_shared<VectorDouble>();
280 auto jac_ptr = boost::make_shared<MatrixDouble>();
281 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
287 auto u_vals_ptr = boost::make_shared<VectorDouble>();
288 auto u_grad_ptr = boost::make_shared<MatrixDouble>();
290 add_base_ops(pipeline_mng->getOpDomainRhsPipeline());
291 pipeline_mng->getOpDomainRhsPipeline().push_back(
293 pipeline_mng->getOpDomainRhsPipeline().push_back(
296 enum NORMS {
L2 = 0, SEMI_NORM,
H1, LAST_NORM };
297 std::array<int, LAST_NORM> error_indices;
298 for (
int i = 0;
i != LAST_NORM; ++
i)
299 error_indices[
i] =
i;
304 error_op->doWorkRhsHook = [&](
DataOperator *op_ptr,
int side, EntityType
type,
311 if (
const size_t nb_dofs = data.getIndices().size()) {
313 const int nb_integration_pts = o->getGaussPts().size2();
314 auto t_w = o->getFTensor0IntegrationWeight();
316 auto t_grad = getFTensor1FromMat<2>(*u_grad_ptr);
317 auto t_coords = o->getFTensor1CoordsAtGaussPts();
319 std::array<double, LAST_NORM> error;
320 std::fill(error.begin(), error.end(), 0);
322 for (
int gg = 0; gg != nb_integration_pts; ++gg) {
324 const double alpha = t_w * o->getMeasure();
326 t_val -
u_exact(t_coords(0), t_coords(1), t_coords(2));
328 auto t_exact_grad =
u_grad_exact(t_coords(0), t_coords(1), t_coords(2));
330 const double diff_grad =
331 (t_grad(
i) - t_exact_grad(
i)) * (t_grad(
i) - t_exact_grad(
i));
333 error[
L2] += alpha * pow(diff, 2);
334 error[SEMI_NORM] += alpha * diff_grad;
342 error[
H1] = error[
L2] + error[SEMI_NORM];
351 auto side_fe_ptr = boost::make_shared<FaceSideEle>(
mField);
352 add_base_ops(side_fe_ptr->getOpPtrVector());
353 side_fe_ptr->getOpPtrVector().push_back(
355 std::array<VectorDouble, 2> side_vals;
356 std::array<double, 2> area_map;
359 side_vals_op->doWorkRhsHook = [&](
DataOperator *op_ptr,
int side,
365 const auto nb_in_loop = o->getFEMethod()->nInTheLoop;
366 area_map[nb_in_loop] = o->getMeasure();
367 side_vals[nb_in_loop] = *u_vals_ptr;
370 side_vals[1].clear();
375 side_fe_ptr->getOpPtrVector().push_back(side_vals_op);
377 auto do_work_rhs_error = [&](
DataOperator *op_ptr,
int side, EntityType
type,
382 CHKERR o->loopSideFaces(
"dFE", *side_fe_ptr);
383 const auto in_the_loop = side_fe_ptr->nInTheLoop;
386 const std::array<std::string, 2> ele_type_name = {
"BOUNDARY",
"SKELETON"};
388 <<
"do_work_rhs_error in_the_loop " << ele_type_name[in_the_loop];
391 const double s = o->getMeasure() / (area_map[0] + area_map[1]);
394 constexpr std::array<int, 2> sign_array{1, -1};
396 std::array<double, LAST_NORM> error;
397 std::fill(error.begin(), error.end(), 0);
399 const int nb_integration_pts = o->getGaussPts().size2();
402 side_vals[1].resize(nb_integration_pts,
false);
403 auto t_coords = o->getFTensor1CoordsAtGaussPts();
405 for (
size_t gg = 0; gg != nb_integration_pts; ++gg) {
406 t_val_m =
u_exact(t_coords(0), t_coords(1), t_coords(2));
414 auto t_w = o->getFTensor0IntegrationWeight();
416 for (
size_t gg = 0; gg != nb_integration_pts; ++gg) {
418 const double alpha = o->getMeasure() * t_w;
419 const auto diff = t_val_p - t_val_m;
420 error[SEMI_NORM] += alpha * p * diff * diff;
428 error[
H1] = error[SEMI_NORM];
436 skeleton_error_op->doWorkRhsHook = do_work_rhs_error;
438 boundary_error_op->doWorkRhsHook = do_work_rhs_error;
440 pipeline_mng->getOpDomainRhsPipeline().push_back(error_op);
441 pipeline_mng->getOpSkeletonLhsPipeline().push_back(skeleton_error_op);
442 pipeline_mng->getOpBoundaryRhsPipeline().push_back(boundary_error_op);
444 CHKERR pipeline_mng->loopFiniteElements();
446 CHKERR VecAssemblyBegin(l2_vec);
447 CHKERR VecAssemblyEnd(l2_vec);
451 CHKERR VecGetArrayRead(l2_vec, &array);
452 MOFEM_LOG_C(
"SELF", Sev::inform,
"Error Norm L2 %6.4e",
453 std::sqrt(array[
L2]));
454 MOFEM_LOG_C(
"SELF", Sev::inform,
"Error Norm Energetic %6.4e",
455 std::sqrt(array[SEMI_NORM]));
456 MOFEM_LOG_C(
"SELF", Sev::inform,
"Error Norm H1 %6.4e",
457 std::sqrt(array[
H1]));
460 constexpr
double eps = 1e-12;
461 if (std::sqrt(array[
H1]) >
eps)
465 CHKERR VecRestoreArrayRead(l2_vec, &array);
483 pipeline_mng->getSkeletonRhsFE().reset();
484 pipeline_mng->getSkeletonLhsFE().reset();
485 pipeline_mng->getBoundaryRhsFE().reset();
486 pipeline_mng->getBoundaryLhsFE().reset();
488 auto post_proc_fe = boost::make_shared<PostProcEle>(
mField);
490 auto u_ptr = boost::make_shared<VectorDouble>();
491 post_proc_fe->getOpPtrVector().push_back(
496 post_proc_fe->getOpPtrVector().push_back(
500 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
512 pipeline_mng->getDomainRhsFE() = post_proc_fe;
513 CHKERR pipeline_mng->loopFiniteElements();
514 CHKERR post_proc_fe->writeFile(
"out_result.h5m");
538 int main(
int argc,
char *argv[]) {
541 const char param_file[] =
"param_file.petsc";
547 DMType dm_name =
"DMMOFEM";