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;
233 INSERT_VALUES, SCATTER_FORWARD);
241 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Topology optimization completed";
294 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
295 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
296 PetscInt choice_base_value = AINSWORTH;
298 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
300 switch (choice_base_value) {
304 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
309 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
343 auto project_ho_geometry = [&]() {
347 CHKERR project_ho_geometry();
363 auto create_adjoint_dm = [&]() {
366 constexpr int adjoint_field_order = 1;
368 auto add_field = [&]() {
373 for (
auto tt = MBEDGE;
374 tt <= moab::CN::TypeDimensionMap[
SPACE_DIM - 1].second; ++tt)
376 "ADJOINT_FIELD", adjoint_field_order);
383 auto add_adjoint_fe_impl = [&]() {
422 auto set_adjoint_dm_imp = [&]() {
428 CHKERR DMSetFromOptions(adjoint_dm);
435 CHKERR DMSetUp(adjoint_dm);
467 "REMOVE_ALL",
"U", 0, 3);
471 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_X",
472 "ADJOINT_FIELD", 0, 0);
473 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_Y",
474 "ADJOINT_FIELD", 1, 1);
475 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_Z",
476 "ADJOINT_FIELD", 2, 2);
477 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_ALL",
478 "ADJOINT_FIELD", 0, 3);
479 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_X",
"ADJOINT_FIELD",
481 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_Y",
"ADJOINT_FIELD",
483 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_Z",
"ADJOINT_FIELD",
485 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_ALL",
486 "ADJOINT_FIELD", 0, 3);
508 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
509 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
513 pip->getOpDomainLhsPipeline(), {H1},
"GEOMETRY");
515 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
517 pip->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
519 pip->getOpBoundaryLhsPipeline(), {NOSPACE},
"GEOMETRY");
523 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
524 mField, pip->getOpDomainLhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
528 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
529 mField, pip->getOpDomainRhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
533 pip->getOpDomainRhsPipeline(),
mField,
"U", Sev::inform);
539 pip->getOpBoundaryRhsPipeline(),
mField,
"U", -1, Sev::inform);
542 pip->getOpBoundaryLhsPipeline(),
mField,
"U", Sev::noisy);
558 auto set_essential_bc = [&]() {
563 auto pre_proc_rhs = boost::make_shared<FEMethod>();
564 auto post_proc_rhs = boost::make_shared<FEMethod>();
565 auto post_proc_lhs = boost::make_shared<FEMethod>();
567 auto get_pre_proc_hook = [&]() {
571 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
573 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
577 post_proc_rhs, 1.)();
581 auto get_post_proc_hook_lhs = [
this, post_proc_lhs]() {
585 post_proc_lhs, 1.)();
589 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
590 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
592 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
593 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
594 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
598 auto setup_and_solve = [&](
auto solver) {
600 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
601 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp";
603 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp <= Done";
604 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve";
606 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve <= Done";
613 CHKERR set_essential_bc();
616 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
617 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
620 auto evaluate_field_at_the_point = [&]() {
624 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
627 field_eval_coords.data(), &coords_dim,
633 auto field_eval_data =
639 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
640 auto no_rule = [](
int,
int,
int) {
return -1; };
641 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
642 field_eval_fe_ptr->getRuleHook = no_rule;
644 field_eval_fe_ptr->getOpPtrVector().push_back(
648 ->evalFEAtThePoint<SPACE_DIM>(
658 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1);
661 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1)
662 <<
" U_Z: " << t_disp(2);
670 CHKERR evaluate_field_at_the_point();
683 std::vector<std::pair<std::string, SmartPetscObj<Vec>>> additional_vecs;
684 if (gradient_vector) {
685 additional_vecs.emplace_back(
"GRADIENT", gradient_vector);
687 if (adjoint_vector) {
688 additional_vecs.emplace_back(
"ADJOINT", adjoint_vector);
691 additional_vecs.emplace_back(
"dJ_dU", dJ_du);
696 "out_elastic_" + std::to_string(iter) +
".h5m", additional_vecs,
714 t_diff(
i,
j,
k,
l) = 0;
715 t_diff(0, 0, 0, 0) = 1;
716 t_diff(1, 1, 1, 1) = 1;
718 t_diff(1, 0, 1, 0) = 0.5;
719 t_diff(1, 0, 0, 1) = 0.5;
721 t_diff(0, 1, 0, 1) = 0.5;
722 t_diff(0, 1, 1, 0) = 0.5;
724 if constexpr (DIM == 3) {
725 t_diff(2, 2, 2, 2) = 1;
727 t_diff(2, 0, 2, 0) = 0.5;
728 t_diff(2, 0, 0, 2) = 0.5;
729 t_diff(0, 2, 0, 2) = 0.5;
730 t_diff(0, 2, 2, 0) = 0.5;
732 t_diff(2, 1, 2, 1) = 0.5;
733 t_diff(2, 1, 1, 2) = 0.5;
734 t_diff(1, 2, 1, 2) = 0.5;
735 t_diff(1, 2, 2, 1) = 0.5;
744 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
745 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
746 boost::shared_ptr<MatrixDouble> u_ptr)
758 auto nb_gauss_pts = getGaussPts().size2();
760 auto objective_dstress =
761 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
762 auto objective_dstrain =
763 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
765 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
767 auto evaluate_python = [&]() {
769 auto &coords = OP::getCoordsAtGaussPts();
780 auto vol = OP::getMeasure();
781 auto t_w = OP::getFTensor0IntegrationWeight();
784 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
789 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
791 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
792 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
794 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
795 const double alpha = t_w * vol;
797 t_adjoint_stress(
i,
j) =
798 t_D(
i,
j,
k,
l) * t_obj_dstress(
k,
l) + t_obj_dstrain(
i,
j);
800 auto t_nf = OP::template getNf<SPACE_DIM>();
802 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
803 t_nf(
j) += alpha * t_row_grad(
i) * t_adjoint_stress(
i,
j);
804 t_nf(
j) += alpha * t_row_base * t_obj_du(
j);
811 for (; rr < OP::nbRowBaseFunctions; ++rr) {
827 boost::shared_ptr<ObjectiveFunctionData>
pythonPtr;
828 boost::shared_ptr<HookeOps::CommonData>
commPtr;
829 boost::shared_ptr<MatrixDouble>
uPtr;
835 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
836 boost::shared_ptr<MatrixDouble> jac_ptr,
837 boost::shared_ptr<MatrixDouble> u_ptr,
838 boost::shared_ptr<double> glob_objective_ptr)
853 getGaussPts().size2();
855 auto objective_ptr = boost::make_shared<MatrixDouble>(
858 auto evaluate_python = [&]() {
860 auto &coords = OP::getCoordsAtGaussPts();
867 auto vol = OP::getMeasure();
868 auto t_w = getFTensor0IntegrationWeight();
869 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
871 auto alpha = t_w * vol;
872 (*globObjectivePtr) += alpha * t_obj;
888 boost::shared_ptr<HookeOps::CommonData>
commPtr;
890 boost::shared_ptr<MatrixDouble>
uPtr;
898 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
899 boost::shared_ptr<MatrixDouble> jac_ptr,
900 boost::shared_ptr<MatrixDouble> u_ptr,
901 boost::shared_ptr<MatrixDouble> grad_lambda_u_ptr,
902 boost::shared_ptr<double> glob_objective_ptr)
903 :
OP(
"ADJOINT_FIELD",
"ADJOINT_FIELD",
OP::OPROW),
pythonPtr(python_ptr),
917 const auto nb_gauss_pts =
918 getGaussPts().size2();
919 const auto nb_dofs = data.
getIndices().size();
938 auto objective_ptr = boost::make_shared<MatrixDouble>(
940 auto objective_dstress = boost::make_shared<MatrixDouble>(
943 auto objective_dstrain = boost::make_shared<MatrixDouble>(
948 auto evaluate_python = [&]() {
950 auto &coords = OP::getCoordsAtGaussPts();
962 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
commPtr->matGradPtr));
964 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
965 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
jacPtr));
966 auto t_grad_lambda_u =
971 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
973 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
975 auto vol = OP::getMeasure();
976 auto t_w = getFTensor0IntegrationWeight();
978 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
979 auto alpha = t_w * vol;
980 (*globObjectivePtr) += alpha * t_obj;
988 t_diff_inv_jac(
i,
j,
I,
J) =
989 -t_inv_jac(
i,
I) * t_inv_jac(
J,
j);
992 t_diff_grad(
i,
j,
I,
J) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j,
I,
J);
995 t_d_strain(
i,
j,
I,
J) =
996 t_diff_symm(
i,
j,
k,
l) * t_diff_grad(
k,
l,
I,
J);
998 auto t_local_grad_vector = OP::template getNf<SPACE_DIM>();
1000 for (; bb != nb_dofs/
SPACE_DIM; bb++) {
1003 t_coef(
I) = (t_inv_jac(
J,
I) * t_base_diff(
J)) * t_det;
1005 t_local_grad_vector(
I) +=
1008 ((t_obj_dstress(
k,
l) * t_D(
k,
l,
i,
j)) +
1009 t_obj_dstrain(
i,
j)) *
1010 (t_d_strain(
i,
j,
I,
J) * t_base_diff(
J))
1018 t_local_grad_vector(
I) -=
1019 alpha * (t_grad_lambda_u(
i,
j) * t_D(
i,
j,
k,
l)) *
1020 (t_d_strain(
k,
l,
I,
J) * t_base_diff(
J));
1022 ++t_local_grad_vector;
1025 for (; bb < nb_base_funcs; ++bb) {
1042 CHKERR evaluate_python();
1048 boost::shared_ptr<ObjectiveFunctionData>
pythonPtr;
1049 boost::shared_ptr<HookeOps::CommonData>
commPtr;
1050 boost::shared_ptr<MatrixDouble>
jacPtr;
1051 boost::shared_ptr<MatrixDouble>
uPtr;
1058 Vec objective_function_gradient,
1065 auto get_essential_fe = [
this]() {
1066 auto post_proc_rhs = boost::make_shared<FEMethod>();
1067 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1070 post_proc_rhs, 0)();
1073 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1074 return post_proc_rhs;
1077 auto get_objective_fe = [&](
auto lambda_vec,
auto glob_objective_ptr,
1079 auto fe_obj = boost::make_shared<DomainEle>(
mField);
1080 fe_obj->getRuleHook = fe_rule;
1081 auto &pip = fe_obj->getOpPtrVector();
1084 auto jac_ptr = boost::make_shared<MatrixDouble>();
1085 auto u_ptr = boost::make_shared<MatrixDouble>();
1086 auto grad_lambda_ptr = boost::make_shared<MatrixDouble>();
1089 "GEOMETRY", jac_ptr));
1093 "U", grad_lambda_ptr, lambda_smart_vec));
1095 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1096 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1099 glob_objective_ptr));
1103 auto evaluate_objective_terms =
1104 [&](
auto objective_fe,
auto objective_ptr) {
1106 *objective_ptr = 0.0;
1107 CHKERR VecZeroEntries(objective_function_gradient);
1108 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1109 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1110 objective_fe->f = objective_function_gradient;
1113 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1115 CHKERR VecAssemblyBegin(objective_function_gradient);
1116 CHKERR VecAssemblyEnd(objective_function_gradient);
1117 CHKERR VecGhostUpdateBegin(objective_function_gradient, ADD_VALUES,
1119 CHKERR VecGhostUpdateEnd(objective_function_gradient, ADD_VALUES,
1124 auto calculate_variance_of_objective_function_dJ_du = [&]() {
1126 auto fe = boost::make_shared<DomainEle>(
mField);
1127 fe->getRuleHook = [](int, int,
int p_data) {
1128 return 2 * p_data + p_data - 1;
1130 auto &pip = fe->getOpPtrVector();
1132 auto u_ptr = boost::make_shared<MatrixDouble>();
1134 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1135 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1137 CHKERR VecZeroEntries(dJ_du);
1140 CHKERR VecAssemblyBegin(dJ_du);
1141 CHKERR VecAssemblyEnd(dJ_du);
1142 auto post_proc_rhs = get_essential_fe();
1143 post_proc_rhs->f = dJ_du;
1145 post_proc_rhs.get());
1149 auto calculate_adjoint_lambda = [&]() {
1152 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Solving for adjoint variable lambda";
1155 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1156 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1160 auto fe_rule = [](int, int,
int p_data) {
return 2 * p_data + p_data - 1; };
1161 auto objective_ptr_value = boost::make_shared<double>(0.0);
1162 auto objective_fe = get_objective_fe(
lambda, objective_ptr_value, fe_rule);
1164 auto adjoint = [&]() {
1167 CHKERR calculate_variance_of_objective_function_dJ_du();
1168 CHKERR calculate_adjoint_lambda();
1169 CHKERR evaluate_objective_terms(objective_fe, objective_ptr_value);
1170 *objective_function_value = *objective_ptr_value;
1173 <<
"Objective function: " << *objective_function_value;
1175 CHKERR VecAssemblyBegin(objective_function_gradient);
1176 CHKERR VecAssemblyEnd(objective_function_gradient);
1177 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1178 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1186 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Adjoint Sensitivity...";
1192 "Wrong sensitivity type selected");
1195 CHKERR VecAssemblyBegin(objective_function_gradient);
1196 CHKERR VecAssemblyEnd(objective_function_gradient);
1206 PetscBool gradient_fd_check = PETSC_FALSE;
1208 &gradient_fd_check, PETSC_NULLPTR);
1209 if (gradient_fd_check) {
1211 PetscInt nb_modes = 5;
1213 "-gradient_nb_modes", &nb_modes, PETSC_NULLPTR);
1219 auto fe_rule = [](int, int,
int p_data) {
return 2 * p_data + p_data - 1; };
1220 auto get_objective_fe = [&](
auto glob_objective_ptr,
auto fe_rule) {
1221 auto fe_obj_fe = boost::make_shared<DomainEle>(
mField);
1222 fe_obj_fe->getRuleHook = fe_rule;
1223 auto &pip = fe_obj_fe->getOpPtrVector();
1225 auto jac_ptr = boost::make_shared<MatrixDouble>();
1226 auto u_ptr = boost::make_shared<MatrixDouble>();
1228 "GEOMETRY", jac_ptr));
1230 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1231 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1233 glob_objective_ptr));
1237 auto f = boost::make_shared<double>(0.);
1238 auto fe_obj = get_objective_fe(
f, fe_rule);
1243 auto evaluate_objective_terms = [&](
auto objective_fe,
auto objective_ptr,
1244 double &objective_value) {
1246 *objective_ptr = 0.0;
1249 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1251 objective_value = *objective_ptr;
1256 for (PetscInt mode = 0; mode < nb_modes; ++mode) {
1258 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Processing mode: " << mode;
1264 auto a_dof = adj_dofs.find(mode);
1265 if (a_dof != adj_dofs.end()) {
1266 auto ent = (*a_dof)->getEnt();
1267 auto dof_idx = (*a_dof)->getEntDofIdx();
1271 auto dof = dofs.find(uid);
1272 if (dof != dofs.end()) {
1273 auto org_geom_val = (*dof)->getFieldData();
1274 constexpr double eps = 1e-6;
1276 (*dof)->getFieldData() = org_geom_val +
eps;
1280 CHKERR evaluate_objective_terms(fe_obj,
f, f_plus);
1282 (*dof)->getFieldData() = org_geom_val -
eps;
1286 CHKERR evaluate_objective_terms(fe_obj,
f, f_minus);
1289 CHKERR VecGetArray(gradient_vector, &g_array);
1290 if ((*a_dof)->getHasLocalIndex()) {
1291 auto adjoint_grad = g_array[(*a_dof)->getPetscLocalDofIdx()];
1292 auto finite_diff_grad = (f_plus - f_minus) / (2 *
eps);
1293 auto err = std::abs(adjoint_grad - finite_diff_grad) /
1294 std::max(std::abs(adjoint_grad),
1295 std::abs(finite_diff_grad));
1297 <<
"Mode: " << mode <<
", Adjoint gradient: " << adjoint_grad
1298 <<
", Finite difference gradient: " << finite_diff_grad
1299 <<
", Relative error: "
1300 << std::abs(adjoint_grad - finite_diff_grad) /
1301 std::max(std::abs(adjoint_grad),
1302 std::abs(finite_diff_grad));
1303 constexpr double tol = 1e-4;
1306 "Gradient check failed for mode %d: relative error %e is "
1307 "greater than tolerance %e",
1312 CHKERR VecRestoreArray(gradient_vector, &g_array);
1314 constexpr bool restore_solution =
false;
1315 if constexpr (restore_solution) {
1316 (*dof)->getFieldData() = org_geom_val;
1338 const char param_file[] =
"param_file.petsc";
1341 auto core_log = logging::core::get();
1353 DMType dm_name =
"DMMOFEM";
1355 DMType dm_name_mg =
"DMMOFEM_MG";
1360 moab::Core mb_instance;
1361 moab::Interface &moab = mb_instance;
1379 if (Py_FinalizeEx() < 0) {
1385 const std::string block_name,
int dim) {
1391 std::regex((boost::format(
"%s(.*)") % block_name).str())
1395 for (
auto bc : bcs) {
1399 "get meshset ents");
1403 for (
auto dd = dim - 1; dd >= 0; --dd) {
1407 moab::Interface::UNION),
1427 CHKERR moab.add_entities(*out_meshset, r);
1428 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)
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
auto diff_symmetrize(FTensor::Number< DIM >)
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 py_file)
Factory function to create Python-integrated objective function interface.
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 addDomainField(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_ZERO, int verb=-1)
Add field on domain.
EntityHandle & getMeshset()
Get the MeshSet object.
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
MoFEMErrorCode addBoundaryField(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_ZERO, int verb=-1)
Add field on boundary.
MoFEMErrorCode getOptions()
get options
MoFEMErrorCode getDM(DM *dm)
Get DM.
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
BitRefLevel & getBitRefLevelMask()
Get the BitRefLevelMask.
MoFEMErrorCode addDataField(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_ZERO, int verb=-1)
Add data field.
EntityHandle & getBoundaryMeshSet()
Get the BoundaryMeshSet object.
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
const std::string getProblemName() const
Get the Problem Name.
const std::string getDomainFEName() const
Get the Domain FE Name.
BitRefLevel & getBitRefLevel()
Get the BitRefLevel.
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