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;
1365template <
int SPACE_DIM>
1377 auto t_diff_symm = FTensor::diff_symmetrize<double>();
1380 const double vol = OP::getMeasure();
1382 auto t_w = OP::getFTensor0IntegrationWeight();
1384 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(jac));
1386 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(diffJac));
1393 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(commPtr->matGradPtr));
1395 auto t_cauchy_stress =
1396 getFTensor2SymmetricFromMat<SPACE_DIM>(*(commPtr->getMatCauchyStress()));
1399 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
1401 for (
int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1403 const double alpha = t_w * vol;
1411 t_diff_inv_jac(
i,
j) =
1412 -(t_inv_jac(
i,
I) * t_diff_jac(
I,
J)) * t_inv_jac(
J,
j);
1414 t_diff_grad(
i,
j) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j);
1418 t_diff_strain(
i,
j) = t_diff_symm(
i,
j,
k,
l) * t_diff_grad(
k,
l);
1422 t_diff_stress(
i,
j) = t_D(
i,
j,
k,
l) * t_diff_strain(
k,
l);
1425 auto t_nf = OP::template getNf<SPACE_DIM>();
1428 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
1431 t_diff_row_grad(
k) = t_row_grad(
j) * t_diff_inv_jac(
j,
k);
1434 t_nf(
j) += alpha * t_diff_row_grad(
i) * t_cauchy_stress(
i,
j);
1437 t_nf(
j) += (alpha * t_cof) * t_row_grad(
i) * t_cauchy_stress(
i,
j);
1440 t_nf(
j) += alpha * t_row_grad(
i) * t_diff_stress(
i,
j);
1445 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1464 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
1465 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1466 boost::shared_ptr<MatrixDouble> u_ptr)
1478 auto nb_gauss_pts = getGaussPts().size2();
1480 auto objective_dstress =
1481 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
1482 auto objective_dstrain =
1483 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
1485 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
1487 auto evaluate_python = [&]() {
1489 auto &coords = OP::getCoordsAtGaussPts();
1500 auto vol = OP::getMeasure();
1501 auto t_w = OP::getFTensor0IntegrationWeight();
1504 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
1508 auto t_obj_dstress =
1509 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
1510 auto t_obj_dstrain =
1511 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
1512 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
1514 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
1515 const double alpha = t_w * vol;
1517 t_adjoint_stress(
i,
j) =
1518 t_D(
i,
j,
k,
l) * t_obj_dstress(
k,
l) + t_obj_dstrain(
i,
j);
1520 auto t_nf = OP::template getNf<SPACE_DIM>();
1522 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
1523 t_nf(
j) += alpha * t_row_grad(
i) * t_adjoint_stress(
i,
j);
1524 t_nf(
j) += alpha * t_row_base * t_obj_du(
j);
1531 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1542 CHKERR evaluate_python();
1549 boost::shared_ptr<MatrixDouble>
uPtr;
1555 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1556 boost::shared_ptr<MatrixDouble> jac_ptr,
1557 boost::shared_ptr<MatrixDouble> diff_jac,
1558 boost::shared_ptr<VectorDouble> cof_vals,
1559 boost::shared_ptr<MatrixDouble> d_grad_ptr,
1560 boost::shared_ptr<MatrixDouble> d_u_ptr,
1561 boost::shared_ptr<MatrixDouble> u_ptr,
1562 boost::shared_ptr<double> glob_objective_ptr,
1563 boost::shared_ptr<double> glob_objective_grad_ptr)
1592 auto t_diff_symm = FTensor::diff_symmetrize<double>();
1596 getGaussPts().size2();
1597 auto objective_ptr = boost::make_shared<MatrixDouble>(
1599 auto objective_dstress = boost::make_shared<MatrixDouble>(
1602 auto objective_dstrain = boost::make_shared<MatrixDouble>(
1606 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
1609 auto evaluate_python = [&]() {
1611 auto &coords = OP::getCoordsAtGaussPts();
1626 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
commPtr->matGradPtr));
1628 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
1629 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
jacPtr));
1630 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
diffJacPtr));
1632 auto t_d_grad = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
dGradPtr));
1635 auto t_obj_dstress =
1636 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
1637 auto t_obj_dstrain =
1638 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
1639 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
1640 auto t_d_u = getFTensor1FromMat<SPACE_DIM>(*
dUPtr);
1642 auto vol = OP::getMeasure();
1643 auto t_w = getFTensor0IntegrationWeight();
1644 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
1651 t_diff_inv_jac(
i,
j) =
1652 -(t_inv_jac(
i,
I) * t_diff_jac(
I,
J)) * t_inv_jac(
J,
j);
1654 t_diff_grad(
i,
j) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j);
1657 t_d_strain(
i,
j) = t_diff_symm(
i,
j,
k,
l) * (
1667 auto alpha = t_w * vol;
1669 (*globObjectivePtr) += alpha * t_obj;
1670 (*globObjectiveGradPtr) +=
1674 t_obj_dstress(
i,
j) * (t_D(
i,
j,
k,
l) * t_d_strain(
k,
l))
1678 t_obj_dstrain(
i,
j) * t_d_strain(
i,
j)
1682 t_obj_du(
i) * t_d_u(
i)
1707 CHKERR evaluate_python();
1720 boost::shared_ptr<MatrixDouble>
uPtr;
1727 Vec objective_function_gradient,
1728 Vec adjoint_vector) {
1735 auto get_essential_fe = [
this]() {
1736 auto post_proc_rhs = boost::make_shared<FEMethod>();
1737 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1741 post_proc_rhs, 0)();
1744 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1745 return post_proc_rhs;
1748 auto get_fd_direvative_fe = [&]() {
1749 auto fe = boost::make_shared<DomainEle>(
mField);
1750 fe->getRuleHook = [](int, int,
int p_data) {
1751 return 2 * p_data + p_data - 1;
1753 auto &pip = fe->getOpPtrVector();
1756 HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1757 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1762 auto calulate_fd_residual = [&](
auto eps,
auto diff_vec,
auto fd_vec) {
1765 constexpr bool debug =
false;
1771 auto norm2_field = [&](
const double val) {
1776 MPI_Allreduce(MPI_IN_PLACE, &nrm2, 1, MPI_DOUBLE, MPI_SUM,
1778 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Geometry norm: " << sqrt(nrm2);
1782 if constexpr (
debug)
1788 initial_current_geometry, INSERT_VALUES, SCATTER_FORWARD);
1789 CHKERR VecAssemblyBegin(initial_current_geometry);
1790 CHKERR VecAssemblyEnd(initial_current_geometry);
1792 if constexpr (
debug)
1795 auto perturb_geometry = [&](
auto eps,
auto diff_vec) {
1798 CHKERR VecCopy(initial_current_geometry, current_geometry);
1799 CHKERR VecAXPY(current_geometry,
eps, diff_vec);
1802 current_geometry, INSERT_VALUES, SCATTER_REVERSE);
1806 auto fe = get_fd_direvative_fe();
1809 auto calc_impl = [&](
auto f,
auto eps) {
1815 simple->getDomainFEName(), fe);
1818 CHKERR VecGhostUpdateBegin(
f, ADD_VALUES, SCATTER_REVERSE);
1819 CHKERR VecGhostUpdateEnd(
f, ADD_VALUES, SCATTER_REVERSE);
1820 auto post_proc_rhs = get_essential_fe();
1821 post_proc_rhs->f =
f;
1823 post_proc_rhs.get());
1828 CHKERR VecWAXPY(fd_vec, -1.0, fm, fp);
1829 CHKERR VecScale(fd_vec, 1.0 / (2.0 *
eps));
1833 initial_current_geometry, INSERT_VALUES, SCATTER_REVERSE);
1835 if constexpr (
debug)
1841 auto get_direvative_fe = [&](
auto diff_vec) {
1842 auto fe_adjoint = boost::make_shared<DomainEle>(
mField);
1843 fe_adjoint->getRuleHook = [](int, int,
int p_data) {
1844 return 2 * p_data + p_data - 1;
1846 auto &pip = fe_adjoint->getOpPtrVector();
1848 auto jac_ptr = boost::make_shared<MatrixDouble>();
1849 auto det_ptr = boost::make_shared<VectorDouble>();
1850 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1851 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
1852 auto cof_ptr = boost::make_shared<VectorDouble>();
1860 "GEOMETRY", jac_ptr));
1862 "U", diff_jac_ptr, diff_vec));
1864 pip.push_back(
new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
1867 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1868 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1870 "U", common_ptr, jac_ptr, diff_jac_ptr, cof_ptr));
1875 auto get_objective_fe = [&](
auto diff_vec,
auto grad_vec,
1876 auto glob_objective_ptr,
1877 auto glob_objective_grad_ptr) {
1878 auto fe_adjoint = boost::make_shared<DomainEle>(
mField);
1879 fe_adjoint->getRuleHook = [](int, int,
int p_data) {
1880 return 2 * p_data + p_data - 1;
1882 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>();
1890 auto d_grad_ptr = boost::make_shared<MatrixDouble>();
1891 auto d_u_ptr = boost::make_shared<MatrixDouble>();
1892 auto u_ptr = boost::make_shared<MatrixDouble>();
1897 "GEOMETRY", jac_ptr));
1902 pip.push_back(
new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
1904 "U", d_grad_ptr, grad_vec));
1909 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1910 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1912 pythonPtr, common_ptr, jac_ptr, diff_jac_ptr, cof_ptr, d_grad_ptr,
1913 d_u_ptr, u_ptr, glob_objective_ptr, glob_objective_grad_ptr));
1918 auto dm =
simple->getDM();
1924 CHKERR VecZeroEntries(zero_diff_vec);
1925 CHKERR VecZeroEntries(zero_state_sensitivity);
1926 CHKERR VecGhostUpdateBegin(zero_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1927 CHKERR VecGhostUpdateEnd(zero_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1928 CHKERR VecGhostUpdateBegin(zero_state_sensitivity, INSERT_VALUES,
1930 CHKERR VecGhostUpdateEnd(zero_state_sensitivity, INSERT_VALUES,
1933 auto adjoint_fe = get_direvative_fe(dm_diff_vec);
1934 auto objective_ptr_direct = boost::make_shared<double>(0.0);
1935 auto objective_grad_ptr_direct = boost::make_shared<double>(0.0);
1936 auto objective_fe_direct = get_objective_fe(
1937 dm_diff_vec, d, objective_ptr_direct, objective_grad_ptr_direct);
1938 auto objective_ptr_explicit = boost::make_shared<double>(0.0);
1939 auto objective_grad_ptr_explicit = boost::make_shared<double>(0.0);
1940 auto objective_fe_explicit =
1941 get_objective_fe(dm_diff_vec, zero_state_sensitivity,
1942 objective_ptr_explicit, objective_grad_ptr_explicit);
1943 auto objective_ptr_value = boost::make_shared<double>(0.0);
1944 auto objective_grad_ptr_value = boost::make_shared<double>(0.0);
1945 auto objective_fe_value =
1946 get_objective_fe(zero_diff_vec, zero_state_sensitivity,
1947 objective_ptr_value, objective_grad_ptr_value);
1949 auto set_variance_of_geometry =
1950 [&](
auto mode,
auto mod_vec) {
1958 dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1959 CHKERR VecGhostUpdateBegin(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1960 CHKERR VecGhostUpdateEnd(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1964 auto calculate_variance_internal_forces = [&](
auto mode,
auto mod_vec) {
1967 CHKERR VecGhostUpdateBegin(
f, INSERT_VALUES, SCATTER_FORWARD);
1968 CHKERR VecGhostUpdateEnd(
f, INSERT_VALUES, SCATTER_FORWARD);
1973 CHKERR VecGhostUpdateBegin(
f, ADD_VALUES, SCATTER_REVERSE);
1974 CHKERR VecGhostUpdateEnd(
f, ADD_VALUES, SCATTER_REVERSE);
1975 auto post_proc_rhs = get_essential_fe();
1976 post_proc_rhs->f =
f;
1978 post_proc_rhs.get());
1982 constexpr bool debug =
true;
1983 if constexpr (
debug) {
1985 CHKERR VecNorm(
f, NORM_2, &norm0);
1988 CHKERR calulate_fd_residual(
eps, dm_diff_vec, fd_check);
1990 CHKERR VecAXPY(fd_check, -1.0,
f);
1991 CHKERR VecNorm(fd_check, NORM_2, &nrm);
1993 <<
" FD check for internal forces [ " << mode <<
" ]: " << nrm
1994 <<
" / " << norm0 <<
" ( " << (nrm / norm0) <<
" )";
2001 auto calculate_variance_of_displacement = [&](
auto mode,
auto mod_vec) {
2005 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
2006 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
2010 auto evaluate_objective_terms =
2011 [&](
auto objective_fe,
auto objective_ptr,
auto objective_grad_ptr,
2012 double &objective_value,
double &objective_gradient) {
2014 *objective_ptr = 0.0;
2015 *objective_grad_ptr = 0.0;
2018 std::array<double, 2> array = {*objective_ptr, *objective_grad_ptr};
2019 MPI_Allreduce(MPI_IN_PLACE, array.data(), 2, MPI_DOUBLE, MPI_SUM,
2021 objective_value = array[0];
2022 objective_gradient = array[1];
2026 auto calculate_objective_value = [&]() {
2028 double objective_value = 0;
2029 double objective_gradient = 0;
2030 CHKERR evaluate_objective_terms(objective_fe_value, objective_ptr_value,
2031 objective_grad_ptr_value, objective_value,
2032 objective_gradient);
2033 *objective_function_value = objective_value;
2037 auto calculate_variance_of_objective_function_dJ_du = [&](Vec dJ_du) {
2040 auto fe = boost::make_shared<DomainEle>(
mField);
2041 fe->getRuleHook = [](int, int,
int p_data) {
2042 return 2 * p_data + p_data - 1;
2044 auto &pip = fe->getOpPtrVector();
2047 auto u_ptr = boost::make_shared<MatrixDouble>();
2050 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
2051 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
2054 CHKERR VecZeroEntries(dJ_du);
2057 CHKERR VecAssemblyBegin(dJ_du);
2058 CHKERR VecAssemblyEnd(dJ_du);
2060 auto post_proc_rhs = get_essential_fe();
2061 post_proc_rhs->f = dJ_du;
2063 post_proc_rhs.get());
2068 auto calculate_adjoint_lambda = [&](
auto lambda,
auto dJ_du) {
2071 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Solving for adjoint variable lambda";
2074 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
2075 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
2079 CHKERR VecZeroEntries(objective_function_gradient);
2080 CHKERR VecZeroEntries(adjoint_vector);
2082 CHKERR calculate_objective_value();
2084 <<
"Objective function: " << *objective_function_value;
2086 auto direct = [&]() {
2090 CHKERR set_variance_of_geometry(mode, mod_vec);
2091 CHKERR calculate_variance_internal_forces(mode, mod_vec);
2092 CHKERR calculate_variance_of_displacement(mode, mod_vec);
2093 double objective_value = 0;
2094 double objective_gradient = 0;
2095 CHKERR evaluate_objective_terms(objective_fe_direct, objective_ptr_direct,
2096 objective_grad_ptr_direct,
2097 objective_value, objective_gradient);
2098 CHKERR VecSetValue(objective_function_gradient, mode, objective_gradient,
2100 CHKERR VecAXPY(adjoint_vector, objective_gradient, dm_diff_vec);
2109 auto adjoint = [&]() {
2112 CHKERR calculate_variance_of_objective_function_dJ_du(dJ_du);
2119 CHKERR set_variance_of_geometry(mode, mod_vec);
2120 CHKERR calculate_variance_internal_forces(mode, mod_vec);
2121 double objective_value = 0;
2122 double objective_gradient_explicit = 0;
2123 CHKERR evaluate_objective_terms(
2124 objective_fe_explicit, objective_ptr_explicit,
2125 objective_grad_ptr_explicit, objective_value,
2126 objective_gradient_explicit);
2127 double lambda_dot_residual_variation = 0;
2129 const double dJ_dp =
2130 objective_gradient_explicit + lambda_dot_residual_variation;
2131 CHKERR VecSetValue(objective_function_gradient, mode, dJ_dp,
2133 CHKERR VecAXPY(adjoint_vector, dJ_dp, dm_diff_vec);
2136 CHKERR VecAssemblyBegin(objective_function_gradient);
2137 CHKERR VecAssemblyEnd(objective_function_gradient);
2143 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Direct Sensitivity...";
2148 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Adjoint Sensitivity...";
2154 "Wrong sensitivity type selected");
2157 CHKERR VecAssemblyBegin(objective_function_gradient);
2158 CHKERR VecAssemblyEnd(objective_function_gradient);
2160 CHKERR VecAssemblyBegin(adjoint_vector);
2161 CHKERR VecAssemblyEnd(adjoint_vector);
2162 CHKERR VecGhostUpdateBegin(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2163 CHKERR VecGhostUpdateEnd(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2208 const char param_file[] =
"param_file.petsc";
2211 auto core_log = logging::core::get();
2223 DMType dm_name =
"DMMOFEM";
2225 DMType dm_name_mg =
"DMMOFEM_MG";
2230 moab::Core mb_instance;
2231 moab::Interface &moab = mb_instance;
2249 if (Py_FinalizeEx() < 0) {
2255 const std::string block_name,
int dim) {
2261 std::regex((boost::format(
"%s(.*)") % block_name).str())
2265 for (
auto bc : bcs) {
2269 "get meshset ents");
2273 for (
auto dd = dim - 1; dd >= 0; --dd) {
2277 moab::Interface::UNION),
2297 CHKERR moab.add_entities(*out_meshset, r);
2298 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)
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
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