146 auto integration_rule_bc = [](int, int,
int approx_order) {
152 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
153 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
157 pip->getOpDomainLhsPipeline(), {H1},
"GEOMETRY");
159 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
161 pip->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
163 pip->getOpBoundaryLhsPipeline(), {NOSPACE},
"GEOMETRY");
167 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
168 mField, pip->getOpDomainLhsPipeline(),
"U",
"MAT_ELASTIC", Sev::verbose);
172 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
173 mField, pip->getOpDomainRhsPipeline(),
"U",
"MAT_ELASTIC", Sev::verbose);
177 pip->getOpDomainRhsPipeline(),
mField,
"U", Sev::inform);
183 pip->getOpBoundaryRhsPipeline(),
mField,
"U", -1, Sev::inform);
186 pip->getOpBoundaryLhsPipeline(),
mField,
"U", Sev::verbose);
227 auto solver = pip->createKSP();
228 CHKERR KSPSetFromOptions(solver);
230 auto set_essential_bc = [
this]() {
234 auto dm =
simple->getDM();
235 auto ksp_ctx_ptr = getDMKspCtx(dm);
237 auto pre_proc_rhs = boost::make_shared<FEMethod>();
238 auto post_proc_rhs = boost::make_shared<FEMethod>();
239 auto post_proc_lhs = boost::make_shared<FEMethod>();
241 auto get_pre_proc_hook = [
this, pre_proc_rhs]() {
242 return EssentialPreProc<DisplacementCubitBcData>(
mField, pre_proc_rhs,
245 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
247 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
250 CHKERR EssentialPostProcRhs<DisplacementCubitBcData>(
mField,
251 post_proc_rhs, 1.)();
255 auto get_post_proc_hook_lhs = [
this, post_proc_lhs]() {
258 CHKERR EssentialPostProcLhs<DisplacementCubitBcData>(
mField,
259 post_proc_lhs, 1.)();
263 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
264 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
266 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
267 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
268 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
272 auto evaluate_field_at_the_point = [&]() {
276 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
278 CHKERR PetscOptionsGetRealArray(NULL, NULL,
"-field_eval_coords",
279 field_eval_coords.data(), &coords_dim,
285 auto field_eval_data =
289 ->buildTree<SPACE_DIM>(field_eval_data,
simple->getDomainFEName());
291 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
292 auto no_rule = [](int, int, int) {
return -1; };
293 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
294 field_eval_fe_ptr->getRuleHook = no_rule;
296 field_eval_fe_ptr->getOpPtrVector().push_back(
297 new OpCalculateVectorFieldValues<SPACE_DIM>(
"U",
vectorFieldPtr));
300 ->evalFEAtThePoint<SPACE_DIM>(
301 field_eval_coords.data(), 1e-12,
simple->getProblemName(),
302 simple->getDomainFEName(), field_eval_data,
310 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1);
313 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1)
314 <<
" U_Z: " << t_disp(2);
322 CHKERR set_essential_bc();
324 CHKERR evaluate_field_at_the_point();
335 auto det_ptr = boost::make_shared<VectorDouble>();
336 auto jac_ptr = boost::make_shared<MatrixDouble>();
337 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
339 pip->getDomainRhsFE().reset();
340 pip->getDomainLhsFE().reset();
341 pip->getBoundaryRhsFE().reset();
342 pip->getBoundaryLhsFE().reset();
346 auto post_proc_mesh = boost::make_shared<moab::Core>();
347 auto post_proc_begin = boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
349 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
354 auto calculate_stress_ops = [&](
auto &pip) {
359 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEle>(
360 mField, pip,
"U",
"MAT_ELASTIC", Sev::verbose);
363 auto u_ptr = boost::make_shared<MatrixDouble>();
364 pip.push_back(
new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_ptr));
365 auto x_ptr = boost::make_shared<MatrixDouble>();
367 new OpCalculateVectorFieldValues<SPACE_DIM>(
"GEOMETRY", x_ptr));
370 return boost::make_tuple(u_ptr, x_ptr, common_ptr->getMatStrain(),
371 common_ptr->getMatCauchyStress());
374 auto get_tag_id_on_pmesh = [&](
bool post_proc_skin) {
378 "MAT_ELASTIC", 1, MB_TYPE_INTEGER, tag_mat,
379 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val_int);
380 auto meshset_vec_ptr =
382 std::regex((boost::format(
"%s(.*)") %
"MAT_ELASTIC").str()));
385 std::unique_ptr<Skinner> skin_ptr;
386 if (post_proc_skin) {
388 auto boundary_meshset =
simple->getBoundaryMeshSet();
393 for (
auto m : meshset_vec_ptr) {
397 int const id =
m->getMeshsetId();
398 ents_3d = ents_3d.subset_by_dimension(
SPACE_DIM);
399 if (post_proc_skin) {
401 CHKERR skin_ptr->find_skin(0, ents_3d,
false, skin_faces);
402 ents_3d = intersect(skin_ents, skin_faces);
410 auto post_proc_domain = [&](
auto post_proc_mesh) {
412 boost::make_shared<PostProcEleDomain>(
mField, post_proc_mesh);
413 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
415 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
416 calculate_stress_ops(post_proc_fe->getOpPtrVector());
418 post_proc_fe->getOpPtrVector().push_back(
422 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
426 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}},
430 {{
"STRAIN", mat_strain_ptr}, {
"STRESS", mat_stress_ptr}}
436 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(
false)});
440 auto post_proc_boundary = [&](
auto post_proc_mesh) {
442 boost::make_shared<PostProcEleBdy>(mField, post_proc_mesh);
444 post_proc_fe->getOpPtrVector(), {},
"GEOMETRY");
448 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
449 calculate_stress_ops(op_loop_side->getOpPtrVector());
450 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
451 auto mat_traction_ptr = boost::make_shared<MatrixDouble>();
452 post_proc_fe->getOpPtrVector().push_back(
455 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
457 post_proc_fe->getOpPtrVector().push_back(
461 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
465 {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}, {
"T", mat_traction_ptr}},
469 {{
"STRAIN", mat_strain_ptr}, {
"STRESS", mat_stress_ptr}}
475 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(
true)});
479 PetscBool post_proc_skin_only = PETSC_FALSE;
481 post_proc_skin_only = PETSC_TRUE;
483 &post_proc_skin_only, PETSC_NULLPTR);
485 if (post_proc_skin_only == PETSC_FALSE) {
486 pip->getDomainRhsFE() = post_proc_domain(post_proc_mesh);
488 pip->getBoundaryRhsFE() = post_proc_boundary(post_proc_mesh);
492 post_proc_begin->getFEMethod());
493 CHKERR pip->loopFiniteElements();
495 post_proc_end->getFEMethod());
497 CHKERR post_proc_end->writeFile(
"out_elastic.h5m");
508 pip->getDomainRhsFE().reset();
509 pip->getDomainLhsFE().reset();
510 pip->getBoundaryRhsFE().reset();
511 pip->getBoundaryLhsFE().reset();
513 auto integration_rule = [](int, int,
int p_data) {
return 2 * p_data + 1; };
518 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
520 pip->getOpBoundaryRhsPipeline(), {},
"GEOMETRY");
523 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
524 mField, pip->getOpDomainRhsPipeline(),
"U",
"MAT_ELASTIC", Sev::verbose);
527 pip->getOpDomainRhsPipeline(),
mField,
"U", Sev::verbose);
530 pip->getOpBoundaryRhsPipeline(),
mField,
"U", -1, Sev::verbose);
532 auto dm =
simple->getDM();
533 auto res = createDMVector(dm);
534 CHKERR VecSetDM(res, PETSC_NULLPTR);
536 pip->getDomainRhsFE()->f = res;
537 pip->getBoundaryRhsFE()->f = res;
539 CHKERR VecZeroEntries(res);
541 CHKERR pip->loopFiniteElements();
544 CHKERR VecGhostUpdateBegin(res, ADD_VALUES, SCATTER_REVERSE);
545 CHKERR VecGhostUpdateEnd(res, ADD_VALUES, SCATTER_REVERSE);
546 CHKERR VecAssemblyBegin(res);
547 CHKERR VecAssemblyEnd(res);
549 auto zero_residual_at_constrains = [&]() {
551 auto fe_post_proc_ptr = boost::make_shared<FEMethod>();
552 auto get_post_proc_hook_rhs = [&]() {
554 CHKERR EssentialPreProcReaction<DisplacementCubitBcData>(
555 mField, fe_post_proc_ptr, res)();
556 CHKERR EssentialPostProcRhs<DisplacementCubitBcData>(
557 mField, fe_post_proc_ptr, 0, res)();
560 fe_post_proc_ptr->postProcessHook = get_post_proc_hook_rhs;
561 CHKERR DMoFEMPostProcessFiniteElements(dm, fe_post_proc_ptr.get());
565 CHKERR zero_residual_at_constrains();
568 CHKERR VecNorm(res, NORM_2, &nrm2);
570 MOFEM_LOG_C(
"WORLD", Sev::inform,
"residual = %3.4e\n", nrm2);
573 CHKERR PetscOptionsGetInt(PETSC_NULLPTR,
"",
"-test", &test, PETSC_NULLPTR);
575 auto post_proc_residual = [&](
auto dm,
auto f_res,
auto out_name) {
578 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
579 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
580 auto u_vec = boost::make_shared<MatrixDouble>();
581 post_proc_fe->getOpPtrVector().push_back(
582 new OpCalculateVectorFieldValues<SPACE_DIM>(
"U", u_vec, f_res));
583 post_proc_fe->getOpPtrVector().push_back(
587 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
597 CHKERR DMoFEMLoopFiniteElements(dm,
simple->getDomainFEName(),
599 post_proc_fe->writeFile(out_name);
603 CHKERR post_proc_residual(
simple->getDM(), res,
"res.h5m");
605 constexpr double eps = 1e-8;
608 "Residual is not zero");
611 if (!vectorFieldPtr || vectorFieldPtr->size1() == 0) {
613 "atom test %d failed: Field Evaluator did not provide result",
616 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
617 double Ux_ref = 0.46;
618 double Uy_ref = -0.03;
619 constexpr double eps = 1e-8;
620 if (fabs(t_disp(0) - Ux_ref) >
eps || fabs(t_disp(1) - Uy_ref) >
eps) {
622 "atom test %d failed: Ux_ref = %3.6e, computed = %3.6e, Uy_ref "
623 "= %3.6e, computed = %3.6e",
624 test, Ux_ref, t_disp(0), Uy_ref, t_disp(1));
Boundary conditions in domain, i.e. body forces.