14#include <boost/python.hpp>
15#include <boost/python/def.hpp>
16#include <boost/python/numpy.hpp>
17namespace bp = boost::python;
18namespace np = boost::python::numpy;
35 IntegrationType::GAUSS;
59 BoundaryEle::UserDataOperator;
100template <
int SPACE_DIM, IntegrationType I,
typename OpBase>
104template <
int SPACE_DIM, IntegrationType I,
typename OpBase>
111#include <ElasticSpring.hpp>
112#include <FluidLevel.hpp>
113#include <CalculateTraction.hpp>
114#include <NaturalDomainBC.hpp>
115#include <NaturalBoundaryBC.hpp>
116#include <HookeOps.hpp>
123 const std::string block_name,
int dim);
159 Vec objective_function_gradient,
169 boost::shared_ptr<ObjectiveFunctionData>
173 std::vector<SmartPetscObj<Vec>>
175 std::vector<std::array<double, 3>>
177 std::vector<std::array<double, 6>>
206 char objective_function_file_name[255] =
"objective_function.py";
208 PETSC_NULLPTR, PETSC_NULLPTR,
"-objective_function",
209 objective_function_file_name, 255, PETSC_NULLPTR);
212 auto file_exists = [](std::string myfile) {
213 std::ifstream file(myfile.c_str());
219 if (!file_exists(objective_function_file_name)) {
220 MOFEM_LOG(
"WORLD", Sev::error) <<
"Objective function file NOT found: "
221 << objective_function_file_name;
228 char sensitivity_method_name[32] =
"adjoint";
230 "-sensitivity_method", sensitivity_method_name,
231 sizeof(sensitivity_method_name), PETSC_NULLPTR);
232 std::string sensitivity_method = sensitivity_method_name;
233 std::transform(sensitivity_method.begin(), sensitivity_method.end(),
234 sensitivity_method.begin(),
235 [](
unsigned char c) { return std::tolower(c); });
236 if (sensitivity_method ==
"direct") {
238 }
else if (sensitivity_method ==
"adjoint") {
242 "Unknown -sensitivity_method. Use 'direct' or 'adjoint'.");
245 <<
"Sensitivity method: " << sensitivity_method;
263 auto create_vec_modes = [&](
auto block_name) {
268 std::regex((boost::format(
"%s(.*)") % block_name).str())
272 int nb_total_modes = 0;
273 for (
auto &bc : bcs) {
274 auto id = bc->getMeshsetId();
277 nb_total_modes += nb_modes;
281 <<
"Total number of modes to apply: " << nb_total_modes;
288 auto get_modes_bounding_boxes = [&](
auto block_name) {
293 std::regex((boost::format(
"%s(.*)") % block_name).str())
297 for (
auto &bc : bcs) {
298 auto meshset = bc->getMeshset();
303 std::vector<double> x(verts.size());
304 std::vector<double> y(verts.size());
305 std::vector<double> z(verts.size());
307 std::array<double, 3> centroid = {0, 0, 0};
308 for (
int i = 0;
i != verts.size(); ++
i) {
313 MPI_Allreduce(MPI_IN_PLACE, centroid.data(), 3, MPI_DOUBLE, MPI_SUM,
315 int nb_vertex = verts.size();
316 MPI_Allreduce(MPI_IN_PLACE, &nb_vertex, 1, MPI_INT, MPI_SUM,
319 centroid[0] /= nb_vertex;
320 centroid[1] /= nb_vertex;
321 centroid[2] /= nb_vertex;
323 std::array<double, 6> bbox = {centroid[0], centroid[1], centroid[2],
324 centroid[0], centroid[1], centroid[2]};
325 for (
int i = 0;
i != verts.size(); ++
i) {
326 bbox[0] = std::min(bbox[0], x[
i]);
327 bbox[1] = std::min(bbox[1], y[
i]);
328 bbox[2] = std::min(bbox[2], z[
i]);
329 bbox[3] = std::max(bbox[3], x[
i]);
330 bbox[4] = std::max(bbox[4], y[
i]);
331 bbox[5] = std::max(bbox[5], z[
i]);
333 MPI_Allreduce(MPI_IN_PLACE, &bbox[0], 3, MPI_DOUBLE, MPI_MIN,
335 MPI_Allreduce(MPI_IN_PLACE, &bbox[3], 3, MPI_DOUBLE, MPI_MAX,
339 <<
"Block: " << bc->getName() <<
" centroid: " << centroid[0] <<
" "
340 << centroid[1] <<
" " << centroid[2];
342 <<
"Block: " << bc->getName() <<
" bbox: " << bbox[0] <<
" "
343 << bbox[1] <<
" " << bbox[2] <<
" " << bbox[3] <<
" " << bbox[4]
353 auto eval_objective_and_gradient = [](Tao tao,
Vec x, PetscReal *
f,
Vec g,
354 void *ctx) -> PetscErrorCode {
359 CHKERR TaoGetIterationNumber(tao, &iter);
361 auto set_geometry = [&](
Vec x) {
366 CHKERR VecScatterCreateToAll(x, &ctx, &x_local);
368 CHKERR VecScatterBegin(ctx, x, x_local, INSERT_VALUES, SCATTER_FORWARD);
369 CHKERR VecScatterEnd(ctx, x, x_local, INSERT_VALUES, SCATTER_FORWARD);
371 CHKERR VecScatterDestroy(&ctx);
374 CHKERR VecCopy(ex_ptr->initialGeometry, current_geometry);
376 CHKERR VecGetArrayRead(x_local, &
a);
377 const double *coeff =
a;
378 for (
auto &mode_vec : ex_ptr->
modeVecs) {
380 <<
"Adding mode with coeff: " << *coeff;
381 CHKERR VecAXPY(current_geometry, (*coeff), mode_vec);
384 CHKERR VecRestoreArrayRead(x_local, &
a);
385 CHKERR VecGhostUpdateBegin(current_geometry, INSERT_VALUES,
387 CHKERR VecGhostUpdateEnd(current_geometry, INSERT_VALUES,
390 ->setOtherLocalGhostVector(
"ADJOINT",
"ADJOINT_FIELD",
"GEOMETRY",
392 INSERT_VALUES, SCATTER_REVERSE);
394 CHKERR VecDestroy(&x_local);
399 CHKERR KSPReset(ex_ptr->kspElastic);
400 CHKERR ex_ptr->solveElastic();
403 CHKERR ex_ptr->calculateGradient(
f,
g, adjoint_vector);
404 CHKERR ex_ptr->postprocessElastic(iter, adjoint_vector);
410 CHKERR create_vec_modes(
"OPTIMISE");
411 CHKERR get_modes_bounding_boxes(
"OPTIMISE");
424 CHKERR TaoSetType(tao, TAOLMVM);
436 INSERT_VALUES, SCATTER_FORWARD);
465 CHKERR TaoSetSolution(tao, x0);
466 CHKERR TaoSetFromOptions(tao);
470 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Topology optimization completed";
523 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
524 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
525 PetscInt choice_base_value = AINSWORTH;
527 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
529 switch (choice_base_value) {
533 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
538 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
572 auto project_ho_geometry = [&]() {
576 CHKERR project_ho_geometry();
607 auto create_adjoint_dm = [&]() {
610 auto add_field = [&]() {
615 for (
auto tt = MBEDGE; tt <= moab::CN::TypeDimensionMap[
SPACE_DIM].second;
625 auto add_adjoint_fe_impl = [&]() {
650 auto block_name =
"OPTIMISE";
654 std::regex((boost::format(
"%s(.*)") % block_name).str())
658 for (
auto bc : bcs) {
660 bc->getMeshset(),
SPACE_DIM - 1,
"ADJOINT_BOUNDARY_FE");
666 simple->getBitRefLevelMask());
671 auto set_adjoint_dm_imp = [&]() {
675 simple->getBitRefLevelMask());
677 CHKERR DMSetFromOptions(adjoint_dm);
684 CHKERR DMSetUp(adjoint_dm);
709 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_X",
711 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Y",
713 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Z",
715 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
716 "REMOVE_ALL",
"U", 0, 3);
718 simple->getProblemName(),
"U");
734 boost::make_shared<Range>(opt_ents));
736 boost::make_shared<Range>(opt_ents));
737 CHKERR DMSetUp(subset_dm_bdy);
745 CHKERR DMSetUp(subset_dm_domain);
748 auto remove_dofs = [&]() {
751 std::array<Range, 3> remove_dim_ents;
759 for (
int d = 0; d != 3; ++d) {
761 <<
"Removing topology modes on block OPT_REMOVE_" << (char)(
'X' + d)
762 <<
" with " << remove_dim_ents[d].size() <<
" entities";
770 CHKERR skin.find_skin(0, body_ents,
false, boundary_ents);
771 for (
int d = 0; d != 3; ++d) {
772 boundary_ents = subtract(boundary_ents, remove_dim_ents[d]);
774 ParallelComm *pcomm =
776 CHKERR pcomm->filter_pstatus(boundary_ents,
777 PSTATUS_SHARED | PSTATUS_MULTISHARED,
778 PSTATUS_NOT, -1,
nullptr);
779 for (
auto d =
SPACE_DIM - 2; d >= 0; --d) {
783 moab::Interface::UNION);
784 boundary_ents.merge(ents);
788 boundary_ents.merge(verts);
793 boundary_ents.merge(opt_ents);
795 "SUBSET_DOMAIN",
"ADJOINT_FIELD", boundary_ents);
796 for (
int d = 0; d != 3; ++d) {
798 "SUBSET_DOMAIN",
"ADJOINT_FIELD", remove_dim_ents[d], d, d);
813 auto get_lhs_fe = [&]() {
814 auto fe_lhs = boost::make_shared<BoundaryEle>(
mField);
815 fe_lhs->getRuleHook = [](int, int,
int p_data) {
816 return 2 * p_data + p_data - 1;
818 auto &pip = fe_lhs->getOpPtrVector();
823 pip.push_back(
new OpMass(
"ADJOINT_FIELD",
"ADJOINT_FIELD",
824 [](
double,
double,
double) {
return 1.; }));
828 auto get_rhs_fe = [&]() {
829 auto fe_rhs = boost::make_shared<BoundaryEle>(
mField);
830 fe_rhs->getRuleHook = [](int, int,
int p_data) {
831 return 2 * p_data + p_data - 1;
833 auto &pip = fe_rhs->getOpPtrVector();
840 auto block_name =
"OPTIMISE";
844 std::regex((boost::format(
"%s(.*)") % block_name).str())
853 struct OpMode :
public OP {
854 OpMode(
const std::string name,
855 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
int id,
857 std::vector<std::array<double, 3>> mode_centroids,
858 std::vector<std::array<double, 6>> mode_bboxes,
int block_counter,
859 int mode_counter, boost::shared_ptr<Range> range =
nullptr)
860 :
OP(name, name, OP::OPROW, range), pythonPtr(python_ptr), iD(
id),
861 modeVecs(mode_vecs), modeCentroids(mode_centroids),
862 modeBboxes(mode_bboxes), blockCounter(block_counter),
863 modeCounter(mode_counter) {}
869 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
877 auto nb_base_functions = data.
getN().size2();
880 CHKERR pythonPtr->blockModes(iD, OP::getCoordsAtGaussPts(),
881 modeCentroids[blockCounter],
882 modeBboxes[blockCounter], blockModes);
884 auto nb_integration_pts = getGaussPts().size2();
885 if (blockModes.size2() != 3 * nb_integration_pts) {
887 <<
"Number of modes does not match number of integration points: "
888 << blockModes.size2() <<
"!=" << 3 * nb_integration_pts;
894 int nb_modes = blockModes.size1();
895 for (
auto mode = 0; mode != nb_modes; ++mode) {
898 auto t_mode = getFTensor1FromPtr<3>(&blockModes(mode, 0));
900 const double vol = OP::getMeasure();
902 auto t_w = OP::getFTensor0IntegrationWeight();
906 for (
int gg = 0; gg != nb_integration_pts; gg++) {
909 const double alpha = t_w * vol;
911 auto t_nf = getFTensor1FromPtr<SPACE_DIM>(nf.data().data());
913 for (; rr != nb_rows /
SPACE_DIM; ++rr) {
914 t_nf(
i) += alpha * t_base * t_mode(
i);
918 for (; rr < nb_base_functions; ++rr)
923 Vec vec = modeVecs[modeCounter + mode];
925 auto *indices = data.
getIndices().data().data();
926 auto *nf_data = nf.data().data();
934 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
936 std::vector<std::array<double, 3>> modeCentroids;
937 std::vector<std::array<double, 6>> modeBboxes;
939 std::vector<SmartPetscObj<Vec>> modeVecs;
944 auto solve_bdy = [&]() {
947 auto fe_lhs = get_lhs_fe();
948 auto fe_rhs = get_rhs_fe();
949 int block_counter = 0;
950 int mode_counter = 0;
951 for (
auto &bc : bcs) {
952 auto id = bc->getMeshsetId();
956 auto range = boost::make_shared<Range>(ents);
957 auto &pip_rhs = fe_rhs->getOpPtrVector();
960 mode_counter, range));
967 mode_counter += nb_modes;
969 <<
"Setting mode block block: " << bc->getName()
970 <<
" with ID: " << bc->getMeshsetId()
971 <<
" total modes: " << mode_counter;
977 CHKERR VecGhostUpdateBegin(
v, ADD_VALUES, SCATTER_REVERSE);
978 CHKERR VecGhostUpdateEnd(
v, ADD_VALUES, SCATTER_REVERSE);
985 CHKERR MatAssemblyBegin(
M, MAT_FINAL_ASSEMBLY);
986 CHKERR MatAssemblyEnd(
M, MAT_FINAL_ASSEMBLY);
989 CHKERR KSPSetOperators(solver,
M,
M);
990 CHKERR KSPSetFromOptions(solver);
999 CHKERR VecGhostUpdateBegin(
v, INSERT_VALUES, SCATTER_FORWARD);
1000 CHKERR VecGhostUpdateEnd(
v, INSERT_VALUES, SCATTER_FORWARD);
1008 auto get_elastic_fe_lhs = [&]() {
1009 auto fe = boost::make_shared<DomainEle>(
mField);
1010 fe->getRuleHook = [](int, int,
int p_data) {
1011 return 2 * p_data + p_data - 1;
1013 auto &pip = fe->getOpPtrVector();
1016 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
1017 mField, pip,
"ADJOINT_FIELD",
"MAT_ADJOINT", Sev::noisy);
1021 auto get_elastic_fe_rhs = [&]() {
1022 auto fe = boost::make_shared<DomainEle>(
mField);
1023 fe->getRuleHook = [](int, int,
int p_data) {
1024 return 2 * p_data + p_data - 1;
1026 auto &pip = fe->getOpPtrVector();
1029 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1030 mField, pip,
"ADJOINT_FIELD",
"MAT_ADJOINT", Sev::noisy);
1034 auto adjoint_gradient_postprocess = [&](
auto mode) {
1036 auto post_proc_mesh = boost::make_shared<moab::Core>();
1037 auto post_proc_begin =
1038 boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
mField,
1040 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
1043 auto geom_vec = boost::make_shared<MatrixDouble>();
1046 boost::make_shared<PostProcEleDomain>(
mField, post_proc_mesh);
1048 post_proc_fe->getOpPtrVector(), {H1},
"GEOMETRY");
1049 post_proc_fe->getOpPtrVector().push_back(
1055 post_proc_fe->getOpPtrVector().push_back(
1059 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1063 {{
"MODE", geom_vec}},
1074 post_proc_begin->getFEMethod());
1078 post_proc_begin->getFEMethod());
1080 CHKERR post_proc_end->writeFile(
"mode_" + std::to_string(mode) +
".h5m");
1085 auto solve_domain = [&]() {
1087 auto fe_lhs = get_elastic_fe_lhs();
1088 auto fe_rhs = get_elastic_fe_rhs();
1097 CHKERR MatAssemblyBegin(
M, MAT_FINAL_ASSEMBLY);
1098 CHKERR MatAssemblyEnd(
M, MAT_FINAL_ASSEMBLY);
1100 auto solver =
createKSP(mField.get_comm());
1101 CHKERR KSPSetOperators(solver,
M,
M);
1102 CHKERR KSPSetFromOptions(solver);
1105 int mode_counter = 0;
1106 for (
auto &f : modeVecs) {
1107 CHKERR mField.getInterface<
FieldBlas>()->setField(0,
"ADJOINT_FIELD");
1115 CHKERR VecGhostUpdateBegin(
F, ADD_VALUES, SCATTER_REVERSE);
1116 CHKERR VecGhostUpdateEnd(
F, ADD_VALUES, SCATTER_REVERSE);
1118 CHKERR VecGhostUpdateBegin(
v, INSERT_VALUES, SCATTER_FORWARD);
1119 CHKERR VecGhostUpdateEnd(
v, INSERT_VALUES, SCATTER_FORWARD);
1133 for (
int i = 0;
i < modeVecs.size(); ++
i) {
1134 CHKERR adjoint_gradient_postprocess(
i);
1157 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
1158 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
1162 pip->getOpDomainLhsPipeline(), {H1},
"GEOMETRY");
1164 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
1166 pip->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
1168 pip->getOpBoundaryLhsPipeline(), {NOSPACE},
"GEOMETRY");
1172 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
1173 mField, pip->getOpDomainLhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
1177 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1178 mField, pip->getOpDomainRhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
1182 pip->getOpDomainRhsPipeline(),
mField,
"U", Sev::inform);
1188 pip->getOpBoundaryRhsPipeline(),
mField,
"U", -1, Sev::inform);
1191 pip->getOpBoundaryLhsPipeline(),
mField,
"U", Sev::noisy);
1204 CHKERR VecZeroEntries(d);
1207 auto set_essential_bc = [&]() {
1212 auto pre_proc_rhs = boost::make_shared<FEMethod>();
1213 auto post_proc_rhs = boost::make_shared<FEMethod>();
1214 auto post_proc_lhs = boost::make_shared<FEMethod>();
1216 auto get_pre_proc_hook = [&]() {
1220 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
1222 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1226 post_proc_rhs, 1.)();
1230 auto get_post_proc_hook_lhs = [
this, post_proc_lhs]() {
1234 post_proc_lhs, 1.)();
1238 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1239 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
1241 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
1242 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
1243 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
1247 auto setup_and_solve = [&](
auto solver) {
1249 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
1250 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp";
1252 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp <= Done";
1253 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve";
1254 CHKERR KSPSolve(solver,
f, d);
1255 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve <= Done";
1262 CHKERR set_essential_bc();
1265 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
1266 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
1269 auto evaluate_field_at_the_point = [&]() {
1273 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
1276 field_eval_coords.data(), &coords_dim,
1282 auto field_eval_data =
1286 ->buildTree<SPACE_DIM>(field_eval_data,
simple->getDomainFEName());
1288 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1289 auto no_rule = [](int, int, int) {
return -1; };
1290 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
1291 field_eval_fe_ptr->getRuleHook = no_rule;
1293 field_eval_fe_ptr->getOpPtrVector().push_back(
1297 ->evalFEAtThePoint<SPACE_DIM>(
1298 field_eval_coords.data(), 1e-12,
simple->getProblemName(),
1299 simple->getDomainFEName(), field_eval_data,
1306 MOFEM_LOG(
"FieldEvaluator", Sev::inform)
1307 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1);
1309 MOFEM_LOG(
"FieldEvaluator", Sev::inform)
1310 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1)
1311 <<
" U_Z: " << t_disp(2);
1319 CHKERR evaluate_field_at_the_point();
1333 "out_elastic_" + std::to_string(iter) +
".h5m",
1334 {{
"ADJOINT", adjoint_vector}}, {}, Sev::noisy);
1343template <
int SPACE_DIM>
1350 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1351 boost::shared_ptr<MatrixDouble> jac,
1352 boost::shared_ptr<MatrixDouble> diff_jac,
1353 boost::shared_ptr<VectorDouble> cof_vals)
1355 jac(jac), diffJac(diff_jac), cofVals(cof_vals) {}
1359 boost::shared_ptr<MatrixDouble>
jac;
1374 t_diff(
i,
j,
k,
l) = 0;
1375 t_diff(0, 0, 0, 0) = 1;
1376 t_diff(1, 1, 1, 1) = 1;
1378 t_diff(1, 0, 1, 0) = 0.5;
1379 t_diff(1, 0, 0, 1) = 0.5;
1381 t_diff(0, 1, 0, 1) = 0.5;
1382 t_diff(0, 1, 1, 0) = 0.5;
1384 if constexpr (DIM == 3) {
1385 t_diff(2, 2, 2, 2) = 1;
1387 t_diff(2, 0, 2, 0) = 0.5;
1388 t_diff(2, 0, 0, 2) = 0.5;
1389 t_diff(0, 2, 0, 2) = 0.5;
1390 t_diff(0, 2, 2, 0) = 0.5;
1392 t_diff(2, 1, 2, 1) = 0.5;
1393 t_diff(2, 1, 1, 2) = 0.5;
1394 t_diff(1, 2, 1, 2) = 0.5;
1395 t_diff(1, 2, 2, 1) = 0.5;
1401template <
int SPACE_DIM>
1416 const double vol = OP::getMeasure();
1418 auto t_w = OP::getFTensor0IntegrationWeight();
1420 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(jac));
1422 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(diffJac));
1429 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(commPtr->matGradPtr));
1431 auto t_cauchy_stress =
1432 getFTensor2SymmetricFromMat<SPACE_DIM>(*(commPtr->getMatCauchyStress()));
1435 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
1437 for (
int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1439 const double alpha = t_w * vol;
1447 t_diff_inv_jac(
i,
j) =
1448 -(t_inv_jac(
i,
I) * t_diff_jac(
I,
J)) * t_inv_jac(
J,
j);
1450 t_diff_grad(
i,
j) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j);
1454 t_diff_strain(
i,
j) = t_diff_symm(
i,
j,
k,
l) * t_diff_grad(
k,
l);
1458 t_diff_stress(
i,
j) = t_D(
i,
j,
k,
l) * t_diff_strain(
k,
l);
1461 auto t_nf = OP::template getNf<SPACE_DIM>();
1464 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
1467 t_diff_row_grad(
k) = t_row_grad(
j) * t_diff_inv_jac(
j,
k);
1470 t_nf(
j) += alpha * t_diff_row_grad(
i) * t_cauchy_stress(
i,
j);
1473 t_nf(
j) += (alpha * t_cof) * t_row_grad(
i) * t_cauchy_stress(
i,
j);
1476 t_nf(
j) += alpha * t_row_grad(
i) * t_diff_stress(
i,
j);
1481 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1500 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
1501 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1502 boost::shared_ptr<MatrixDouble> u_ptr)
1514 auto nb_gauss_pts = getGaussPts().size2();
1516 auto objective_dstress =
1517 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
1518 auto objective_dstrain =
1519 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
1521 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
1523 auto evaluate_python = [&]() {
1525 auto &coords = OP::getCoordsAtGaussPts();
1536 auto vol = OP::getMeasure();
1537 auto t_w = OP::getFTensor0IntegrationWeight();
1540 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
1544 auto t_obj_dstress =
1545 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
1546 auto t_obj_dstrain =
1547 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
1548 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
1550 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
1551 const double alpha = t_w * vol;
1553 t_adjoint_stress(
i,
j) =
1554 t_D(
i,
j,
k,
l) * t_obj_dstress(
k,
l) + t_obj_dstrain(
i,
j);
1556 auto t_nf = OP::template getNf<SPACE_DIM>();
1558 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
1559 t_nf(
j) += alpha * t_row_grad(
i) * t_adjoint_stress(
i,
j);
1560 t_nf(
j) += alpha * t_row_base * t_obj_du(
j);
1567 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1578 CHKERR evaluate_python();
1585 boost::shared_ptr<MatrixDouble>
uPtr;
1591 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1592 boost::shared_ptr<MatrixDouble> jac_ptr,
1593 boost::shared_ptr<MatrixDouble> diff_jac,
1594 boost::shared_ptr<VectorDouble> cof_vals,
1595 boost::shared_ptr<MatrixDouble> d_grad_ptr,
1596 boost::shared_ptr<MatrixDouble> d_u_ptr,
1597 boost::shared_ptr<MatrixDouble> u_ptr,
1598 boost::shared_ptr<double> glob_objective_ptr,
1599 boost::shared_ptr<double> glob_objective_grad_ptr)
1633 getGaussPts().size2();
1634 auto objective_ptr = boost::make_shared<MatrixDouble>(
1636 auto objective_dstress = boost::make_shared<MatrixDouble>(
1639 auto objective_dstrain = boost::make_shared<MatrixDouble>(
1643 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
1646 auto evaluate_python = [&]() {
1648 auto &coords = OP::getCoordsAtGaussPts();
1663 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
commPtr->matGradPtr));
1665 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
1666 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
jacPtr));
1667 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
diffJacPtr));
1669 auto t_d_grad = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
dGradPtr));
1672 auto t_obj_dstress =
1673 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
1674 auto t_obj_dstrain =
1675 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
1676 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
1677 auto t_d_u = getFTensor1FromMat<SPACE_DIM>(*
dUPtr);
1679 auto vol = OP::getMeasure();
1680 auto t_w = getFTensor0IntegrationWeight();
1681 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
1688 t_diff_inv_jac(
i,
j) =
1689 -(t_inv_jac(
i,
I) * t_diff_jac(
I,
J)) * t_inv_jac(
J,
j);
1691 t_diff_grad(
i,
j) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j);
1694 t_d_strain(
i,
j) = t_diff_symm(
i,
j,
k,
l) * (
1704 auto alpha = t_w * vol;
1706 (*globObjectivePtr) += alpha * t_obj;
1707 (*globObjectiveGradPtr) +=
1711 t_obj_dstress(
i,
j) * (t_D(
i,
j,
k,
l) * t_d_strain(
k,
l))
1715 t_obj_dstrain(
i,
j) * t_d_strain(
i,
j)
1719 t_obj_du(
i) * t_d_u(
i)
1744 CHKERR evaluate_python();
1757 boost::shared_ptr<MatrixDouble>
uPtr;
1764 Vec objective_function_gradient,
1765 Vec adjoint_vector) {
1772 auto get_essential_fe = [
this]() {
1773 auto post_proc_rhs = boost::make_shared<FEMethod>();
1774 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1778 post_proc_rhs, 0)();
1781 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1782 return post_proc_rhs;
1785 auto get_fd_direvative_fe = [&]() {
1786 auto fe = boost::make_shared<DomainEle>(
mField);
1787 fe->getRuleHook = [](int, int,
int p_data) {
1788 return 2 * p_data + p_data - 1;
1790 auto &pip = fe->getOpPtrVector();
1793 HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1794 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1799 auto calulate_fd_residual = [&](
auto eps,
auto diff_vec,
auto fd_vec) {
1802 constexpr bool debug =
false;
1808 auto norm2_field = [&](
const double val) {
1813 MPI_Allreduce(MPI_IN_PLACE, &nrm2, 1, MPI_DOUBLE, MPI_SUM,
1815 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Geometry norm: " << sqrt(nrm2);
1819 if constexpr (
debug)
1825 initial_current_geometry, INSERT_VALUES, SCATTER_FORWARD);
1826 CHKERR VecAssemblyBegin(initial_current_geometry);
1827 CHKERR VecAssemblyEnd(initial_current_geometry);
1829 if constexpr (
debug)
1832 auto perturb_geometry = [&](
auto eps,
auto diff_vec) {
1835 CHKERR VecCopy(initial_current_geometry, current_geometry);
1836 CHKERR VecAXPY(current_geometry,
eps, diff_vec);
1839 current_geometry, INSERT_VALUES, SCATTER_REVERSE);
1843 auto fe = get_fd_direvative_fe();
1846 auto calc_impl = [&](
auto f,
auto eps) {
1852 simple->getDomainFEName(), fe);
1855 CHKERR VecGhostUpdateBegin(
f, ADD_VALUES, SCATTER_REVERSE);
1856 CHKERR VecGhostUpdateEnd(
f, ADD_VALUES, SCATTER_REVERSE);
1857 auto post_proc_rhs = get_essential_fe();
1858 post_proc_rhs->f =
f;
1860 post_proc_rhs.get());
1865 CHKERR VecWAXPY(fd_vec, -1.0, fm, fp);
1866 CHKERR VecScale(fd_vec, 1.0 / (2.0 *
eps));
1870 initial_current_geometry, INSERT_VALUES, SCATTER_REVERSE);
1872 if constexpr (
debug)
1878 auto get_direvative_fe = [&](
auto diff_vec) {
1879 auto fe_adjoint = boost::make_shared<DomainEle>(
mField);
1880 fe_adjoint->getRuleHook = [](int, int,
int p_data) {
1881 return 2 * p_data + p_data - 1;
1883 auto &pip = fe_adjoint->getOpPtrVector();
1885 auto jac_ptr = boost::make_shared<MatrixDouble>();
1886 auto det_ptr = boost::make_shared<VectorDouble>();
1887 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1888 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
1889 auto cof_ptr = boost::make_shared<VectorDouble>();
1897 "GEOMETRY", jac_ptr));
1899 "U", diff_jac_ptr, diff_vec));
1901 pip.push_back(
new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
1904 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1905 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1907 "U", common_ptr, jac_ptr, diff_jac_ptr, cof_ptr));
1912 auto get_objective_fe = [&](
auto diff_vec,
auto grad_vec,
1913 auto glob_objective_ptr,
1914 auto glob_objective_grad_ptr) {
1915 auto fe_adjoint = boost::make_shared<DomainEle>(
mField);
1916 fe_adjoint->getRuleHook = [](int, int,
int p_data) {
1917 return 2 * p_data + p_data - 1;
1919 auto &pip = fe_adjoint->getOpPtrVector();
1922 auto jac_ptr = boost::make_shared<MatrixDouble>();
1923 auto det_ptr = boost::make_shared<VectorDouble>();
1924 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1925 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
1926 auto cof_ptr = boost::make_shared<VectorDouble>();
1927 auto d_grad_ptr = boost::make_shared<MatrixDouble>();
1928 auto d_u_ptr = boost::make_shared<MatrixDouble>();
1929 auto u_ptr = boost::make_shared<MatrixDouble>();
1934 "GEOMETRY", jac_ptr));
1939 pip.push_back(
new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
1941 "U", d_grad_ptr, grad_vec));
1946 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1947 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1949 pythonPtr, common_ptr, jac_ptr, diff_jac_ptr, cof_ptr, d_grad_ptr,
1950 d_u_ptr, u_ptr, glob_objective_ptr, glob_objective_grad_ptr));
1955 auto dm =
simple->getDM();
1961 CHKERR VecZeroEntries(zero_diff_vec);
1962 CHKERR VecZeroEntries(zero_state_sensitivity);
1963 CHKERR VecGhostUpdateBegin(zero_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1964 CHKERR VecGhostUpdateEnd(zero_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1965 CHKERR VecGhostUpdateBegin(zero_state_sensitivity, INSERT_VALUES,
1967 CHKERR VecGhostUpdateEnd(zero_state_sensitivity, INSERT_VALUES,
1970 auto adjoint_fe = get_direvative_fe(dm_diff_vec);
1971 auto objective_ptr_direct = boost::make_shared<double>(0.0);
1972 auto objective_grad_ptr_direct = boost::make_shared<double>(0.0);
1973 auto objective_fe_direct = get_objective_fe(
1974 dm_diff_vec, d, objective_ptr_direct, objective_grad_ptr_direct);
1975 auto objective_ptr_explicit = boost::make_shared<double>(0.0);
1976 auto objective_grad_ptr_explicit = boost::make_shared<double>(0.0);
1977 auto objective_fe_explicit =
1978 get_objective_fe(dm_diff_vec, zero_state_sensitivity,
1979 objective_ptr_explicit, objective_grad_ptr_explicit);
1980 auto objective_ptr_value = boost::make_shared<double>(0.0);
1981 auto objective_grad_ptr_value = boost::make_shared<double>(0.0);
1982 auto objective_fe_value =
1983 get_objective_fe(zero_diff_vec, zero_state_sensitivity,
1984 objective_ptr_value, objective_grad_ptr_value);
1986 auto set_variance_of_geometry =
1987 [&](
auto mode,
auto mod_vec) {
1995 dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1996 CHKERR VecGhostUpdateBegin(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1997 CHKERR VecGhostUpdateEnd(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
2001 auto calculate_variance_internal_forces = [&](
auto mode,
auto mod_vec) {
2004 CHKERR VecGhostUpdateBegin(
f, INSERT_VALUES, SCATTER_FORWARD);
2005 CHKERR VecGhostUpdateEnd(
f, INSERT_VALUES, SCATTER_FORWARD);
2010 CHKERR VecGhostUpdateBegin(
f, ADD_VALUES, SCATTER_REVERSE);
2011 CHKERR VecGhostUpdateEnd(
f, ADD_VALUES, SCATTER_REVERSE);
2012 auto post_proc_rhs = get_essential_fe();
2013 post_proc_rhs->f =
f;
2015 post_proc_rhs.get());
2019 constexpr bool debug =
true;
2020 if constexpr (
debug) {
2022 CHKERR VecNorm(
f, NORM_2, &norm0);
2025 CHKERR calulate_fd_residual(
eps, dm_diff_vec, fd_check);
2027 CHKERR VecAXPY(fd_check, -1.0,
f);
2028 CHKERR VecNorm(fd_check, NORM_2, &nrm);
2030 <<
" FD check for internal forces [ " << mode <<
" ]: " << nrm
2031 <<
" / " << norm0 <<
" ( " << (nrm / norm0) <<
" )";
2038 auto calculate_variance_of_displacement = [&](
auto mode,
auto mod_vec) {
2042 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
2043 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
2047 auto evaluate_objective_terms =
2048 [&](
auto objective_fe,
auto objective_ptr,
auto objective_grad_ptr,
2049 double &objective_value,
double &objective_gradient) {
2051 *objective_ptr = 0.0;
2052 *objective_grad_ptr = 0.0;
2055 std::array<double, 2> array = {*objective_ptr, *objective_grad_ptr};
2056 MPI_Allreduce(MPI_IN_PLACE, array.data(), 2, MPI_DOUBLE, MPI_SUM,
2058 objective_value = array[0];
2059 objective_gradient = array[1];
2063 auto calculate_objective_value = [&]() {
2065 double objective_value = 0;
2066 double objective_gradient = 0;
2067 CHKERR evaluate_objective_terms(objective_fe_value, objective_ptr_value,
2068 objective_grad_ptr_value, objective_value,
2069 objective_gradient);
2070 *objective_function_value = objective_value;
2074 auto calculate_variance_of_objective_function_dJ_du = [&](Vec dJ_du) {
2077 auto fe = boost::make_shared<DomainEle>(
mField);
2078 fe->getRuleHook = [](int, int,
int p_data) {
2079 return 2 * p_data + p_data - 1;
2081 auto &pip = fe->getOpPtrVector();
2084 auto u_ptr = boost::make_shared<MatrixDouble>();
2087 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
2088 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
2091 CHKERR VecZeroEntries(dJ_du);
2094 CHKERR VecAssemblyBegin(dJ_du);
2095 CHKERR VecAssemblyEnd(dJ_du);
2097 auto post_proc_rhs = get_essential_fe();
2098 post_proc_rhs->f = dJ_du;
2100 post_proc_rhs.get());
2105 auto calculate_adjoint_lambda = [&](
auto lambda,
auto dJ_du) {
2108 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Solving for adjoint variable lambda";
2111 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
2112 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
2116 CHKERR VecZeroEntries(objective_function_gradient);
2117 CHKERR VecZeroEntries(adjoint_vector);
2119 CHKERR calculate_objective_value();
2121 <<
"Objective function: " << *objective_function_value;
2123 auto direct = [&]() {
2127 CHKERR set_variance_of_geometry(mode, mod_vec);
2128 CHKERR calculate_variance_internal_forces(mode, mod_vec);
2129 CHKERR calculate_variance_of_displacement(mode, mod_vec);
2130 double objective_value = 0;
2131 double objective_gradient = 0;
2132 CHKERR evaluate_objective_terms(objective_fe_direct, objective_ptr_direct,
2133 objective_grad_ptr_direct,
2134 objective_value, objective_gradient);
2135 CHKERR VecSetValue(objective_function_gradient, mode, objective_gradient,
2137 CHKERR VecAXPY(adjoint_vector, objective_gradient, dm_diff_vec);
2146 auto adjoint = [&]() {
2149 CHKERR calculate_variance_of_objective_function_dJ_du(dJ_du);
2156 CHKERR set_variance_of_geometry(mode, mod_vec);
2157 CHKERR calculate_variance_internal_forces(mode, mod_vec);
2158 double objective_value = 0;
2159 double objective_gradient_explicit = 0;
2160 CHKERR evaluate_objective_terms(
2161 objective_fe_explicit, objective_ptr_explicit,
2162 objective_grad_ptr_explicit, objective_value,
2163 objective_gradient_explicit);
2164 double lambda_dot_residual_variation = 0;
2166 const double dJ_dp =
2167 objective_gradient_explicit + lambda_dot_residual_variation;
2168 CHKERR VecSetValue(objective_function_gradient, mode, dJ_dp,
2170 CHKERR VecAXPY(adjoint_vector, dJ_dp, dm_diff_vec);
2173 CHKERR VecAssemblyBegin(objective_function_gradient);
2174 CHKERR VecAssemblyEnd(objective_function_gradient);
2180 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Direct Sensitivity...";
2185 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Adjoint Sensitivity...";
2191 "Wrong sensitivity type selected");
2194 CHKERR VecAssemblyBegin(objective_function_gradient);
2195 CHKERR VecAssemblyEnd(objective_function_gradient);
2197 CHKERR VecAssemblyBegin(adjoint_vector);
2198 CHKERR VecAssemblyEnd(adjoint_vector);
2199 CHKERR VecGhostUpdateBegin(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2200 CHKERR VecGhostUpdateEnd(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2245 const char param_file[] =
"param_file.petsc";
2248 auto core_log = logging::core::get();
2260 DMType dm_name =
"DMMOFEM";
2262 DMType dm_name_mg =
"DMMOFEM_MG";
2267 moab::Core mb_instance;
2268 moab::Interface &moab = mb_instance;
2286 if (Py_FinalizeEx() < 0) {
2292 const std::string block_name,
int dim) {
2298 std::regex((boost::format(
"%s(.*)") % block_name).str())
2302 for (
auto bc : bcs) {
2306 "get meshset ents");
2310 for (
auto dd = dim - 1; dd >= 0; --dd) {
2314 moab::Interface::UNION),
2334 CHKERR moab.add_entities(*out_meshset, r);
2335 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)
auto diff_symmetrize(FTensor::Number< DIM >)
static char help[]
[calculateGradient]
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ν))
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]
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 MYPCOMM_INDEX
default communicator number PCOMM
#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
auto diff_symmetrize(FTensor::Number< DIM >)
constexpr int SPACE_DIM
[Define dimension]
constexpr IntegrationType I
Use Gauss quadrature for integration.
FormsIntegrators< DomainEleOp >::Assembly< A >::OpBase DomainBaseOp
[Postprocess results]
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
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 DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
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.
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
auto createDMMatrix(DM dm)
Get smart matrix from DM.
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
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)
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'J', DIM1 > J
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
const FTensor::Tensor2< T, Dim, Dim > Vec
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
auto createKSP(MPI_Comm comm)
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 createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
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.
PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
Sets the objective function value and gradient for a TAO optimization solver.
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
MoFEMErrorCode VecSetValues(Vec V, const EntitiesFieldData::EntData &data, const double *ptr, InsertMode iora)
Assemble PETSc vector.
auto createTao(MPI_Comm comm)
boost::shared_ptr< ObjectiveFunctionData > create_python_objective_function(std::string)
constexpr IntegrationType I
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr auto field_name
static constexpr int approx_order
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
PetscBool is_plane_strain
FTensor::Index< 'm', 3 > m
Boundary conditions marker.
MoFEMErrorCode boundaryCondition()
Apply essential boundary conditions.
MoFEMErrorCode assembleSystem()
Setup operators in finite element pipeline.
MoFEMErrorCode readMesh()
Read mesh from file and setup meshsets.
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Interface to Python objective function.
std::vector< SmartPetscObj< Vec > > modeVecs
Topology mode vectors (design variables)
SmartPetscObj< DM > adjointDM
Data manager for adjoint problem.
FieldApproximationBase base
Choice of finite element basis functions.
std::vector< std::array< double, 3 > > modeCentroids
Centroids of optimization blocks.
MoFEMErrorCode topologyModes()
Compute topology optimization modes.
SmartPetscObj< KSP > kspElastic
Linear solver for elastic problem.
SmartPetscObj< Vec > initialGeometry
Initial geometry field.
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()
Setup adjoint fields and finite elements.
MoFEM::Interface & mField
Reference to MoFEM interface.
std::vector< std::array< double, 6 > > modeBBoxes
Bounding boxes of optimization blocks.
MoFEMErrorCode setupProblem()
Setup fields, approximation spaces and DOFs.
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 moab::Interface & get_moab()=0
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.
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.
MoFEMErrorCode fieldLambdaOnValues(OneFieldFunctionOnValues lambda, const std::string field_name, Range *ents_ptr=nullptr)
field lambda
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.
Post post-proc data at points from hash maps.
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.
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< MatrixDouble > diffJac
boost::shared_ptr< MatrixDouble > jac
OpAdJointGradTimesSymTensor(const std::string field_name, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > jac, boost::shared_ptr< MatrixDouble > diff_jac, boost::shared_ptr< VectorDouble > cof_vals)
boost::shared_ptr< HookeOps::CommonData > commPtr
boost::shared_ptr< VectorDouble > cofVals
Forward declaration of operator for gradient times symmetric tensor operations.
boost::shared_ptr< MatrixDouble > dGradPtr
boost::shared_ptr< double > globObjectiveGradPtr
boost::shared_ptr< HookeOps::CommonData > commPtr
ForcesAndSourcesCore::UserDataOperator OP
boost::shared_ptr< double > globObjectivePtr
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Compute objective function contributions at element level.
boost::shared_ptr< VectorDouble > cofVals
boost::shared_ptr< MatrixDouble > uPtr
boost::shared_ptr< MatrixDouble > jacPtr
OpAdJointObjective(boost::shared_ptr< ObjectiveFunctionData > python_ptr, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > jac_ptr, boost::shared_ptr< MatrixDouble > diff_jac, boost::shared_ptr< VectorDouble > cof_vals, boost::shared_ptr< MatrixDouble > d_grad_ptr, boost::shared_ptr< MatrixDouble > d_u_ptr, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< double > glob_objective_ptr, boost::shared_ptr< double > glob_objective_grad_ptr)
boost::shared_ptr< MatrixDouble > diffJacPtr
boost::shared_ptr< MatrixDouble > dUPtr
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