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;
34 IntegrationType::GAUSS;
85template <
int SPACE_DIM, IntegrationType I,
typename OpBase>
89template <
int SPACE_DIM, IntegrationType I,
typename OpBase>
93#include <ElasticSpring.hpp>
94#include <FluidLevel.hpp>
95#include <CalculateTraction.hpp>
96#include <NaturalDomainBC.hpp>
97#include <NaturalBoundaryBC.hpp>
98#include <HookeOps.hpp>
122 boost::shared_ptr<MatrixDouble> u_ptr,
123 boost::shared_ptr<MatrixDouble> stress_ptr,
124 boost::shared_ptr<MatrixDouble> strain_ptr,
125 boost::shared_ptr<VectorDouble> o_ptr) = 0;
130 boost::shared_ptr<MatrixDouble> u_ptr,
131 boost::shared_ptr<MatrixDouble> stress_ptr,
132 boost::shared_ptr<MatrixDouble> strain_ptr,
133 boost::shared_ptr<MatrixDouble> o_ptr) = 0;
138 boost::shared_ptr<MatrixDouble> u_ptr,
139 boost::shared_ptr<MatrixDouble> stress_ptr,
140 boost::shared_ptr<MatrixDouble> strain_ptr,
141 boost::shared_ptr<MatrixDouble> o_ptr) = 0;
148 std::array<double, 3> ¢roid,
149 std::array<double, 6> &bbox,
155boost::shared_ptr<ObjectiveFunctionData>
159 const std::string block_name,
int dim);
203 Vec objective_function_gradient,
246 char objective_function_file_name[255] =
"objective_function.py";
248 PETSC_NULLPTR, PETSC_NULLPTR,
"-objective_function",
249 objective_function_file_name, 255, PETSC_NULLPTR);
252 auto file_exists = [](std::string myfile) {
253 std::ifstream file(myfile.c_str());
259 if (!file_exists(objective_function_file_name)) {
260 MOFEM_LOG(
"WORLD", Sev::error) <<
"Objective function file NOT found: "
261 << objective_function_file_name;
284 auto create_vec_modes = [&](
auto block_name) {
289 std::regex((boost::format(
"%s(.*)") % block_name).str())
293 int nb_total_modes = 0;
294 for (
auto &bc : bcs) {
295 auto id = bc->getMeshsetId();
298 nb_total_modes += nb_modes;
302 <<
"Total number of modes to apply: " << nb_total_modes;
309 auto get_modes_bounding_boxes = [&](
auto block_name) {
314 std::regex((boost::format(
"%s(.*)") % block_name).str())
318 for (
auto &bc : bcs) {
319 auto meshset = bc->getMeshset();
324 std::vector<double> x(verts.size());
325 std::vector<double> y(verts.size());
326 std::vector<double> z(verts.size());
328 std::array<double, 3> centroid = {0, 0, 0};
329 for (
int i = 0;
i != verts.size(); ++
i) {
334 MPI_Allreduce(MPI_IN_PLACE, centroid.data(), 3, MPI_DOUBLE, MPI_SUM,
336 int nb_vertex = verts.size();
337 MPI_Allreduce(MPI_IN_PLACE, &nb_vertex, 1, MPI_INT, MPI_SUM,
340 centroid[0] /= nb_vertex;
341 centroid[1] /= nb_vertex;
342 centroid[2] /= nb_vertex;
344 std::array<double, 6> bbox = {centroid[0], centroid[1], centroid[2],
345 centroid[0], centroid[1], centroid[2]};
346 for (
int i = 0;
i != verts.size(); ++
i) {
347 bbox[0] = std::min(bbox[0], x[
i]);
348 bbox[1] = std::min(bbox[1], y[
i]);
349 bbox[2] = std::min(bbox[2], z[
i]);
350 bbox[3] = std::max(bbox[3], x[
i]);
351 bbox[4] = std::max(bbox[4], y[
i]);
352 bbox[5] = std::max(bbox[5], z[
i]);
354 MPI_Allreduce(MPI_IN_PLACE, &bbox[0], 3, MPI_DOUBLE, MPI_MIN,
356 MPI_Allreduce(MPI_IN_PLACE, &bbox[3], 3, MPI_DOUBLE, MPI_MAX,
360 <<
"Block: " << bc->getName() <<
" centroid: " << centroid[0] <<
" "
361 << centroid[1] <<
" " << centroid[2];
363 <<
"Block: " << bc->getName() <<
" bbox: " << bbox[0] <<
" "
364 << bbox[1] <<
" " << bbox[2] <<
" " << bbox[3] <<
" " << bbox[4]
374 auto eval_objective_and_gradient = [](Tao tao,
Vec x, PetscReal *
f,
Vec g,
375 void *ctx) -> PetscErrorCode {
380 CHKERR TaoGetIterationNumber(tao, &iter);
382 auto set_geometry = [&](
Vec x) {
387 CHKERR VecScatterCreateToAll(x, &ctx, &x_local);
389 CHKERR VecScatterBegin(ctx, x, x_local, INSERT_VALUES, SCATTER_FORWARD);
390 CHKERR VecScatterEnd(ctx, x, x_local, INSERT_VALUES, SCATTER_FORWARD);
392 CHKERR VecScatterDestroy(&ctx);
395 CHKERR VecCopy(ex_ptr->initialGeometry, current_geometry);
397 CHKERR VecGetArrayRead(x_local, &
a);
398 const double *coeff =
a;
399 for (
auto &mode_vec : ex_ptr->
modeVecs) {
401 <<
"Adding mode with coeff: " << *coeff;
402 CHKERR VecAXPY(current_geometry, (*coeff), mode_vec);
405 CHKERR VecRestoreArrayRead(x_local, &
a);
406 CHKERR VecGhostUpdateBegin(current_geometry, INSERT_VALUES,
408 CHKERR VecGhostUpdateEnd(current_geometry, INSERT_VALUES,
411 ->setOtherLocalGhostVector(
"ADJOINT",
"ADJOINT_FIELD",
"GEOMETRY",
413 INSERT_VALUES, SCATTER_REVERSE);
415 CHKERR VecDestroy(&x_local);
420 CHKERR KSPReset(ex_ptr->kspElastic);
421 CHKERR ex_ptr->solveElastic();
424 CHKERR ex_ptr->calculateGradient(
f,
g, adjoint_vector);
425 CHKERR ex_ptr->postprocessElastic(iter, adjoint_vector);
431 CHKERR create_vec_modes(
"OPTIMISE");
432 CHKERR get_modes_bounding_boxes(
"OPTIMISE");
445 CHKERR TaoSetType(tao, TAOLMVM);
457 INSERT_VALUES, SCATTER_FORWARD);
486 CHKERR TaoSetSolution(tao, x0);
487 CHKERR TaoSetFromOptions(tao);
491 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Topology optimization completed";
544 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
545 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
546 PetscInt choice_base_value = AINSWORTH;
548 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
550 switch (choice_base_value) {
554 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
559 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
593 auto project_ho_geometry = [&]() {
597 CHKERR project_ho_geometry();
628 auto create_adjoint_dm = [&]() {
631 auto add_field = [&]() {
636 for (
auto tt = MBEDGE; tt <= moab::CN::TypeDimensionMap[
SPACE_DIM].second;
646 auto add_adjoint_fe_impl = [&]() {
671 auto block_name =
"OPTIMISE";
675 std::regex((boost::format(
"%s(.*)") % block_name).str())
679 for (
auto bc : bcs) {
681 bc->getMeshset(),
SPACE_DIM - 1,
"ADJOINT_BOUNDARY_FE");
687 simple->getBitRefLevelMask());
692 auto set_adjoint_dm_imp = [&]() {
696 simple->getBitRefLevelMask());
698 CHKERR DMSetFromOptions(adjoint_dm);
705 CHKERR DMSetUp(adjoint_dm);
730 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_X",
732 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Y",
734 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
"REMOVE_Z",
736 CHKERR bc_mng->removeBlockDOFsOnEntities(
simple->getProblemName(),
737 "REMOVE_ALL",
"U", 0, 3);
739 simple->getProblemName(),
"U");
755 boost::make_shared<Range>(opt_ents));
757 boost::make_shared<Range>(opt_ents));
758 CHKERR DMSetUp(subset_dm_bdy);
766 CHKERR DMSetUp(subset_dm_domain);
769 auto remove_dofs = [&]() {
772 std::array<Range, 3> remove_dim_ents;
780 for (
int d = 0; d != 3; ++d) {
782 <<
"Removing topology modes on block OPT_REMOVE_" << (char)(
'X' + d)
783 <<
" with " << remove_dim_ents[d].size() <<
" entities";
791 CHKERR skin.find_skin(0, body_ents,
false, boundary_ents);
792 for (
int d = 0; d != 3; ++d) {
793 boundary_ents = subtract(boundary_ents, remove_dim_ents[d]);
795 ParallelComm *pcomm =
797 CHKERR pcomm->filter_pstatus(boundary_ents,
798 PSTATUS_SHARED | PSTATUS_MULTISHARED,
799 PSTATUS_NOT, -1,
nullptr);
800 for (
auto d =
SPACE_DIM - 2; d >= 0; --d) {
804 moab::Interface::UNION);
805 boundary_ents.merge(ents);
809 boundary_ents.merge(verts);
814 boundary_ents.merge(opt_ents);
816 "SUBSET_DOMAIN",
"ADJOINT_FIELD", boundary_ents);
817 for (
int d = 0; d != 3; ++d) {
819 "SUBSET_DOMAIN",
"ADJOINT_FIELD", remove_dim_ents[d], d, d);
834 auto get_lhs_fe = [&]() {
835 auto fe_lhs = boost::make_shared<BoundaryEle>(
mField);
836 fe_lhs->getRuleHook = [](int, int,
int p_data) {
837 return 2 * p_data + p_data - 1;
839 auto &pip = fe_lhs->getOpPtrVector();
844 pip.push_back(
new OpMass(
"ADJOINT_FIELD",
"ADJOINT_FIELD",
845 [](
double,
double,
double) {
return 1.; }));
849 auto get_rhs_fe = [&]() {
850 auto fe_rhs = boost::make_shared<BoundaryEle>(
mField);
851 fe_rhs->getRuleHook = [](int, int,
int p_data) {
852 return 2 * p_data + p_data - 1;
854 auto &pip = fe_rhs->getOpPtrVector();
861 auto block_name =
"OPTIMISE";
865 std::regex((boost::format(
"%s(.*)") % block_name).str())
874 struct OpMode :
public OP {
875 OpMode(
const std::string name,
876 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
int id,
878 std::vector<std::array<double, 3>> mode_centroids,
879 std::vector<std::array<double, 6>> mode_bboxes,
int block_counter,
880 int mode_counter, boost::shared_ptr<Range> range =
nullptr)
881 :
OP(name, name, OP::OPROW, range), pythonPtr(python_ptr), iD(
id),
882 modeVecs(mode_vecs), modeCentroids(mode_centroids),
883 modeBboxes(mode_bboxes), blockCounter(block_counter),
884 modeCounter(mode_counter) {}
890 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
898 auto nb_base_functions = data.
getN().size2();
901 CHKERR pythonPtr->blockModes(iD, OP::getCoordsAtGaussPts(),
902 modeCentroids[blockCounter],
903 modeBboxes[blockCounter], blockModes);
905 auto nb_integration_pts = getGaussPts().size2();
906 if (blockModes.size2() != 3 * nb_integration_pts) {
908 <<
"Number of modes does not match number of integration points: "
909 << blockModes.size2() <<
"!=" << 3 * nb_integration_pts;
915 int nb_modes = blockModes.size1();
916 for (
auto mode = 0; mode != nb_modes; ++mode) {
919 auto t_mode = getFTensor1FromPtr<3>(&blockModes(mode, 0));
921 const double vol = OP::getMeasure();
923 auto t_w = OP::getFTensor0IntegrationWeight();
927 for (
int gg = 0; gg != nb_integration_pts; gg++) {
930 const double alpha = t_w * vol;
932 auto t_nf = getFTensor1FromPtr<SPACE_DIM>(nf.data().data());
934 for (; rr != nb_rows /
SPACE_DIM; ++rr) {
935 t_nf(
i) += alpha * t_base * t_mode(
i);
939 for (; rr < nb_base_functions; ++rr)
944 Vec vec = modeVecs[modeCounter + mode];
946 auto *indices = data.
getIndices().data().data();
947 auto *nf_data = nf.data().data();
955 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
957 std::vector<std::array<double, 3>> modeCentroids;
958 std::vector<std::array<double, 6>> modeBboxes;
960 std::vector<SmartPetscObj<Vec>> modeVecs;
965 auto solve_bdy = [&]() {
968 auto fe_lhs = get_lhs_fe();
969 auto fe_rhs = get_rhs_fe();
970 int block_counter = 0;
971 int mode_counter = 0;
972 for (
auto &bc : bcs) {
973 auto id = bc->getMeshsetId();
977 auto range = boost::make_shared<Range>(ents);
978 auto &pip_rhs = fe_rhs->getOpPtrVector();
981 mode_counter, range));
988 mode_counter += nb_modes;
990 <<
"Setting mode block block: " << bc->getName()
991 <<
" with ID: " << bc->getMeshsetId()
992 <<
" total modes: " << mode_counter;
998 CHKERR VecGhostUpdateBegin(
v, ADD_VALUES, SCATTER_REVERSE);
999 CHKERR VecGhostUpdateEnd(
v, ADD_VALUES, SCATTER_REVERSE);
1006 CHKERR MatAssemblyBegin(
M, MAT_FINAL_ASSEMBLY);
1007 CHKERR MatAssemblyEnd(
M, MAT_FINAL_ASSEMBLY);
1010 CHKERR KSPSetOperators(solver,
M,
M);
1011 CHKERR KSPSetFromOptions(solver);
1020 CHKERR VecGhostUpdateBegin(
v, INSERT_VALUES, SCATTER_FORWARD);
1021 CHKERR VecGhostUpdateEnd(
v, INSERT_VALUES, SCATTER_FORWARD);
1029 auto get_elastic_fe_lhs = [&]() {
1030 auto fe = boost::make_shared<DomainEle>(
mField);
1031 fe->getRuleHook = [](int, int,
int p_data) {
1032 return 2 * p_data + p_data - 1;
1034 auto &pip = fe->getOpPtrVector();
1037 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
1038 mField, pip,
"ADJOINT_FIELD",
"MAT_ADJOINT", Sev::noisy);
1042 auto get_elastic_fe_rhs = [&]() {
1043 auto fe = boost::make_shared<DomainEle>(
mField);
1044 fe->getRuleHook = [](int, int,
int p_data) {
1045 return 2 * p_data + p_data - 1;
1047 auto &pip = fe->getOpPtrVector();
1050 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1051 mField, pip,
"ADJOINT_FIELD",
"MAT_ADJOINT", Sev::noisy);
1055 auto adjoint_gradient_postprocess = [&](
auto mode) {
1057 auto post_proc_mesh = boost::make_shared<moab::Core>();
1058 auto post_proc_begin =
1059 boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
mField,
1061 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
1064 auto geom_vec = boost::make_shared<MatrixDouble>();
1067 boost::make_shared<PostProcEleDomain>(
mField, post_proc_mesh);
1069 post_proc_fe->getOpPtrVector(), {H1},
"GEOMETRY");
1070 post_proc_fe->getOpPtrVector().push_back(
1076 post_proc_fe->getOpPtrVector().push_back(
1080 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1084 {{
"MODE", geom_vec}},
1095 post_proc_begin->getFEMethod());
1099 post_proc_begin->getFEMethod());
1101 CHKERR post_proc_end->writeFile(
"mode_" + std::to_string(mode) +
".h5m");
1106 auto solve_domain = [&]() {
1108 auto fe_lhs = get_elastic_fe_lhs();
1109 auto fe_rhs = get_elastic_fe_rhs();
1118 CHKERR MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY);
1119 CHKERR MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY);
1121 auto solver =
createKSP(mField.get_comm());
1122 CHKERR KSPSetOperators(solver, M, M);
1123 CHKERR KSPSetFromOptions(solver);
1126 int mode_counter = 0;
1127 for (
auto &f : modeVecs) {
1128 CHKERR mField.getInterface<
FieldBlas>()->setField(0,
"ADJOINT_FIELD");
1136 CHKERR VecGhostUpdateBegin(
F, ADD_VALUES, SCATTER_REVERSE);
1137 CHKERR VecGhostUpdateEnd(
F, ADD_VALUES, SCATTER_REVERSE);
1139 CHKERR VecGhostUpdateBegin(
v, INSERT_VALUES, SCATTER_FORWARD);
1140 CHKERR VecGhostUpdateEnd(
v, INSERT_VALUES, SCATTER_FORWARD);
1154 for (
int i = 0;
i < modeVecs.size(); ++
i) {
1155 CHKERR adjoint_gradient_postprocess(
i);
1178 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
1179 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
1183 pip->getOpDomainLhsPipeline(), {H1},
"GEOMETRY");
1185 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
1187 pip->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
1189 pip->getOpBoundaryLhsPipeline(), {NOSPACE},
"GEOMETRY");
1193 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
1194 mField, pip->getOpDomainLhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
1198 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1199 mField, pip->getOpDomainRhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
1203 pip->getOpDomainRhsPipeline(),
mField,
"U", Sev::inform);
1209 pip->getOpBoundaryRhsPipeline(),
mField,
"U", -1, Sev::inform);
1212 pip->getOpBoundaryLhsPipeline(),
mField,
"U", Sev::noisy);
1225 CHKERR VecZeroEntries(d);
1228 auto set_essential_bc = [&]() {
1233 auto pre_proc_rhs = boost::make_shared<FEMethod>();
1234 auto post_proc_rhs = boost::make_shared<FEMethod>();
1235 auto post_proc_lhs = boost::make_shared<FEMethod>();
1237 auto get_pre_proc_hook = [&]() {
1241 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
1243 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1247 post_proc_rhs, 1.)();
1251 auto get_post_proc_hook_lhs = [
this, post_proc_lhs]() {
1255 post_proc_lhs, 1.)();
1259 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1260 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
1262 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
1263 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
1264 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
1268 auto setup_and_solve = [&](
auto solver) {
1270 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
1271 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp";
1273 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp <= Done";
1274 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve";
1275 CHKERR KSPSolve(solver,
f, d);
1276 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve <= Done";
1283 CHKERR set_essential_bc();
1286 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
1287 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
1290 auto evaluate_field_at_the_point = [&]() {
1294 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
1297 field_eval_coords.data(), &coords_dim,
1303 auto field_eval_data =
1307 ->buildTree<SPACE_DIM>(field_eval_data,
simple->getDomainFEName());
1309 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1310 auto no_rule = [](int, int, int) {
return -1; };
1311 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
1312 field_eval_fe_ptr->getRuleHook = no_rule;
1314 field_eval_fe_ptr->getOpPtrVector().push_back(
1318 ->evalFEAtThePoint<SPACE_DIM>(
1319 field_eval_coords.data(), 1e-12,
simple->getProblemName(),
1320 simple->getDomainFEName(), field_eval_data,
1327 MOFEM_LOG(
"FieldEvaluator", Sev::inform)
1328 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1);
1330 MOFEM_LOG(
"FieldEvaluator", Sev::inform)
1331 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1)
1332 <<
" U_Z: " << t_disp(2);
1340 CHKERR evaluate_field_at_the_point();
1352 auto det_ptr = boost::make_shared<VectorDouble>();
1353 auto jac_ptr = boost::make_shared<MatrixDouble>();
1354 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1356 pip->getDomainRhsFE().reset();
1357 pip->getDomainLhsFE().reset();
1358 pip->getBoundaryRhsFE().reset();
1359 pip->getBoundaryLhsFE().reset();
1363 auto post_proc_mesh = boost::make_shared<moab::Core>();
1364 auto post_proc_begin = boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
1366 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
1371 auto calculate_stress_ops = [&](
auto &pip) {
1376 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEle>(
1377 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1380 auto u_ptr = boost::make_shared<MatrixDouble>();
1382 auto x_ptr = boost::make_shared<MatrixDouble>();
1386 using DataMapMat = std::map<std::string, boost::shared_ptr<MatrixDouble>>;
1388 DataMapMat vec_map = {{
"U", u_ptr}, {
"GEOMETRY", x_ptr}};
1389 DataMapMat sym_map = {{
"STRAIN", common_ptr->getMatStrain()},
1390 {
"STRESS", common_ptr->getMatCauchyStress()}};
1392 if (adjoint_vector) {
1393 auto adjoint_ptr = boost::make_shared<MatrixDouble>();
1395 "U", adjoint_ptr, adjoint_vector));
1396 vec_map[
"ADJOINT"] = adjoint_ptr;
1400 return boost::make_tuple(u_ptr, x_ptr, common_ptr->getMatStrain(),
1401 common_ptr->getMatCauchyStress(), vec_map,
1405 auto get_tag_id_on_pmesh = [&](
bool post_proc_skin) {
1406 int def_val_int = 0;
1409 "MAT_ELASTIC", 1, MB_TYPE_INTEGER, tag_mat,
1410 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val_int);
1411 auto meshset_vec_ptr =
1413 std::regex((boost::format(
"%s(.*)") %
"MAT_ELASTIC").str()));
1416 std::unique_ptr<Skinner> skin_ptr;
1417 if (post_proc_skin) {
1419 auto boundary_meshset =
simple->getBoundaryMeshSet();
1424 for (
auto m : meshset_vec_ptr) {
1428 int const id =
m->getMeshsetId();
1429 ents_3d = ents_3d.subset_by_dimension(
SPACE_DIM);
1430 if (post_proc_skin) {
1432 CHKERR skin_ptr->find_skin(0, ents_3d,
false, skin_faces);
1433 ents_3d = intersect(skin_ents, skin_faces);
1441 auto post_proc_domain = [&](
auto post_proc_mesh) {
1443 boost::make_shared<PostProcEleDomain>(
mField, post_proc_mesh);
1446 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr, vec_map, sym_map] =
1447 calculate_stress_ops(post_proc_fe->getOpPtrVector());
1449 post_proc_fe->getOpPtrVector().push_back(
1453 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1467 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(
false)});
1468 return post_proc_fe;
1471 auto post_proc_boundary = [&](
auto post_proc_mesh) {
1473 boost::make_shared<PostProcEleBdy>(
mField, post_proc_mesh);
1475 post_proc_fe->getOpPtrVector(), {},
"GEOMETRY");
1479 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr, vec_map, sym_map] =
1480 calculate_stress_ops(op_loop_side->getOpPtrVector());
1481 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
1482 auto mat_traction_ptr = boost::make_shared<MatrixDouble>();
1483 post_proc_fe->getOpPtrVector().push_back(
1485 vec_map[
"T"] = mat_traction_ptr;
1489 post_proc_fe->getOpPtrVector().push_back(
1493 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1507 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(
true)});
1508 return post_proc_fe;
1511 PetscBool post_proc_skin_only = PETSC_FALSE;
1513 post_proc_skin_only = PETSC_TRUE;
1515 &post_proc_skin_only, PETSC_NULLPTR);
1517 if (post_proc_skin_only == PETSC_FALSE) {
1518 pip->getDomainRhsFE() = post_proc_domain(post_proc_mesh);
1520 pip->getBoundaryRhsFE() = post_proc_boundary(post_proc_mesh);
1524 post_proc_begin->getFEMethod());
1525 CHKERR pip->loopFiniteElements();
1527 post_proc_end->getFEMethod());
1529 CHKERR post_proc_end->writeFile(
"out_elastic_" + std::to_string(iter) +
1552template <
int SPACE_DIM>
1559 boost::shared_ptr<HookeOps::CommonData> comm_ptr)
1578template <
int SPACE_DIM>
1592 const double vol = OP::getMeasure();
1594 auto t_w = OP::getFTensor0IntegrationWeight();
1598 auto t_cauchy_stress =
1599 getFTensor2SymmetricFromMat<SPACE_DIM>(*(commPtr->getMatCauchyStress()));
1602 for (
int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1604 const double alpha = t_w * vol;
1607 auto t_nf = OP::template getNf<SPACE_DIM>();
1610 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
1612 t_nf(
j) += alpha * t_row_grad(
i) * t_cauchy_stress(
i,
j);
1617 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1627template <
int SPACE_DIM>
1634 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1635 boost::shared_ptr<MatrixDouble> jac,
1636 boost::shared_ptr<MatrixDouble> diff_jac,
1637 boost::shared_ptr<VectorDouble> cof_vals)
1639 jac(jac), diffJac(diff_jac), cofVals(cof_vals) {}
1643 boost::shared_ptr<MatrixDouble>
jac;
1658 t_diff(
i,
j,
k,
l) = 0;
1659 t_diff(0, 0, 0, 0) = 1;
1660 t_diff(1, 1, 1, 1) = 1;
1662 t_diff(1, 0, 1, 0) = 0.5;
1663 t_diff(1, 0, 0, 1) = 0.5;
1665 t_diff(0, 1, 0, 1) = 0.5;
1666 t_diff(0, 1, 1, 0) = 0.5;
1668 if constexpr (DIM == 3) {
1669 t_diff(2, 2, 2, 2) = 1;
1671 t_diff(2, 0, 2, 0) = 0.5;
1672 t_diff(2, 0, 0, 2) = 0.5;
1673 t_diff(0, 2, 0, 2) = 0.5;
1674 t_diff(0, 2, 2, 0) = 0.5;
1676 t_diff(2, 1, 2, 1) = 0.5;
1677 t_diff(2, 1, 1, 2) = 0.5;
1678 t_diff(1, 2, 1, 2) = 0.5;
1679 t_diff(1, 2, 2, 1) = 0.5;
1685template <
int SPACE_DIM>
1700 const double vol = OP::getMeasure();
1702 auto t_w = OP::getFTensor0IntegrationWeight();
1704 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(jac));
1706 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(diffJac));
1713 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(commPtr->matGradPtr));
1715 auto t_cauchy_stress =
1716 getFTensor2SymmetricFromMat<SPACE_DIM>(*(commPtr->getMatCauchyStress()));
1719 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
1721 for (
int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1723 const double alpha = t_w * vol;
1731 t_diff_inv_jac(
i,
j) =
1732 -(t_inv_jac(
i,
I) * t_diff_jac(
I,
J)) * t_inv_jac(
J,
j);
1734 t_diff_grad(
i,
j) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j);
1738 t_diff_strain(
i,
j) = t_diff_symm(
i,
j,
k,
l) * t_diff_grad(
k,
l);
1742 t_diff_stress(
i,
j) = t_D(
i,
j,
k,
l) * t_diff_strain(
k,
l);
1745 auto t_nf = OP::template getNf<SPACE_DIM>();
1748 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
1751 t_diff_row_grad(
k) = t_row_grad(
j) * t_diff_inv_jac(
j,
k);
1754 t_nf(
j) += alpha * t_diff_row_grad(
i) * t_cauchy_stress(
i,
j);
1757 t_nf(
j) += (alpha * t_cof) * t_row_grad(
i) * t_cauchy_stress(
i,
j);
1760 t_nf(
j) += alpha * t_row_grad(
i) * t_diff_stress(
i,
j);
1765 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1798 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1799 boost::shared_ptr<MatrixDouble> jac_ptr,
1800 boost::shared_ptr<MatrixDouble> diff_jac,
1801 boost::shared_ptr<VectorDouble> cof_vals,
1802 boost::shared_ptr<MatrixDouble> d_grad_ptr,
1803 boost::shared_ptr<MatrixDouble> u_ptr,
1804 boost::shared_ptr<double> glob_objective_ptr,
1805 boost::shared_ptr<double> glob_objective_grad_ptr)
1834 auto nb_gauss_pts = getGaussPts().size2();
1835 auto objective_ptr = boost::make_shared<VectorDouble>(nb_gauss_pts);
1836 auto objective_dstress =
1837 boost::make_shared<MatrixDouble>(symm_size, nb_gauss_pts);
1838 auto objective_dstrain =
1839 boost::make_shared<MatrixDouble>(symm_size, nb_gauss_pts);
1840 auto obj_grad = boost::make_shared<MatrixDouble>(
SPACE_DIM, nb_gauss_pts);
1842 auto evaluate_python = [&]() {
1844 auto &coords = OP::getCoordsAtGaussPts();
1856 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
commPtr->matGradPtr));
1858 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
1859 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
jacPtr));
1860 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
diffJacPtr));
1862 auto t_d_grad = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
dGradPtr));
1865 auto t_obj_dstress =
1866 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
1867 auto t_obj_dstrain =
1868 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
1870 auto vol = OP::getMeasure();
1871 auto t_w = getFTensor0IntegrationWeight();
1872 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
1879 t_diff_inv_jac(
i,
j) =
1880 -(t_inv_jac(
i,
I) * t_diff_jac(
I,
J)) * t_inv_jac(
J,
j);
1882 t_diff_grad(
i,
j) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j);
1885 t_d_strain(
i,
j) = t_diff_symm(
i,
j,
k,
l) * (
1895 auto alpha = t_w * vol;
1897 (*globObjectivePtr) += alpha * t_obj;
1898 (*globObjectiveGradPtr) +=
1902 t_obj_dstress(
i,
j) * (t_D(
i,
j,
k,
l) * t_d_strain(
k,
l))
1906 t_obj_dstrain(
i,
j) * t_d_strain(
i,
j)
1929 CHKERR evaluate_python();
1941 boost::shared_ptr<MatrixDouble>
uPtr;
1948 Vec objective_function_gradient,
1949 Vec adjoint_vector) {
1956 auto get_essential_fe = [
this]() {
1957 auto post_proc_rhs = boost::make_shared<FEMethod>();
1958 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1962 post_proc_rhs, 0)();
1965 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1966 return post_proc_rhs;
1969 auto get_fd_direvative_fe = [&]() {
1970 auto fe = boost::make_shared<DomainEle>(
mField);
1971 fe->getRuleHook = [](int, int,
int p_data) {
1972 return 2 * p_data + p_data - 1;
1974 auto &pip = fe->getOpPtrVector();
1977 constexpr bool debug =
false;
1978 if constexpr (
debug) {
1979 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1980 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1984 HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1985 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1990 auto calulate_fd_residual = [&](
auto eps,
auto diff_vec,
auto fd_vec) {
1993 constexpr bool debug =
false;
1999 auto norm2_field = [&](
const double val) {
2004 MPI_Allreduce(MPI_IN_PLACE, &nrm2, 1, MPI_DOUBLE, MPI_SUM,
2006 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Geometry norm: " << sqrt(nrm2);
2010 if constexpr (
debug)
2016 initial_current_geometry, INSERT_VALUES, SCATTER_FORWARD);
2017 CHKERR VecAssemblyBegin(initial_current_geometry);
2018 CHKERR VecAssemblyEnd(initial_current_geometry);
2020 if constexpr (
debug)
2023 auto perturb_geometry = [&](
auto eps,
auto diff_vec) {
2026 CHKERR VecCopy(initial_current_geometry, current_geometry);
2027 CHKERR VecAXPY(current_geometry,
eps, diff_vec);
2030 current_geometry, INSERT_VALUES, SCATTER_REVERSE);
2034 auto fe = get_fd_direvative_fe();
2037 auto calc_impl = [&](
auto f,
auto eps) {
2043 simple->getDomainFEName(), fe);
2046 CHKERR VecGhostUpdateBegin(
f, ADD_VALUES, SCATTER_REVERSE);
2047 CHKERR VecGhostUpdateEnd(
f, ADD_VALUES, SCATTER_REVERSE);
2048 auto post_proc_rhs = get_essential_fe();
2049 post_proc_rhs->f =
f;
2051 post_proc_rhs.get());
2056 CHKERR VecWAXPY(fd_vec, -1.0, fm, fp);
2057 CHKERR VecScale(fd_vec, 1.0 / (2.0 *
eps));
2061 initial_current_geometry, INSERT_VALUES, SCATTER_REVERSE);
2063 if constexpr (
debug)
2069 auto get_direvative_fe = [&](
auto diff_vec) {
2070 auto fe_adjoint = boost::make_shared<DomainEle>(
mField);
2071 fe_adjoint->getRuleHook = [](int, int,
int p_data) {
2072 return 2 * p_data + p_data - 1;
2074 auto &pip = fe_adjoint->getOpPtrVector();
2076 auto jac_ptr = boost::make_shared<MatrixDouble>();
2077 auto det_ptr = boost::make_shared<VectorDouble>();
2078 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
2079 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
2080 auto cof_ptr = boost::make_shared<VectorDouble>();
2088 "GEOMETRY", jac_ptr));
2094 pip.push_back(
new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
2097 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
2098 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
2100 "U", common_ptr, jac_ptr, diff_jac_ptr, cof_ptr));
2105 auto get_objective_fe = [&](
auto diff_vec,
auto grad_vec,
2106 auto glob_objective_ptr,
2107 auto glob_objective_grad_ptr) {
2108 auto fe_adjoint = boost::make_shared<DomainEle>(
mField);
2109 fe_adjoint->getRuleHook = [](int, int,
int p_data) {
2110 return 2 * p_data + p_data - 1;
2112 auto &pip = fe_adjoint->getOpPtrVector();
2115 auto jac_ptr = boost::make_shared<MatrixDouble>();
2116 auto det_ptr = boost::make_shared<VectorDouble>();
2117 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
2118 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
2119 auto cof_ptr = boost::make_shared<VectorDouble>();
2120 auto d_grad_ptr = boost::make_shared<MatrixDouble>();
2121 auto u_ptr = boost::make_shared<MatrixDouble>();
2126 "GEOMETRY", jac_ptr));
2131 pip.push_back(
new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
2133 "U", d_grad_ptr, grad_vec));
2136 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
2137 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
2139 pythonPtr, common_ptr, jac_ptr, diff_jac_ptr, cof_ptr, d_grad_ptr,
2140 u_ptr, glob_objective_ptr, glob_objective_grad_ptr));
2145 auto dm =
simple->getDM();
2150 auto adjoint_fe = get_direvative_fe(dm_diff_vec);
2151 auto glob_objective_ptr = boost::make_shared<double>(0.0);
2152 auto glob_objective_grad_ptr = boost::make_shared<double>(0.0);
2153 auto objective_fe = get_objective_fe(dm_diff_vec, d, glob_objective_ptr,
2154 glob_objective_grad_ptr);
2156 auto set_variance_of_geometry = [&](
auto mode,
auto mod_vec) {
2162 dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
2163 CHKERR VecGhostUpdateBegin(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
2164 CHKERR VecGhostUpdateEnd(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
2168 auto calculate_variance_internal_forces = [&](
auto mode,
auto mod_vec) {
2171 CHKERR VecGhostUpdateBegin(
f, INSERT_VALUES, SCATTER_FORWARD);
2172 CHKERR VecGhostUpdateEnd(
f, INSERT_VALUES, SCATTER_FORWARD);
2177 CHKERR VecGhostUpdateBegin(
f, ADD_VALUES, SCATTER_REVERSE);
2178 CHKERR VecGhostUpdateEnd(
f, ADD_VALUES, SCATTER_REVERSE);
2179 auto post_proc_rhs = get_essential_fe();
2180 post_proc_rhs->f =
f;
2182 post_proc_rhs.get());
2186 constexpr bool debug =
false;
2187 if constexpr (
debug) {
2189 CHKERR VecNorm(
f, NORM_2, &norm0);
2192 CHKERR calulate_fd_residual(
eps, dm_diff_vec, fd_check);
2194 CHKERR VecAXPY(fd_check, -1.0,
f);
2195 CHKERR VecNorm(fd_check, NORM_2, &nrm);
2197 <<
" FD check for internal forces [ " << mode <<
" ]: " << nrm
2198 <<
" / " << norm0 <<
" ( " << (nrm / norm0) <<
" )";
2205 auto calulate_variance_of_displacement = [&](
auto mode,
auto mod_vec) {
2208 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
2209 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
2213 auto calculate_variance_of_objective_function = [&](
auto mode,
auto mod_vec) {
2215 *glob_objective_ptr = 0.0;
2216 *glob_objective_grad_ptr = 0.0;
2219 CHKERR VecSetValue(objective_function_gradient, mode,
2220 *glob_objective_grad_ptr, ADD_VALUES);
2221 std::array<double, 2> array = {*glob_objective_ptr,
2222 *glob_objective_grad_ptr};
2223 MPI_Allreduce(MPI_IN_PLACE, array.data(), 2, MPI_DOUBLE, MPI_SUM,
2225 *glob_objective_ptr = array[0];
2226 *glob_objective_grad_ptr = array[1];
2227 (*objective_function_value) += *glob_objective_ptr;
2229 MOFEM_LOG(
"WORLD", Sev::verbose) <<
" Objective gradient [ " << mode
2230 <<
" ]: " << *glob_objective_grad_ptr;
2234 CHKERR VecZeroEntries(objective_function_gradient);
2235 CHKERR VecZeroEntries(adjoint_vector);
2236 *objective_function_value = 0.0;
2240 CHKERR set_variance_of_geometry(mode, mod_vec);
2241 CHKERR calculate_variance_internal_forces(mode, mod_vec);
2242 CHKERR calulate_variance_of_displacement(mode, mod_vec);
2243 CHKERR calculate_variance_of_objective_function(mode, mod_vec);
2245 CHKERR VecAXPY(adjoint_vector, *glob_objective_grad_ptr, dm_diff_vec);
2249 (*objective_function_value) /=
modeVecs.size();
2251 <<
"Objective function: " << *glob_objective_ptr;
2253 CHKERR VecAssemblyBegin(objective_function_gradient);
2254 CHKERR VecAssemblyEnd(objective_function_gradient);
2256 CHKERR VecAssemblyBegin(adjoint_vector);
2257 CHKERR VecAssemblyEnd(adjoint_vector);
2258 CHKERR VecGhostUpdateBegin(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2259 CHKERR VecGhostUpdateEnd(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2304 const char param_file[] =
"param_file.petsc";
2307 auto core_log = logging::core::get();
2319 DMType dm_name =
"DMMOFEM";
2321 DMType dm_name_mg =
"DMMOFEM_MG";
2326 moab::Core mb_instance;
2327 moab::Interface &moab = mb_instance;
2344 if (Py_FinalizeEx() < 0) {
2400 boost::shared_ptr<MatrixDouble> u_ptr,
2401 boost::shared_ptr<MatrixDouble> stress_ptr,
2402 boost::shared_ptr<MatrixDouble> strain_ptr,
2403 boost::shared_ptr<VectorDouble> o_ptr);
2421 boost::shared_ptr<MatrixDouble> u_ptr,
2422 boost::shared_ptr<MatrixDouble> stress_ptr,
2423 boost::shared_ptr<MatrixDouble> strain_ptr,
2424 boost::shared_ptr<MatrixDouble> o_ptr);
2442 boost::shared_ptr<MatrixDouble> u_ptr,
2443 boost::shared_ptr<MatrixDouble> stress_ptr,
2444 boost::shared_ptr<MatrixDouble> strain_ptr,
2445 boost::shared_ptr<MatrixDouble> o_ptr);
2463 boost::shared_ptr<MatrixDouble> u_ptr,
2464 boost::shared_ptr<MatrixDouble> stress_ptr,
2465 boost::shared_ptr<MatrixDouble> strain_ptr,
2466 boost::shared_ptr<MatrixDouble> o_ptr);
2486 std::array<double, 3> ¢roid,
2515 np::ndarray coords, np::ndarray u,
2517 np::ndarray stress, np::ndarray strain, np::ndarray &o
2536 np::ndarray coords, np::ndarray u,
2538 np::ndarray stress, np::ndarray strain, np::ndarray &o
2557 np::ndarray coords, np::ndarray u,
2559 np::ndarray stress, np::ndarray strain, np::ndarray &o
2579 np::ndarray coords, np::ndarray u,
2581 np::ndarray stress, np::ndarray strain, np::ndarray &o
2601 int block_id, np::ndarray coords, np::ndarray centroid, np::ndarray bbodx,
2659boost::shared_ptr<ObjectiveFunctionData>
2661 auto ptr = boost::make_shared<ObjectiveFunctionDataImpl>();
2695 auto main_module = bp::import(
"__main__");
2709 }
catch (bp::error_already_set
const &) {
2722 auto t_f = getFTensor2FromMat<3, 3>(f);
2723 auto t_s = getFTensor2SymmetricFromMat<SPACE_DIM>(s);
2724 for (
int ii = 0; ii != s.size2(); ++ii) {
2725 t_f(
i,
j) = t_s(
i,
j);
2737 ptr + 0 * s.size2(), ptr + 1 * s.size2(),
2738 ptr + 2 * s.size2(), ptr + 3 * s.size2(),
2739 ptr + 4 * s.size2(), ptr + 5 * s.size2(),
2740 ptr + 6 * s.size2(), ptr + 7 * s.size2(),
2744 auto t_s = getFTensor2SymmetricFromMat<SPACE_DIM>(s);
2745 for (
int ii = 0; ii != s.size2(); ++ii) {
2746 t_s(
i,
j) = (t_f(
i,
j) || t_f(
j,
i)) / 2.0;
2780 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
2781 boost::shared_ptr<MatrixDouble> stress_ptr,
2782 boost::shared_ptr<MatrixDouble> strain_ptr,
2783 boost::shared_ptr<VectorDouble> o_ptr) {
2791 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
2795 auto full_stress =
copyToFull(*(stress_ptr));
2796 auto full_strain =
copyToFull(*(strain_ptr));
2799 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
2800 full_stress.size2());
2801 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
2802 full_strain.size2());
2805 np::ndarray np_output = np::empty(bp::make_tuple(strain_ptr->size2()),
2806 np::dtype::get_builtin<double>());
2813 o_ptr->resize(stress_ptr->size2(),
false);
2814 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
2815 std::copy(val_ptr, val_ptr + strain_ptr->size2(), o_ptr->data().begin());
2817 }
catch (bp::error_already_set
const &) {
2856 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
2857 boost::shared_ptr<MatrixDouble> stress_ptr,
2858 boost::shared_ptr<MatrixDouble> strain_ptr,
2859 boost::shared_ptr<MatrixDouble> o_ptr) {
2866 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
2869 auto full_stress =
copyToFull(*(stress_ptr));
2870 auto full_strain =
copyToFull(*(strain_ptr));
2873 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
2874 full_stress.size2());
2875 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
2876 full_strain.size2());
2879 np::ndarray np_output =
2880 np::empty(bp::make_tuple(full_strain.size1(), full_strain.size2()),
2881 np::dtype::get_builtin<double>());
2888 o_ptr->resize(stress_ptr->size1(), stress_ptr->size2(),
false);
2889 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
2893 }
catch (bp::error_already_set
const &) {
2933 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
2934 boost::shared_ptr<MatrixDouble> stress_ptr,
2935 boost::shared_ptr<MatrixDouble> strain_ptr,
2936 boost::shared_ptr<MatrixDouble> o_ptr) {
2943 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
2946 auto full_stress =
copyToFull(*(stress_ptr));
2947 auto full_strain =
copyToFull(*(strain_ptr));
2948 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
2949 full_stress.size2());
2950 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
2951 full_strain.size2());
2954 np::ndarray np_output =
2955 np::empty(bp::make_tuple(full_strain.size1(), full_strain.size2()),
2956 np::dtype::get_builtin<double>());
2961 o_ptr->resize(strain_ptr->size1(), strain_ptr->size2(),
false);
2962 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
2965 }
catch (bp::error_already_set
const &) {
3007 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
3008 boost::shared_ptr<MatrixDouble> stress_ptr,
3009 boost::shared_ptr<MatrixDouble> strain_ptr,
3010 boost::shared_ptr<MatrixDouble> o_ptr) {
3017 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
3020 auto full_stress =
copyToFull(*(stress_ptr));
3021 auto full_strain =
copyToFull(*(strain_ptr));
3022 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
3023 full_stress.size2());
3024 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
3025 full_strain.size2());
3028 np::ndarray np_output =
3029 np::empty(bp::make_tuple(u_ptr->size1(), u_ptr->size2()),
3030 np::dtype::get_builtin<double>());
3038 o_ptr->resize(u_ptr->size1(), u_ptr->size2(),
false);
3039 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
3040 std::copy(val_ptr, val_ptr + u_ptr->size1() * u_ptr->size2(),
3041 o_ptr->data().begin());
3043 }
catch (bp::error_already_set
const &) {
3087 int block_id,
MatrixDouble &coords, std::array<double, 3> ¢roid,
3104 np::ndarray np_output =
3105 np::empty(bp::make_tuple(coords.size1(), nb_modes, 3),
3106 np::dtype::get_builtin<double>());
3113 o_ptr.resize(nb_modes, coords.size1() * coords.size2(),
false);
3114 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
3116 std::copy(val_ptr, val_ptr + coords.size1() * coords.size2() * nb_modes,
3117 o_ptr.data().begin());
3119 }
catch (bp::error_already_set
const &) {
3129 np::ndarray coords, np::ndarray u,
3131 np::ndarray stress, np::ndarray strain, np::ndarray &o
3140 }
catch (bp::error_already_set
const &) {
3150 np::ndarray coords, np::ndarray u,
3152 np::ndarray stress, np::ndarray strain, np::ndarray &o
3159 o = bp::extract<np::ndarray>(
3162 }
catch (bp::error_already_set
const &) {
3172 np::ndarray coords, np::ndarray u,
3174 np::ndarray stress, np::ndarray strain, np::ndarray &o
3181 o = bp::extract<np::ndarray>(
3184 }
catch (bp::error_already_set
const &) {
3194 np::ndarray coords, np::ndarray u,
3196 np::ndarray stress, np::ndarray strain, np::ndarray &o
3205 }
catch (bp::error_already_set
const &) {
3220 }
catch (bp::error_already_set
const &) {
3230 np::ndarray centroid,
3236 o = bp::extract<np::ndarray>(
3238 }
catch (bp::error_already_set
const &) {
3269 auto dtype = np::dtype::get_builtin<double>();
3270 auto size = bp::make_tuple(rows, nb_gauss_pts);
3271 auto stride = bp::make_tuple(nb_gauss_pts *
sizeof(
double),
sizeof(
double));
3272 return (np::from_data(data.data(), dtype, size, stride, bp::object()));
3277 auto dtype = np::dtype::get_builtin<double>();
3278 auto size = bp::make_tuple(s);
3279 auto stride = bp::make_tuple(
sizeof(
double));
3280 return (np::from_data(ptr, dtype, size, stride, bp::object()));
3284 const std::string block_name,
int dim) {
3290 std::regex((boost::format(
"%s(.*)") % block_name).str())
3294 for (
auto bc : bcs) {
3298 "get meshset ents");
3302 for (
auto dd = dim - 1; dd >= 0; --dd) {
3306 moab::Interface::UNION),
3326 CHKERR moab.add_entities(*out_meshset, r);
3327 CHKERR moab.write_file(name.c_str(),
"VTK",
"", out_meshset->get_ptr(), 1);
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#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
constexpr int SPACE_DIM
[Define dimension]
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ν))
boost::shared_ptr< ObjectiveFunctionData > create_python_objective_function(std::string py_file)
Factory function to create Python-integrated objective function interface.
constexpr AssemblyType A
[Define dimension]
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
constexpr int SPACE_DIM
[Define dimension]
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_OPERATION_UNSUCCESSFUL
@ 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
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 DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
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)
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 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
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.
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
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 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.
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)
constexpr IntegrationType I
constexpr AssemblyType A
[Define dimension]
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr auto field_name
static constexpr int approx_order
OpBaseImpl< PETSC, EdgeEleOp > OpBase
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
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.
SmartPetscObj< KSP > kspElastic
Linear solver for elastic problem.
std::vector< SmartPetscObj< Vec > > modeVecs
Topology mode vectors (design variables)
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< 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.
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Interface to Python objective function.
SmartPetscObj< DM > adjointDM
Data manager for adjoint problem.
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::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
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 double precision vector field values calculation.
Element used to execute operators on side of the element.
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.
Implementation of ObjectiveFunctionData interface using Python integration.
MoFEMErrorCode objectiveGradientStrainImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Internal implementation for strain gradient computation.
MoFEMErrorCode numberOfModes(int block_id, int &modes)
Return number of topology optimization modes for given material block.
MoFEMErrorCode blockModesImpl(int block_id, np::ndarray coords, np::ndarray centroid, np::ndarray bbodx, np::ndarray &o_ptr)
Internal implementation for topology mode generation.
bp::object objectNumberOfModes
Python function: numberOfModes(block_id) -> int.
MoFEMErrorCode evalObjectiveGradientStrain(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)
Compute gradient of objective function with respect to strain.
bp::object objectiveGradientStress
Python function: ∂f/∂σ(coords,u,stress,strain) -> gradient
ObjectiveFunctionDataImpl()=default
MoFEMErrorCode initPython(const std::string py_file)
Initialize Python interpreter and load objective function script.
MoFEMErrorCode blockModes(int block_id, MatrixDouble &coords, std::array< double, 3 > ¢roid, std::array< double, 6 > &bbodx, MatrixDouble &o_ptr)
Define spatial topology modes for design optimization.
bp::object objectiveGradientStrain
Python function: ∂f/∂ε(coords,u,stress,strain) -> gradient.
MoFEMErrorCode evalObjectiveGradientU(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)
Compute gradient of objective function with respect to displacement.
virtual ~ObjectiveFunctionDataImpl()=default
MoFEMErrorCode evalObjectiveGradientStress(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)
Compute gradient of objective function with respect to stress.
bp::object objectiveFunction
Python function: f(coords,u,stress,strain) -> objective.
MoFEMErrorCode evalObjectiveFunction(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< VectorDouble > o_ptr)
Evaluate objective function at current state.
bp::object objectiveGradientU
Python function: ∂f/∂u(coords,u,stress,strain) -> gradient.
MatrixDouble copyToFull(MatrixDouble &s)
Convert symmetric tensor storage to full matrix format.
np::ndarray convertToNumPy(std::vector< double > &data, int rows, int nb_gauss_pts)
Convert std::vector to NumPy array for Python interface.
MoFEMErrorCode objectiveGradientUImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Internal implementation for displacement gradient computation.
MoFEMErrorCode objectiveGradientStressImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Internal implementation for stress gradient computation.
void copyToSymmetric(double *ptr, MatrixDouble &s)
Convert full matrix to symmetric tensor storage format
bp::object objectBlockModes
Python function: blockModes(block_id,coords,centroid,bbox) -> modes.
bp::object mainNamespace
Main Python namespace for script execution.
MoFEMErrorCode objectiveFunctionImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Internal implementation for objective function evaluation.
[Adjoint operator declarations]
virtual ~ObjectiveFunctionData()=default
virtual MoFEMErrorCode evalObjectiveGradientStress(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)=0
Evaluate gradient of objective function w.r.t. stress: ∂f/∂σ
virtual MoFEMErrorCode evalObjectiveGradientStrain(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)=0
Evaluate gradient of objective function w.r.t. strain: ∂f/∂ε
virtual MoFEMErrorCode numberOfModes(int block_id, int &modes)=0
Return number of topology optimization modes for given block.
virtual MoFEMErrorCode blockModes(int block_id, MatrixDouble &coords, std::array< double, 3 > ¢roid, std::array< double, 6 > &bbox, MatrixDouble &o_ptr)=0
Define spatial modes for topology optimization.
virtual MoFEMErrorCode evalObjectiveFunction(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< VectorDouble > o_ptr)=0
Evaluate objective function f(coords, u, stress, strain)
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.
Operator for computing objective function and gradients in topology optimization.
boost::shared_ptr< MatrixDouble > dGradPtr
boost::shared_ptr< double > globObjectiveGradPtr
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
boost::shared_ptr< double > globObjectivePtr
ForcesAndSourcesCore::UserDataOperator OP
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< VectorDouble > cofVals
boost::shared_ptr< MatrixDouble > uPtr
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 > 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 > jacPtr
OpAdJointTestOp(const std::string field_name, boost::shared_ptr< HookeOps::CommonData > comm_ptr)
boost::shared_ptr< HookeOps::CommonData > commPtr
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle
ElementsAndOps< SPACE_DIM >::SideEle SideEle
#define EXECUTABLE_DIMENSION
PetscBool do_eval_field
Evaluate field.