13 using namespace MoFEM;
125 boost::shared_ptr<ClosestPointProjection>
cpPtr;
134 CHKERR boundaryCondition();
164 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
165 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
166 PetscInt choice_base_value = AINSWORTH;
168 LASBASETOPT, &choice_base_value, PETSC_NULL);
170 switch (choice_base_value) {
174 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
179 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
204 VonMissesPlaneStress,
208 const char *list_materials[LastModel] = {
"VonMisses",
"VonMissesPlaneStress",
210 PetscInt choice_material = VonMisses;
212 LastModel, &choice_material, PETSC_NULL);
214 switch (choice_material) {
216 cpPtr = createMaterial<J2Plasticity<3>>();
218 case VonMissesPlaneStress:
221 "VonMissesPlaneStrain is only for 2D case");
222 cpPtr = createMaterial<J2Plasticity<2>>();
225 cpPtr = createMaterial<ParaboloidalPlasticity>();
232 cpPtr->integrationRule = [](
int,
int,
int p) {
return 2 * (p - 2); };
246 auto time_scale = boost::make_shared<TimeScale>();
248 auto rule = [](
int,
int,
int p) {
return 2 * p; };
249 CHKERR pipeline_mng->setDomainRhsIntegrationRule(cpPtr->integrationRule);
250 CHKERR pipeline_mng->setDomainLhsIntegrationRule(cpPtr->integrationRule);
251 CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(rule);
255 pipeline_mng->getOpBoundaryRhsPipeline(), mField,
"U", {time_scale},
259 pipeline_mng->getOpBoundaryRhsPipeline(), mField,
"U", Sev::inform);
263 pipeline_mng->getOpDomainRhsPipeline(), mField,
"U", {time_scale},
264 "BODY_FORCE", Sev::inform);
267 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_X",
269 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Y",
271 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Z",
274 simple->getProblemName(),
"U");
287 auto add_domain_ops_lhs = [&](
auto &pip) {
292 auto common_data_ptr = boost::make_shared<ADOLCPlasticity::CommonData>();
295 "U", common_data_ptr->getGardAtGaussPtsPtr()));
297 CHKERR opFactoryDomainLhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
298 mField,
"U", pip,
"ADOLCMAT", common_data_ptr, cpPtr);
302 auto add_domain_ops_rhs = [&](
auto &pip) {
307 auto common_data_ptr = boost::make_shared<ADOLCPlasticity::CommonData>();
310 "U", common_data_ptr->getGardAtGaussPtsPtr()));
312 CHKERR opFactoryDomainRhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
313 mField,
"U", pip,
"ADOLCMAT", common_data_ptr, cpPtr, Sev::inform);
319 CHKERR add_domain_ops_lhs(pipeline_mng->getOpDomainLhsPipeline());
321 CHKERR add_domain_ops_rhs(pipeline_mng->getOpDomainRhsPipeline());
335 std::pair<boost::shared_ptr<PostProcEleDomain>,
336 boost::shared_ptr<PostProcEleBdy>>
338 boost::shared_ptr<DomainEle> reaction_fe,
339 std::vector<boost::shared_ptr<ScalingMethod>> smv)
340 : dM(dm), reactionFE(reaction_fe), vecOfTimeScalingMethods(smv) {
342 domainPostProcFe = pair_post_proc_fe.first;
343 skinPostProcFe = pair_post_proc_fe.second;
350 auto make_vtk = [&]() {
352 if (domainPostProcFe) {
355 CHKERR domainPostProcFe->writeFile(
356 "out_plastic_" + boost::lexical_cast<std::string>(ts_step) +
359 if (skinPostProcFe) {
362 CHKERR skinPostProcFe->writeFile(
363 "out_skin_plastic_" + boost::lexical_cast<std::string>(ts_step) +
373 CHKERR VecZeroEntries(fRes);
374 reactionFE->f = fRes;
376 CHKERR VecAssemblyBegin(fRes);
377 CHKERR VecAssemblyEnd(fRes);
378 CHKERR VecGhostUpdateBegin(fRes, ADD_VALUES, SCATTER_REVERSE);
379 CHKERR VecGhostUpdateEnd(fRes, ADD_VALUES, SCATTER_REVERSE);
384 *m_field_ptr, reactionFE, fRes)();
387 CHKERR VecNorm(fRes, NORM_2, &nrm);
389 <<
"Residual norm " << nrm <<
" at time step " << ts_step;
392 auto get_min_max_displacement = [&]() {
397 std::array<double, 4> a_min = {DBL_MAX, DBL_MAX, DBL_MAX, 0};
398 std::array<double, 4> a_max = {-DBL_MAX, -DBL_MAX, -DBL_MAX, 0};
400 auto get_min_max = [&](boost::shared_ptr<FieldEntity> field_entity_ptr) {
403 for (
auto v : field_entity_ptr->getEntFieldData()) {
404 a_min[
d] = std::min(a_min[
d],
v);
405 a_max[
d] = std::max(a_max[
d],
v);
417 get_min_max,
"U", &verts);
419 auto mpi_reduce = [&](
auto &
a,
auto op) {
420 std::array<double, 3> a_mpi = {0, 0, 0};
421 MPI_Allreduce(
a.data(), a_mpi.data(), 3, MPI_DOUBLE, op,
426 auto a_min_mpi = mpi_reduce(a_min, MPI_MIN);
427 auto a_max_mpi = mpi_reduce(a_max, MPI_MAX);
430 <<
"Min displacement " << a_min_mpi[0] <<
" " << a_min_mpi[1] <<
" "
433 <<
"Max displacement " << a_max_mpi[0] <<
" " << a_max_mpi[1] <<
" "
438 CHKERR get_min_max_displacement();
441 for (
auto s : vecOfTimeScalingMethods) {
442 scale *= s->getScale(this->ts_t);
446 <<
"Time: " << this->ts_t <<
" scale: " <<
scale;
468 auto dm =
simple->getDM();
469 auto time_scale = boost::make_shared<TimeScale>();
472 auto create_post_proc_fe = [dm,
this,
simple]() {
476 auto post_proc_ele_domain = [
this](
auto &pip_domain,
auto &fe_name) {
483 auto grad_ptr = boost::make_shared<MatrixDouble>();
484 pip_domain.push_back(
494 pip_domain.push_back(op_this);
498 auto fe_physics = op_this->getThisFEPtr();
500 auto evaluate_stress_on_physical_element = [&]() {
502 fe_physics->getRuleHook = cpPtr->integrationRule;
504 fe_physics->getOpPtrVector(), {H1});
505 auto common_data_ptr =
506 boost::make_shared<ADOLCPlasticity::CommonData>();
509 fe_physics->getOpPtrVector().push_back(
511 "U", common_data_ptr->getGardAtGaussPtsPtr()));
513 CHKERR cpPtr->addMatBlockOps(mField, fe_physics->getOpPtrVector(),
514 "ADOLCMAT", Sev::noisy);
515 fe_physics->getOpPtrVector().push_back(
516 getRawPtrOpCalculateStress<SPACE_DIM>(mField, common_data_ptr,
518 return common_data_ptr;
521 auto dg_projection_froward_and_back = [&](
auto &common_data_ptr) {
523 int dg_order = approxOrder - 1;
524 auto entity_data_l2 =
525 boost::make_shared<EntitiesFieldData>(MBENTITYSET);
527 boost::make_shared<MatrixDouble>();
530 dg_order, mass_ptr, entity_data_l2, approxBase,
L2));
532 auto coeffs_ptr_stress = boost::make_shared<MatrixDouble>();
535 common_data_ptr->getStressMatrixPtr(), coeffs_ptr_stress, mass_ptr,
536 entity_data_l2, approxBase,
L2));
538 auto coeffs_ptr_plastic_strain = boost::make_shared<MatrixDouble>();
540 common_data_ptr->getPlasticStrainMatrixPtr(),
541 coeffs_ptr_plastic_strain, mass_ptr, entity_data_l2, approxBase,
547 common_data_ptr->getStressMatrixPtr(), coeffs_ptr_stress,
548 entity_data_l2, approxBase,
L2));
550 common_data_ptr->getPlasticStrainMatrixPtr(),
551 coeffs_ptr_plastic_strain, entity_data_l2, approxBase,
L2));
554 auto common_data_ptr = evaluate_stress_on_physical_element();
555 dg_projection_froward_and_back(common_data_ptr);
557 return boost::make_tuple(grad_ptr, common_data_ptr->getStressMatrixPtr(),
558 common_data_ptr->getPlasticStrainMatrixPtr());
564 auto add_post_proc_map = [&](
auto post_proc_fe,
auto u_ptr,
auto grad_ptr,
565 auto stress_ptr,
auto plastic_strain_ptr) {
567 post_proc_fe->getOpPtrVector().push_back(
569 new OpPPMapSPACE_DIM(
571 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
577 {{
"GRAD", grad_ptr}},
586 post_proc_fe->getOpPtrVector().push_back(
590 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
598 {{
"STRESS", stress_ptr}, {
"PLASTIC_STRAIN", plastic_strain_ptr}}
607 auto vol_post_proc = [
this,
simple, post_proc_ele_domain,
608 add_post_proc_map]() {
609 PetscBool post_proc_vol = PETSC_FALSE;
611 post_proc_vol = PETSC_TRUE;
614 &post_proc_vol, PETSC_NULL);
615 if (post_proc_vol == PETSC_FALSE)
616 return boost::shared_ptr<PostProcEleDomain>();
617 auto post_proc_fe = boost::make_shared<PostProcEleDomain>(mField);
618 auto u_ptr = boost::make_shared<MatrixDouble>();
619 post_proc_fe->getOpPtrVector().push_back(
621 auto [grad_ptr, stress_ptr, plastic_strain_ptr] = post_proc_ele_domain(
622 post_proc_fe->getOpPtrVector(),
simple->getDomainFEName());
623 return add_post_proc_map(post_proc_fe, u_ptr, grad_ptr, stress_ptr,
627 auto skin_post_proc = [
this,
simple, post_proc_ele_domain,
628 add_post_proc_map]() {
631 PetscBool post_proc_skin = PETSC_TRUE;
633 post_proc_skin = PETSC_FALSE;
636 &post_proc_skin, PETSC_NULL);
638 if (post_proc_skin == PETSC_FALSE)
639 return boost::shared_ptr<PostProcEleBdy>();
641 auto post_proc_fe = boost::make_shared<PostProcEleBdy>(mField);
642 auto u_ptr = boost::make_shared<MatrixDouble>();
643 post_proc_fe->getOpPtrVector().push_back(
647 auto [grad_ptr, stress_ptr, plastic_strain_ptr] = post_proc_ele_domain(
648 op_loop_side->getOpPtrVector(),
simple->getDomainFEName());
649 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
650 return add_post_proc_map(post_proc_fe, u_ptr, grad_ptr, stress_ptr,
654 return std::make_pair(vol_post_proc(), skin_post_proc());
657 auto create_reaction_fe = [&]() {
658 auto fe_ptr = boost::make_shared<DomainEle>(mField);
659 fe_ptr->getRuleHook = cpPtr->integrationRule;
661 auto &pip = fe_ptr->getOpPtrVector();
663 auto common_data_ptr = boost::make_shared<ADOLCPlasticity::CommonData>();
665 "U", common_data_ptr->getGardAtGaussPtsPtr()));
666 CHKERR opFactoryDomainRhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
667 mField,
"U", pip,
"ADOLCMAT", common_data_ptr, cpPtr, Sev::noisy);
672 auto add_extra_finite_elements_to_ksp_solver_pipelines = [&]() {
675 auto pre_proc_ptr = boost::make_shared<FEMethod>();
676 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
677 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
679 auto get_bc_hook_rhs = [
this, pre_proc_ptr, time_scale]() {
682 {time_scale},
false)();
686 pre_proc_ptr->preProcessHook = get_bc_hook_rhs;
688 auto get_post_proc_hook_rhs = [
this, post_proc_rhs_ptr]() {
691 mField, post_proc_rhs_ptr,
nullptr, Sev::verbose)();
693 mField, post_proc_rhs_ptr, 1.)();
696 auto get_post_proc_hook_lhs = [
this, post_proc_lhs_ptr]() {
699 mField, post_proc_lhs_ptr, 1.)();
702 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
703 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs;
707 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
708 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
709 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
710 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
716 CHKERR add_extra_finite_elements_to_ksp_solver_pipelines();
718 auto create_monitor_fe = [dm, time_scale](
auto &&post_proc_fe,
719 auto &&reaction_fe) {
720 return boost::make_shared<Monitor>(
721 dm, post_proc_fe, reaction_fe,
722 std::vector<boost::shared_ptr<ScalingMethod>>{time_scale});
726 auto set_up_post_step = [&](
auto ts) {
731 auto create_update_ptr = [&]() {
732 auto fe_ptr = boost::make_shared<DomainEle>(mField);
733 fe_ptr->getRuleHook = cpPtr->integrationRule;
736 auto common_data_ptr = boost::make_shared<ADOLCPlasticity::CommonData>();
737 fe_ptr->getOpPtrVector().push_back(
739 "U", common_data_ptr->getGardAtGaussPtsPtr()));
741 opFactoryDomainUpdate<SPACE_DIM>(mField, fe_ptr->getOpPtrVector(),
742 "ADOLCMAT", common_data_ptr, cpPtr),
753 auto ts_step_post_proc = [](TS ts) {
762 CHKERR TSSetPostStep(ts, ts_step_post_proc);
768 auto set_up_monitor = [&](
auto ts) {
770 boost::shared_ptr<FEMethod> null_fe;
772 create_monitor_fe(create_post_proc_fe(), create_reaction_fe());
774 null_fe, monitor_ptr);
778 auto set_up_adapt = [&](
auto ts) {
782 CHKERR TSGetAdapt(ts, &adapt);
787 auto ts = pipeline_mng->createTSIM();
791 CHKERR TSSetMaxTime(ts, ftime);
792 CHKERR TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP);
797 CHKERR set_up_monitor(ts);
798 CHKERR set_up_post_step(ts);
800 CHKERR TSSetFromOptions(ts);
805 CHKERR TSGetTime(ts, &ftime);
807 PetscInt steps, snesfails, rejects, nonlinits, linits;
808 CHKERR TSGetStepNumber(ts, &steps);
809 CHKERR TSGetSNESFailures(ts, &snesfails);
810 CHKERR TSGetStepRejections(ts, &rejects);
811 CHKERR TSGetSNESIterations(ts, &nonlinits);
812 CHKERR TSGetKSPIterations(ts, &linits);
814 "steps %d (%d rejected, %d SNES fails), ftime %g, nonlinits "
816 steps, rejects, snesfails, ftime, nonlinits, linits);
827 auto dm =
simple->getDM();
833 CHKERR VecNorm(T, NORM_2, &nrm2);
834 MOFEM_LOG(
"PlasticPrb", Sev::inform) <<
"Solution norm " << nrm2;
836 auto post_proc_norm_fe = boost::make_shared<DomainEle>(
mField);
838 post_proc_norm_fe->getRuleHook =
cpPtr->integrationRule;
841 post_proc_norm_fe->getOpPtrVector(), {H1});
843 enum NORMS { U_NORM_L2 = 0, PIOLA_NORM, LAST_NORM };
847 CHKERR VecZeroEntries(norms_vec);
849 auto u_ptr = boost::make_shared<MatrixDouble>();
850 post_proc_norm_fe->getOpPtrVector().push_back(
853 post_proc_norm_fe->getOpPtrVector().push_back(
859 CHKERR VecAssemblyBegin(norms_vec);
860 CHKERR VecAssemblyEnd(norms_vec);
865 CHKERR VecGetArrayRead(norms_vec, &norms);
867 <<
"norm_u: " << std::scientific << std::sqrt(norms[U_NORM_L2]);
868 CHKERR VecRestoreArrayRead(norms_vec, &norms);
878 PetscInt test_nb = 0;
879 PetscBool test_flg = PETSC_FALSE;
888 CHKERR VecNorm(T, NORM_2, &nrm2);
889 MOFEM_LOG(
"PlasticPrb", Sev::verbose) <<
"Regression norm " << nrm2;
890 double regression_value = 0;
896 if (fabs(nrm2 - regression_value) > 1e-2)
898 "Regression test field; wrong norm value. %6.4e != %6.4e", nrm2,
912 static char help[] =
"...\n\n";
914 int main(
int argc,
char *argv[]) {
917 const char param_file[] =
"param_file.petsc";
921 auto core_log = logging::core::get();
923 LogManager::createSink(LogManager::getStrmWorld(),
"PlasticPrb"));
924 LogManager::setLog(
"PlasticPrb");
931 DMType dm_name =
"DMMOFEM";