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>
110 const std::string block_name,
int dim);
140 Vec objective_function_gradient,
141 Vec adjoint_vector, Vec dJ_du);
152 boost::shared_ptr<ObjectiveFunctionData>
161 char objective_function_file_name[255] =
"objective_function.py";
163 PETSC_NULLPTR, PETSC_NULLPTR,
"-objective_function",
164 objective_function_file_name, 255, PETSC_NULLPTR);
167 auto file_exists = [](std::string myfile) {
168 std::ifstream file(myfile.c_str());
174 if (!file_exists(objective_function_file_name)) {
175 MOFEM_LOG(
"WORLD", Sev::error) <<
"Objective function file NOT found: "
176 << objective_function_file_name;
183 char sensitivity_method_name[32] =
"adjoint";
185 "-sensitivity_method", sensitivity_method_name,
186 sizeof(sensitivity_method_name), PETSC_NULLPTR);
187 std::string sensitivity_method = sensitivity_method_name;
188 std::transform(sensitivity_method.begin(), sensitivity_method.end(),
189 sensitivity_method.begin(),
190 [](
unsigned char c) { return std::tolower(c); });
191 if (sensitivity_method ==
"direct") {
193 }
else if (sensitivity_method ==
"adjoint") {
197 "Unknown -sensitivity_method. Use 'direct' or 'adjoint'.");
200 <<
"Sensitivity method: " << sensitivity_method;
224 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Objective function value: " <<
f;
231 INSERT_VALUES, SCATTER_FORWARD);
238 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Topology optimization completed";
291 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
292 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
293 PetscInt choice_base_value = AINSWORTH;
295 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
297 switch (choice_base_value) {
301 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
306 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
340 auto project_ho_geometry = [&]() {
344 CHKERR project_ho_geometry();
360 auto create_adjoint_dm = [&]() {
363 constexpr int adjoint_field_order = 1;
365 auto add_field = [&]() {
370 for (
auto tt = MBEDGE;
371 tt <= moab::CN::TypeDimensionMap[
SPACE_DIM - 1].second; ++tt)
373 "ADJOINT_FIELD", adjoint_field_order);
380 auto add_adjoint_fe_impl = [&]() {
419 auto set_adjoint_dm_imp = [&]() {
425 CHKERR DMSetFromOptions(adjoint_dm);
432 CHKERR DMSetUp(adjoint_dm);
464 "REMOVE_ALL",
"U", 0, 3);
468 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_X",
469 "ADJOINT_FIELD", 0, 0);
470 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_Y",
471 "ADJOINT_FIELD", 1, 1);
472 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_Z",
473 "ADJOINT_FIELD", 2, 2);
474 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"REMOVE_ALL",
475 "ADJOINT_FIELD", 0, 3);
476 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_X",
"ADJOINT_FIELD",
478 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_Y",
"ADJOINT_FIELD",
480 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_Z",
"ADJOINT_FIELD",
482 CHKERR bc_mng->removeBlockDOFsOnEntities(
"ADJOINT",
"FIX_ALL",
483 "ADJOINT_FIELD", 0, 3);
505 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
506 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
510 pip->getOpDomainLhsPipeline(), {H1},
"GEOMETRY");
512 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
514 pip->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
516 pip->getOpBoundaryLhsPipeline(), {NOSPACE},
"GEOMETRY");
520 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
521 mField, pip->getOpDomainLhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
525 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
526 mField, pip->getOpDomainRhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
530 pip->getOpDomainRhsPipeline(),
mField,
"U", Sev::inform);
536 pip->getOpBoundaryRhsPipeline(),
mField,
"U", -1, Sev::inform);
539 pip->getOpBoundaryLhsPipeline(),
mField,
"U", Sev::noisy);
555 auto set_essential_bc = [&]() {
560 auto pre_proc_rhs = boost::make_shared<FEMethod>();
561 auto post_proc_rhs = boost::make_shared<FEMethod>();
562 auto post_proc_lhs = boost::make_shared<FEMethod>();
564 auto get_pre_proc_hook = [&]() {
568 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
570 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
574 post_proc_rhs, 1.)();
578 auto get_post_proc_hook_lhs = [
this, post_proc_lhs]() {
582 post_proc_lhs, 1.)();
586 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
587 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
589 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
590 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
591 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
595 auto setup_and_solve = [&](
auto solver) {
597 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
598 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp";
600 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp <= Done";
601 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve";
602 CHKERR KSPSolve(solver, f, d);
603 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve <= Done";
610 CHKERR set_essential_bc();
613 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
614 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
617 auto evaluate_field_at_the_point = [&]() {
621 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
624 field_eval_coords.data(), &coords_dim,
629 auto vector_field_ptr = boost::make_shared<MatrixDouble>();
630 auto field_eval_data =
636 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
637 auto no_rule = [](
int,
int,
int) {
return -1; };
638 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
639 field_eval_fe_ptr->getRuleHook = no_rule;
641 field_eval_fe_ptr->getOpPtrVector().push_back(
645 ->evalFEAtThePoint<SPACE_DIM>(
651 if (vector_field_ptr->size1()) {
652 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vector_field_ptr);
655 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1);
658 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1)
659 <<
" U_Z: " << t_disp(2);
667 CHKERR evaluate_field_at_the_point();
680 std::vector<std::pair<std::string, SmartPetscObj<Vec>>> additional_vecs;
681 if (gradient_vector) {
682 additional_vecs.emplace_back(
"GRADIENT", gradient_vector);
684 if (adjoint_vector) {
685 additional_vecs.emplace_back(
"ADJOINT", adjoint_vector);
688 additional_vecs.emplace_back(
"dJ_dU", dJ_du);
693 "out_elastic_" + std::to_string(iter) +
".h5m", additional_vecs,
704 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
705 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
706 boost::shared_ptr<MatrixDouble> u_ptr)
718 auto nb_gauss_pts = getGaussPts().size2();
720 auto objective_dstress =
721 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
722 auto objective_dstrain =
723 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
725 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
727 auto evaluate_python = [&]() {
729 auto &coords = OP::getCoordsAtGaussPts();
740 auto vol = OP::getMeasure();
741 auto t_w = OP::getFTensor0IntegrationWeight();
744 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
749 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
751 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
752 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
754 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
755 const double alpha = t_w * vol;
757 t_adjoint_stress(
i,
j) =
758 t_D(
i,
j,
k,
l) * t_obj_dstress(
k,
l) + t_obj_dstrain(
i,
j);
760 auto t_nf = OP::template getNf<SPACE_DIM>();
763 t_nf(
j) += alpha * t_row_grad(
i) * t_adjoint_stress(
i,
j);
764 t_nf(
j) += alpha * t_row_base * t_obj_du(
j);
787 boost::shared_ptr<ObjectiveFunctionData>
pythonPtr;
788 boost::shared_ptr<HookeOps::CommonData>
commPtr;
789 boost::shared_ptr<MatrixDouble>
uPtr;
795 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
796 boost::shared_ptr<MatrixDouble> jac_ptr,
797 boost::shared_ptr<MatrixDouble> u_ptr,
798 boost::shared_ptr<double> glob_objective_ptr)
813 getGaussPts().size2();
815 auto objective_ptr = boost::make_shared<MatrixDouble>(
818 auto evaluate_python = [&]() {
820 auto &coords = OP::getCoordsAtGaussPts();
827 auto vol = OP::getMeasure();
828 auto t_w = getFTensor0IntegrationWeight();
829 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
831 auto alpha = t_w * vol;
832 (*globObjectivePtr) += alpha * t_obj;
848 boost::shared_ptr<HookeOps::CommonData>
commPtr;
850 boost::shared_ptr<MatrixDouble>
uPtr;
858 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
859 boost::shared_ptr<MatrixDouble> jac_ptr,
860 boost::shared_ptr<MatrixDouble> u_ptr,
861 boost::shared_ptr<MatrixDouble> grad_lambda_u_ptr,
862 boost::shared_ptr<double> glob_objective_ptr)
863 :
OP(
"ADJOINT_FIELD",
"ADJOINT_FIELD",
OP::OPROW),
pythonPtr(python_ptr),
877 const auto nb_gauss_pts =
878 getGaussPts().size2();
879 const auto nb_dofs = data.
getIndices().size();
894 auto t_diff_symm = FTensor::diff_symmetrize<double>();
897 auto objective_ptr = boost::make_shared<MatrixDouble>(
899 auto objective_dstress = boost::make_shared<MatrixDouble>(
902 auto objective_dstrain = boost::make_shared<MatrixDouble>(
907 auto evaluate_python = [&]() {
909 auto &coords = OP::getCoordsAtGaussPts();
921 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
commPtr->matGradPtr));
923 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
924 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
jacPtr));
925 auto t_grad_lambda_u =
930 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
932 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
934 auto vol = OP::getMeasure();
935 auto t_w = getFTensor0IntegrationWeight();
937 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
938 auto alpha = t_w * vol;
939 (*globObjectivePtr) += alpha * t_obj;
947 t_diff_inv_jac(
i,
j,
I,
J) =
948 -t_inv_jac(
i,
I) * t_inv_jac(
J,
j);
951 t_diff_grad(
i,
j,
I,
J) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j,
I,
J);
954 t_d_strain(
i,
j,
I,
J) =
955 t_diff_symm(
i,
j,
k,
l) * t_diff_grad(
k,
l,
I,
J);
957 auto t_local_grad_vector = OP::template getNf<SPACE_DIM>();
962 t_coef(
I) = (t_inv_jac(
J,
I) * t_base_diff(
J)) * t_det;
964 t_local_grad_vector(
I) +=
967 ((t_obj_dstress(
k,
l) * t_D(
k,
l,
i,
j)) +
968 t_obj_dstrain(
i,
j)) *
969 (t_d_strain(
i,
j,
I,
J) * t_base_diff(
J))
977 t_local_grad_vector(
I) -=
978 alpha * (t_grad_lambda_u(
i,
j) * t_D(
i,
j,
k,
l)) *
979 (t_d_strain(
k,
l,
I,
J) * t_base_diff(
J));
981 ++t_local_grad_vector;
984 for (; bb < nb_base_funcs; ++bb) {
1001 CHKERR evaluate_python();
1007 boost::shared_ptr<ObjectiveFunctionData>
pythonPtr;
1008 boost::shared_ptr<HookeOps::CommonData>
commPtr;
1009 boost::shared_ptr<MatrixDouble>
jacPtr;
1010 boost::shared_ptr<MatrixDouble>
uPtr;
1017 Vec objective_function_gradient,
1024 auto get_essential_fe = [
this]() {
1025 auto post_proc_rhs = boost::make_shared<FEMethod>();
1026 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1029 post_proc_rhs, 0)();
1032 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1033 return post_proc_rhs;
1036 auto get_objective_fe = [&](
auto lambda_vec,
auto glob_objective_ptr,
1038 auto fe_obj = boost::make_shared<DomainEle>(
mField);
1039 fe_obj->getRuleHook = fe_rule;
1040 auto &pip = fe_obj->getOpPtrVector();
1043 auto jac_ptr = boost::make_shared<MatrixDouble>();
1044 auto u_ptr = boost::make_shared<MatrixDouble>();
1045 auto grad_lambda_ptr = boost::make_shared<MatrixDouble>();
1048 "GEOMETRY", jac_ptr));
1052 "U", grad_lambda_ptr, lambda_smart_vec));
1054 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1055 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1058 glob_objective_ptr));
1062 auto evaluate_objective_terms =
1063 [&](
auto objective_fe,
auto objective_ptr) {
1065 *objective_ptr = 0.0;
1066 CHKERR VecZeroEntries(objective_function_gradient);
1067 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1068 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1069 objective_fe->f = objective_function_gradient;
1072 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1074 CHKERR VecAssemblyBegin(objective_function_gradient);
1075 CHKERR VecAssemblyEnd(objective_function_gradient);
1076 CHKERR VecGhostUpdateBegin(objective_function_gradient, ADD_VALUES,
1078 CHKERR VecGhostUpdateEnd(objective_function_gradient, ADD_VALUES,
1083 auto calculate_variance_of_objective_function_dJ_du = [&]() {
1085 auto fe = boost::make_shared<DomainEle>(
mField);
1086 fe->getRuleHook = [](int, int,
int p_data) {
1087 return 2 * p_data + p_data - 1;
1089 auto &pip = fe->getOpPtrVector();
1091 auto u_ptr = boost::make_shared<MatrixDouble>();
1093 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1094 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1096 CHKERR VecZeroEntries(dJ_du);
1099 CHKERR VecAssemblyBegin(dJ_du);
1100 CHKERR VecAssemblyEnd(dJ_du);
1101 auto post_proc_rhs = get_essential_fe();
1102 post_proc_rhs->f = dJ_du;
1104 post_proc_rhs.get());
1108 auto calculate_adjoint_lambda = [&]() {
1111 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Solving for adjoint variable lambda";
1114 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1115 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1119 auto fe_rule = [](int, int,
int p_data) {
return 2 * p_data + p_data - 1; };
1120 auto objective_ptr_value = boost::make_shared<double>(0.0);
1121 auto objective_fe = get_objective_fe(
lambda, objective_ptr_value, fe_rule);
1123 auto adjoint = [&]() {
1126 CHKERR calculate_variance_of_objective_function_dJ_du();
1127 CHKERR calculate_adjoint_lambda();
1128 CHKERR evaluate_objective_terms(objective_fe, objective_ptr_value);
1129 *objective_function_value = *objective_ptr_value;
1132 <<
"Objective function: " << *objective_function_value;
1134 CHKERR VecAssemblyBegin(objective_function_gradient);
1135 CHKERR VecAssemblyEnd(objective_function_gradient);
1136 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1137 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
1145 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Adjoint Sensitivity...";
1151 "Wrong sensitivity type selected");
1154 CHKERR VecAssemblyBegin(objective_function_gradient);
1155 CHKERR VecAssemblyEnd(objective_function_gradient);
1169 PetscInt nb_modes = 5;
1171 "-gradient_nb_modes", &nb_modes, PETSC_NULLPTR);
1172 PetscReal
eps = 1e-6;
1174 &
eps, PETSC_NULLPTR);
1180 auto get_objective_fe = [&](
auto glob_objective_ptr) {
1181 auto fe_obj_fe = boost::make_shared<DomainEle>(
mField);
1182 fe_obj_fe->getRuleHook = [](int, int,
int p_data) {
1183 return 2 * p_data + p_data - 1;
1185 auto &pip = fe_obj_fe->getOpPtrVector();
1187 auto jac_ptr = boost::make_shared<MatrixDouble>();
1188 auto u_ptr = boost::make_shared<MatrixDouble>();
1190 "GEOMETRY", jac_ptr));
1192 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1193 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1195 glob_objective_ptr));
1199 auto f = boost::make_shared<double>(0.);
1200 auto fe_obj = get_objective_fe(f);
1205 auto evaluate_objective = [&](
double &objective_value) {
1209 MPI_Allreduce(MPI_IN_PLACE, f.get(), 1, MPI_DOUBLE, MPI_SUM,
1211 objective_value = *f;
1223 auto get_geometry_dof = [&](PetscInt mode) ->
const DofEntity * {
1224 auto a_dof = adj_dofs.find(mode);
1225 if (a_dof == adj_dofs.end())
1228 (*a_dof)->getEntDofIdx(),
1230 (*a_dof)->getEnt()));
1231 auto dof = dofs.find(uid);
1232 return dof != dofs.end() ? dof->get() :
nullptr;
1235 auto solve_and_evaluate = [&](
const DofEntity *dof,
double geom_val,
1236 double &objective_value) {
1242 CHKERR evaluate_objective(objective_value);
1246 for (PetscInt mode = 0; mode < nb_modes; ++mode) {
1247 auto dof = get_geometry_dof(mode);
1248 const double org_geom_val = dof ? dof->
getFieldData() : 0.;
1250 double f_plus, f_minus;
1251 CHKERR solve_and_evaluate(dof, org_geom_val +
eps, f_plus);
1252 CHKERR solve_and_evaluate(dof, org_geom_val -
eps, f_minus);
1255 const double finite_diff_grad = (f_plus - f_minus) / (2 *
eps);
1259 double owner_data[2] = {0., 0.};
1260 auto a_dof = adj_dofs.find(mode);
1261 if (a_dof != adj_dofs.end() && (*a_dof)->getHasLocalIndex()) {
1262 const double *g_array;
1263 CHKERR VecGetArrayRead(gradient_vector, &g_array);
1264 owner_data[0] = g_array[(*a_dof)->getPetscLocalDofIdx()];
1266 CHKERR VecRestoreArrayRead(gradient_vector, &g_array);
1268 CHKERR MPI_Allreduce(MPI_IN_PLACE, owner_data, 2, MPI_DOUBLE, MPI_SUM,
1270 if (owner_data[1] == 0.)
1272 "Adjoint DOF for mode %d not found on any rank", mode);
1273 const double adjoint_grad = owner_data[0] / owner_data[1];
1276 <<
"Mode: " << mode <<
", Adjoint gradient: " << adjoint_grad
1277 <<
", Finite difference gradient: " << finite_diff_grad;
1279 "gradient mode " + std::to_string(mode), adjoint_grad,
1280 finite_diff_grad, {0., 1e-4});
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);
Calculate traction for linear problem.
Implementation of elastic spring bc.
Natural boundary condition applying pressure from fluid.
Implementation of Hookes operator Hookes for linear elastic problems in MoFEM.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
Implementation of natural boundary conditions.
Boundary conditions in domain, i.e. body forces.
Interface for Python-based objective function evaluation in topology optimization.
#define FTENSOR_INDEX(DIM, I)
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_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]
PostProcEleByDim< SPACE_DIM >::SideEle SideEle
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 PetscOptionsGetReal(PetscOptions *, const char pre[], const char name[], PetscReal *dval, 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)
#define EXECUTABLE_DIMENSION
PetscBool do_eval_field
Evaluate field.
ElementsAndOps< SPACE_DIM >::SideEle SideEle
constexpr auto field_name
static constexpr int approx_order
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.
MoFEMErrorCode checkResults()
[Postprocess results]
SmartPetscObj< KSP > kspElastic
Linear solver for elastic problem.
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.
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.
keeps information about DOF on the entity
FieldData & getFieldData() const
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.
int nbRows
number of dofs on rows
int nbRowBaseFunctions
number or row base functions
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
virtual MoFEMErrorCode addTestCommandLine(const std::string &prefix, int number, const std::string &name, TestHook hook)=0
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)
Class dedicated to integrate operator.
boost::shared_ptr< MatrixDouble > uPtr
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle