5#include <boost/python.hpp>
6#include <boost/python/def.hpp>
7#include <boost/python/numpy.hpp>
8namespace bp = boost::python;
9namespace np = boost::python::numpy;
26 IntegrationType::GAUSS;
50 BoundaryEle::UserDataOperator;
91template <
int SPACE_DIM, IntegrationType I,
typename OpBase>
98#include <ElasticSpring.hpp>
99#include <FluidLevel.hpp>
100#include <CalculateTraction.hpp>
101#include <NaturalDomainBC.hpp>
102#include <NaturalBoundaryBC.hpp>
103#include <HookeOps.hpp>
110 const std::string block_name,
int dim);
143 Vec objective_function_gradient,
144 Vec adjoint_vector, Vec dJ_du);
155 boost::shared_ptr<ObjectiveFunctionData>
164 char objective_function_file_name[255] =
"objective_function.py";
166 PETSC_NULLPTR, PETSC_NULLPTR,
"-objective_function",
167 objective_function_file_name, 255, PETSC_NULLPTR);
170 auto file_exists = [](std::string myfile) {
171 std::ifstream file(myfile.c_str());
177 if (!file_exists(objective_function_file_name)) {
178 MOFEM_LOG(
"WORLD", Sev::error) <<
"Objective function file NOT found: "
179 << objective_function_file_name;
186 char sensitivity_method_name[32] =
"adjoint";
188 "-sensitivity_method", sensitivity_method_name,
189 sizeof(sensitivity_method_name), PETSC_NULLPTR);
190 std::string sensitivity_method = sensitivity_method_name;
191 std::transform(sensitivity_method.begin(), sensitivity_method.end(),
192 sensitivity_method.begin(),
193 [](
unsigned char c) { return std::tolower(c); });
194 if (sensitivity_method ==
"direct") {
196 }
else if (sensitivity_method ==
"adjoint") {
200 "Unknown -sensitivity_method. Use 'direct' or 'adjoint'.");
203 <<
"Sensitivity method: " << sensitivity_method;
227 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Objective function value: " <<
f;
234 INSERT_VALUES, SCATTER_FORWARD);
242 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Topology optimization completed";
295 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
296 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
297 PetscInt choice_base_value = AINSWORTH;
299 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
301 switch (choice_base_value) {
305 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
310 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
344 auto project_ho_geometry = [&]() {
348 CHKERR project_ho_geometry();
364 auto create_adjoint_dm = [&]() {
367 constexpr int adjoint_field_order = 1;
369 auto add_field = [&]() {
374 for (
auto tt = MBEDGE;
375 tt <= moab::CN::TypeDimensionMap[
SPACE_DIM - 1].second; ++tt)
377 "ADJOINT_FIELD", adjoint_field_order);
384 auto add_adjoint_fe_impl = [&]() {
418 simple->getBitRefLevelMask());
423 auto set_adjoint_dm_imp = [&]() {
427 simple->getBitRefLevelMask());
429 CHKERR DMSetFromOptions(adjoint_dm);
436 CHKERR DMSetUp(adjoint_dm);
461 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_X",
463 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Y",
465 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Z",
467 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
468 "REMOVE_ALL",
"U", 0, 3);
470 simple->getProblemName(),
"U");
472 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_X",
473 "ADJOINT_FIELD", 0, 0);
474 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_Y",
475 "ADJOINT_FIELD", 1, 1);
476 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_Z",
477 "ADJOINT_FIELD", 2, 2);
478 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_ALL",
479 "ADJOINT_FIELD", 0, 3);
480 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_X",
"ADJOINT_FIELD",
482 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_Y",
"ADJOINT_FIELD",
484 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_Z",
"ADJOINT_FIELD",
486 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_ALL",
487 "ADJOINT_FIELD", 0, 3);
509 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
510 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
514 pip->getOpDomainLhsPipeline(), {H1},
"GEOMETRY");
516 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
518 pip->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
520 pip->getOpBoundaryLhsPipeline(), {NOSPACE},
"GEOMETRY");
524 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
525 mField, pip->getOpDomainLhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
529 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
530 mField, pip->getOpDomainRhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
534 pip->getOpDomainRhsPipeline(),
mField,
"U", Sev::inform);
540 pip->getOpBoundaryRhsPipeline(),
mField,
"U", -1, Sev::inform);
543 pip->getOpBoundaryLhsPipeline(),
mField,
"U", Sev::noisy);
559 auto set_essential_bc = [&]() {
564 auto pre_proc_rhs = boost::make_shared<FEMethod>();
565 auto post_proc_rhs = boost::make_shared<FEMethod>();
566 auto post_proc_lhs = boost::make_shared<FEMethod>();
568 auto get_pre_proc_hook = [&]() {
572 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
574 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
578 post_proc_rhs, 1.)();
582 auto get_post_proc_hook_lhs = [
this, post_proc_lhs]() {
586 post_proc_lhs, 1.)();
590 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
591 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
593 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
594 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
595 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
599 auto setup_and_solve = [&](
auto solver) {
601 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
602 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp";
604 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp <= Done";
605 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve";
607 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve <= Done";
614 CHKERR set_essential_bc();
617 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
618 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
621 auto evaluate_field_at_the_point = [&]() {
625 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
628 field_eval_coords.data(), &coords_dim,
634 auto field_eval_data =
638 ->buildTree<SPACE_DIM>(field_eval_data,
simple->getDomainFEName());
640 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
641 auto no_rule = [](
int,
int,
int) {
return -1; };
642 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
643 field_eval_fe_ptr->getRuleHook = no_rule;
645 field_eval_fe_ptr->getOpPtrVector().push_back(
649 ->evalFEAtThePoint<SPACE_DIM>(
650 field_eval_coords.data(), 1e-12,
simple->getProblemName(),
651 simple->getDomainFEName(), field_eval_data,
659 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1);
662 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1)
663 <<
" U_Z: " << t_disp(2);
671 CHKERR evaluate_field_at_the_point();
684 std::vector<std::pair<std::string, SmartPetscObj<Vec>>> additional_vecs;
685 if (gradient_vector) {
686 additional_vecs.emplace_back(
"GRADIENT", gradient_vector);
688 if (adjoint_vector) {
689 additional_vecs.emplace_back(
"ADJOINT", adjoint_vector);
692 additional_vecs.emplace_back(
"dJ_dU", dJ_du);
697 "out_elastic_" + std::to_string(iter) +
".h5m", additional_vecs,
708 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
709 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
710 boost::shared_ptr<MatrixDouble> u_ptr)
722 auto nb_gauss_pts = getGaussPts().size2();
724 auto objective_dstress =
725 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
726 auto objective_dstrain =
727 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
729 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
731 auto evaluate_python = [&]() {
733 auto &coords = OP::getCoordsAtGaussPts();
744 auto vol = OP::getMeasure();
745 auto t_w = OP::getFTensor0IntegrationWeight();
748 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
753 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
755 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
756 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
758 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
759 const double alpha = t_w * vol;
761 t_adjoint_stress(
i,
j) =
762 t_D(
i,
j,
k,
l) * t_obj_dstress(
k,
l) + t_obj_dstrain(
i,
j);
764 auto t_nf = OP::template getNf<SPACE_DIM>();
766 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
767 t_nf(
j) += alpha * t_row_grad(
i) * t_adjoint_stress(
i,
j);
768 t_nf(
j) += alpha * t_row_base * t_obj_du(
j);
775 for (; rr < OP::nbRowBaseFunctions; ++rr) {
791 boost::shared_ptr<ObjectiveFunctionData>
pythonPtr;
792 boost::shared_ptr<HookeOps::CommonData>
commPtr;
793 boost::shared_ptr<MatrixDouble>
uPtr;
799 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
800 boost::shared_ptr<MatrixDouble> jac_ptr,
801 boost::shared_ptr<MatrixDouble> u_ptr,
802 boost::shared_ptr<double> glob_objective_ptr)
817 getGaussPts().size2();
819 auto objective_ptr = boost::make_shared<MatrixDouble>(
822 auto evaluate_python = [&]() {
824 auto &coords = OP::getCoordsAtGaussPts();
831 auto vol = OP::getMeasure();
832 auto t_w = getFTensor0IntegrationWeight();
833 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
835 auto alpha = t_w * vol;
836 (*globObjectivePtr) += alpha * t_obj;
852 boost::shared_ptr<HookeOps::CommonData>
commPtr;
854 boost::shared_ptr<MatrixDouble>
uPtr;
862 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
863 boost::shared_ptr<MatrixDouble> jac_ptr,
864 boost::shared_ptr<MatrixDouble> u_ptr,
865 boost::shared_ptr<MatrixDouble> grad_lambda_u_ptr,
866 boost::shared_ptr<double> glob_objective_ptr)
867 :
OP(
"ADJOINT_FIELD",
"ADJOINT_FIELD",
OP::OPROW),
pythonPtr(python_ptr),
881 const auto nb_gauss_pts =
882 getGaussPts().size2();
883 const auto nb_dofs = data.
getIndices().size();
898 auto t_diff_symm = FTensor::diff_symmetrize<double>();
901 auto objective_ptr = boost::make_shared<MatrixDouble>(
903 auto objective_dstress = boost::make_shared<MatrixDouble>(
906 auto objective_dstrain = boost::make_shared<MatrixDouble>(
911 auto evaluate_python = [&]() {
913 auto &coords = OP::getCoordsAtGaussPts();
925 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
commPtr->matGradPtr));
927 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
928 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
jacPtr));
929 auto t_grad_lambda_u =
934 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
936 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
938 auto vol = OP::getMeasure();
939 auto t_w = getFTensor0IntegrationWeight();
941 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
942 auto alpha = t_w * vol;
943 (*globObjectivePtr) += alpha * t_obj;
951 t_diff_inv_jac(
i,
j,
I,
J) =
952 -t_inv_jac(
i,
I) * t_inv_jac(
J,
j);
955 t_diff_grad(
i,
j,
I,
J) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j,
I,
J);
958 t_d_strain(
i,
j,
I,
J) =
959 t_diff_symm(
i,
j,
k,
l) * t_diff_grad(
k,
l,
I,
J);
961 auto t_local_grad_vector = OP::template getNf<SPACE_DIM>();
966 t_coef(
I) = (t_inv_jac(
J,
I) * t_base_diff(
J)) * t_det;
968 t_local_grad_vector(
I) +=
971 ((t_obj_dstress(
k,
l) * t_D(
k,
l,
i,
j)) +
972 t_obj_dstrain(
i,
j)) *
973 (t_d_strain(
i,
j,
I,
J) * t_base_diff(
J))
981 t_local_grad_vector(
I) -=
982 alpha * (t_grad_lambda_u(
i,
j) * t_D(
i,
j,
k,
l)) *
983 (t_d_strain(
k,
l,
I,
J) * t_base_diff(
J));
985 ++t_local_grad_vector;
988 for (; bb < nb_base_funcs; ++bb) {
1005 CHKERR evaluate_python();
1011 boost::shared_ptr<ObjectiveFunctionData>
pythonPtr;
1012 boost::shared_ptr<HookeOps::CommonData>
commPtr;
1013 boost::shared_ptr<MatrixDouble>
jacPtr;
1014 boost::shared_ptr<MatrixDouble>
uPtr;
1021 Vec objective_function_gradient,
1028 auto get_essential_fe = [
this]() {
1029 auto post_proc_rhs = boost::make_shared<FEMethod>();
1030 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1033 post_proc_rhs, 0)();
1036 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1037 return post_proc_rhs;
1040 auto get_objective_fe = [&](
auto lambda_vec,
auto glob_objective_ptr,
1042 auto fe_obj = boost::make_shared<DomainEle>(
mField);
1043 fe_obj->getRuleHook = fe_rule;
1044 auto &pip = fe_obj->getOpPtrVector();
1047 auto jac_ptr = boost::make_shared<MatrixDouble>();
1048 auto u_ptr = boost::make_shared<MatrixDouble>();
1049 auto grad_lambda_ptr = boost::make_shared<MatrixDouble>();
1052 "GEOMETRY", jac_ptr));
1056 "U", grad_lambda_ptr, lambda_smart_vec));
1058 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1059 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1062 glob_objective_ptr));
1066 auto evaluate_objective_terms =
1067 [&](
auto objective_fe,
auto objective_ptr) {
1069 *objective_ptr = 0.0;
1070 CHKERR VecZeroEntries(objective_function_gradient);
1071 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1072 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1073 objective_fe->f = objective_function_gradient;
1076 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1078 CHKERR VecAssemblyBegin(objective_function_gradient);
1079 CHKERR VecAssemblyEnd(objective_function_gradient);
1080 CHKERR VecGhostUpdateBegin(objective_function_gradient, ADD_VALUES,
1082 CHKERR VecGhostUpdateEnd(objective_function_gradient, ADD_VALUES,
1087 auto calculate_variance_of_objective_function_dJ_du = [&]() {
1089 auto fe = boost::make_shared<DomainEle>(
mField);
1090 fe->getRuleHook = [](int, int,
int p_data) {
1091 return 2 * p_data + p_data - 1;
1093 auto &pip = fe->getOpPtrVector();
1095 auto u_ptr = boost::make_shared<MatrixDouble>();
1097 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1098 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1100 CHKERR VecZeroEntries(dJ_du);
1103 CHKERR VecAssemblyBegin(dJ_du);
1104 CHKERR VecAssemblyEnd(dJ_du);
1105 auto post_proc_rhs = get_essential_fe();
1106 post_proc_rhs->f = dJ_du;
1108 post_proc_rhs.get());
1112 auto calculate_adjoint_lambda = [&]() {
1115 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Solving for adjoint variable lambda";
1118 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1119 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1123 auto fe_rule = [](int, int,
int p_data) {
return 2 * p_data + p_data - 1; };
1124 auto objective_ptr_value = boost::make_shared<double>(0.0);
1125 auto objective_fe = get_objective_fe(
lambda, objective_ptr_value, fe_rule);
1127 auto adjoint = [&]() {
1130 CHKERR calculate_variance_of_objective_function_dJ_du();
1131 CHKERR calculate_adjoint_lambda();
1132 CHKERR evaluate_objective_terms(objective_fe, objective_ptr_value);
1133 *objective_function_value = *objective_ptr_value;
1136 <<
"Objective function: " << *objective_function_value;
1138 CHKERR VecAssemblyBegin(objective_function_gradient);
1139 CHKERR VecAssemblyEnd(objective_function_gradient);
1140 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1141 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1149 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Adjoint Sensitivity...";
1155 "Wrong sensitivity type selected");
1158 CHKERR VecAssemblyBegin(objective_function_gradient);
1159 CHKERR VecAssemblyEnd(objective_function_gradient);
1169 PetscBool gradient_fd_check = PETSC_FALSE;
1171 &gradient_fd_check, PETSC_NULLPTR);
1172 if (gradient_fd_check) {
1174 PetscInt nb_modes = 5;
1176 "-gradient_nb_modes", &nb_modes, PETSC_NULLPTR);
1182 auto fe_rule = [](int, int,
int p_data) {
return 2 * p_data + p_data - 1; };
1183 auto get_objective_fe = [&](
auto glob_objective_ptr,
auto fe_rule) {
1184 auto fe_obj_fe = boost::make_shared<DomainEle>(
mField);
1185 fe_obj_fe->getRuleHook = fe_rule;
1186 auto &pip = fe_obj_fe->getOpPtrVector();
1188 auto jac_ptr = boost::make_shared<MatrixDouble>();
1189 auto u_ptr = boost::make_shared<MatrixDouble>();
1191 "GEOMETRY", jac_ptr));
1193 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1194 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1196 glob_objective_ptr));
1200 auto f = boost::make_shared<double>(0.);
1201 auto fe_obj = get_objective_fe(
f, fe_rule);
1206 auto evaluate_objective_terms = [&](
auto objective_fe,
auto objective_ptr,
1207 double &objective_value) {
1209 *objective_ptr = 0.0;
1212 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1214 objective_value = *objective_ptr;
1219 for (PetscInt mode = 0; mode < nb_modes; ++mode) {
1221 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Processing mode: " << mode;
1227 auto a_dof = adj_dofs.find(mode);
1228 if (a_dof != adj_dofs.end()) {
1229 auto ent = (*a_dof)->getEnt();
1230 auto dof_idx = (*a_dof)->getEntDofIdx();
1234 auto dof = dofs.find(uid);
1235 if (dof != dofs.end()) {
1236 auto org_geom_val = (*dof)->getFieldData();
1237 constexpr double eps = 1e-6;
1239 (*dof)->getFieldData() = org_geom_val +
eps;
1243 CHKERR evaluate_objective_terms(fe_obj,
f, f_plus);
1245 (*dof)->getFieldData() = org_geom_val -
eps;
1249 CHKERR evaluate_objective_terms(fe_obj,
f, f_minus);
1252 CHKERR VecGetArray(gradient_vector, &g_array);
1253 if ((*a_dof)->getHasLocalIndex()) {
1254 auto adjoint_grad = g_array[(*a_dof)->getPetscLocalDofIdx()];
1255 auto finite_diff_grad = (f_plus - f_minus) / (2 *
eps);
1256 auto err = std::abs(adjoint_grad - finite_diff_grad) /
1257 std::max(std::abs(adjoint_grad),
1258 std::abs(finite_diff_grad));
1260 <<
"Mode: " << mode <<
", Adjoint gradient: " << adjoint_grad
1261 <<
", Finite difference gradient: " << finite_diff_grad
1262 <<
", Relative error: "
1263 << std::abs(adjoint_grad - finite_diff_grad) /
1264 std::max(std::abs(adjoint_grad),
1265 std::abs(finite_diff_grad));
1266 constexpr double tol = 1e-4;
1269 "Gradient check failed for mode %d: relative error %e is "
1270 "greater than tolerance %e",
1275 CHKERR VecRestoreArray(gradient_vector, &g_array);
1277 constexpr bool restore_solution =
false;
1278 if constexpr (restore_solution) {
1279 (*dof)->getFieldData() = org_geom_val;
1301 const char param_file[] =
"param_file.petsc";
1304 auto core_log = logging::core::get();
1316 DMType dm_name =
"DMMOFEM";
1318 DMType dm_name_mg =
"DMMOFEM_MG";
1323 moab::Core mb_instance;
1324 moab::Interface &moab = mb_instance;
1342 if (Py_FinalizeEx() < 0) {
1348 const std::string block_name,
int dim) {
1354 std::regex((boost::format(
"%s(.*)") % block_name).str())
1358 for (
auto bc : bcs) {
1362 "get meshset ents");
1366 for (
auto dd = dim - 1; dd >= 0; --dd) {
1370 moab::Interface::UNION),
1390 CHKERR moab.add_entities(*out_meshset, r);
1391 CHKERR moab.write_file(name.c_str(),
"VTK",
"", out_meshset->get_ptr(), 1);
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
Interface for Python-based objective function evaluation in topology optimization.
#define FTENSOR_INDEX(DIM, I)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
SensitivityMethod derivative_type
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
#define CATCH_ERRORS
Catch errors.
FieldApproximationBase
approximation base
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_ATOM_TEST_INVALID
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
PostProcEleByDim< SPACE_DIM >::PostProcEleDomain PostProcEleDomain
PostProcEleByDim< SPACE_DIM >::PostProcEleBdy PostProcEleBdy
static char help[]
[Finite difference check]
PetscBool is_plane_strain
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle DomainEle
Domain finite elements.
constexpr int SPACE_DIM
[Define dimension]
SensitivityMethod derivative_type
constexpr double poisson_ratio
Poisson's ratio ν
constexpr int BASE_DIM
[Constants and material properties]
constexpr double shear_modulus_G
Shear modulus G = E/(2(1+ν))
constexpr IntegrationType I
Use Gauss quadrature for integration.
constexpr double bulk_modulus_K
Bulk modulus K = E/(3(1-2ν))
FormsIntegrators< DomainEleOp >::Assembly< A >::OpBase DomainBaseOp
[Postprocess results]
constexpr AssemblyType A
[Define dimension]
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::BoundaryEle BoundaryEle
Boundary finite elements.
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
constexpr double young_modulus
[Material properties for linear elasticity]
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
MoFEMErrorCode DMRegister_MGViaApproxOrders(const char sname[])
Register DM for Multi-Grid via approximation orders.
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
virtual const DofEntity_multiIndex * get_dofs() const =0
Get the dofs object.
virtual MoFEMErrorCode add_ents_to_finite_element_by_dim(const EntityHandle entities, const int dim, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode add_ents_to_field_by_dim(const Range &ents, const int dim, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
FTensor::Index< 'J', DIM1 > J
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
MoFEMErrorCode postProcessElasticResults(MoFEM::Interface &mField, SmartPetscObj< DM > dm, const std::string &domain_fe_name, const std::string &out_file_name, std::vector< std::pair< std::string, SmartPetscObj< Vec > > > extra_vectors={}, const std::vector< std::string > &tags_to_transfer={}, const Sev hooke_ops_sev=Sev::verbose)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PetscErrorCode PetscOptionsGetRealArray(PetscOptions *, const char pre[], const char name[], PetscReal dval[], PetscInt *nmax, PetscBool *set)
auto getDMKspCtx(DM dm)
Get KSP context data structure used by DM.
static MoFEMErrorCode invertTensor(FTensor::Tensor2< T1, DIM, DIM > &t, T2 &det, FTensor::Tensor2< T3, DIM, DIM > &inv_t)
static auto determinantTensor(FTensor::Tensor2< T, DIM, DIM > &t)
Calculate the determinant of a tensor of rank DIM.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
auto getFTensor0FromMat(M &data)
Get tensor rank 0 (scalar) form data vector.
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
boost::shared_ptr< CacheTuple > CacheTupleSharedPtr
auto getProblemPtr(DM dm)
get problem pointer from DM
boost::shared_ptr< ObjectiveFunctionData > create_python_objective_function(std::string)
constexpr auto field_name
static constexpr int approx_order
PetscBool is_plane_strain
Boundary conditions marker.
MoFEMErrorCode boundaryCondition()
MoFEMErrorCode assembleSystem()
MoFEMErrorCode readMesh()
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Interface to Python objective function.
SmartPetscObj< DM > adjointDM
Data manager for adjoint problem.
FieldApproximationBase base
Choice of finite element basis functions.
SmartPetscObj< KSP > kspElastic
Linear solver for elastic problem.
MoFEMErrorCode testGradient(Vec gradient_vector)
[calculateGradient]
int fieldOrder
Polynomial order for approximation.
Example(MoFEM::Interface &m_field)
MoFEMErrorCode runProblem()
Main driver function for the optimization process.
MoFEMErrorCode calculateGradient(PetscReal *objective_function_value, Vec objective_function_gradient, Vec adjoint_vector)
Calculate objective function gradient using adjoint method.
MoFEMErrorCode setupAdJoint()
MoFEM::Interface & mField
Reference to MoFEM interface.
MoFEMErrorCode setupProblem()
MoFEMErrorCode postprocessElastic(int iter, SmartPetscObj< Vec > adjoint_vector=nullptr)
Post-process and output results.
MoFEMErrorCode solveElastic()
Solve forward elastic problem.
boost::shared_ptr< MatrixDouble > vectorFieldPtr
Field values at evaluation points.
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
MoFEMErrorCode synchroniseEntities(Range &ent, std::map< int, Range > *received_ents, int verb=DEFAULT_VERBOSITY)
synchronize entity range on processors (collective)
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
virtual moab::Interface & get_moab()=0
virtual MoFEMErrorCode cache_problem_entities(const std::string prb_name, CacheTupleWeakPtr cache_ptr)=0
Cache variables.
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Deprecated interface functions.
Definition of the displacement bc data structure.
static UId getUniqueIdCalculate(const DofIdx dof, UId ent_uid)
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
auto getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
Class (Function) to enforce essential constrains on the left hand side diagonal.
Class (Function) to enforce essential constrains on the right hand side diagonal.
Class (Function) to enforce essential constrains.
UId getLocalUniqueIdCalculate()
Get the Local Unique Id Calculate object.
Field evaluator interface.
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
Interface for managing meshsets containing materials and boundary conditions.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for MatrixDouble vector field values calculation.
Template struct for dimension-specific finite element types.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
Problem manager is used to build and partition problems.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
MoFEMErrorCode getOptions()
get options
MoFEMErrorCode getDM(DM *dm)
Get DM.
const std::string getDomainFEName() const
Get the Domain FE Name.
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
boost::shared_ptr< HookeOps::CommonData > commPtr
ForcesAndSourcesCore::UserDataOperator OP
boost::shared_ptr< double > globObjectivePtr
OpAdJointObjective(boost::shared_ptr< ObjectiveFunctionData > python_ptr, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > jac_ptr, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > grad_lambda_u_ptr, boost::shared_ptr< double > glob_objective_ptr)
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
boost::shared_ptr< MatrixDouble > gradLambdaUPtr
boost::shared_ptr< MatrixDouble > uPtr
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
Compute objective function contributions at element level.
boost::shared_ptr< MatrixDouble > jacPtr
boost::shared_ptr< double > globObjectivePtr
ForcesAndSourcesCore::UserDataOperator OP
boost::shared_ptr< MatrixDouble > jacPtr
OpObjective(boost::shared_ptr< ObjectiveFunctionData > python_ptr, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > jac_ptr, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< double > glob_objective_ptr)
boost::shared_ptr< MatrixDouble > uPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Compute objective function contributions at element level.
boost::shared_ptr< HookeOps::CommonData > commPtr
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
boost::shared_ptr< HookeOps::CommonData > commPtr
OpStateSensitivity(const std::string field_name, boost::shared_ptr< ObjectiveFunctionData > python_ptr, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > u_ptr)
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
boost::shared_ptr< MatrixDouble > uPtr
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle
#define EXECUTABLE_DIMENSION
PetscBool do_eval_field
Evaluate field.
ElementsAndOps< SPACE_DIM >::SideEle SideEle
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::BoundaryEle BoundaryEle
PostProcEleByDim< SPACE_DIM >::SideEle SideEle
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle DomainEle