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>
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);
469 "", 1,
"gradient_fd",
470 [
this, tao, x0,
g, rank, eval_objective_and_gradient]()
mutable {
472 PetscReal
eps = 1e-4, design = 0;
477 CHKERR VecSet(x0, design);
479 CHKERR eval_objective_and_gradient(tao, x0, &value,
g,
this);
483 CHKERR VecCopy(x0, test_x);
486 auto evaluate = [&](
Vec x, PetscReal &
f) {
487 return eval_objective_and_gradient(tao, x, &f, work_gradient,
this);
490 for (PetscInt mode = 0; mode <
modeVecs.size(); ++mode) {
491 CHKERR VecZeroEntries(direction);
493 CHKERR VecSetValue(direction, mode, 1., INSERT_VALUES);
494 CHKERR VecAssemblyBegin(direction);
495 CHKERR VecAssemblyEnd(direction);
496 PetscReal fd, analytical;
497 CHKERR tester->checkScalarCentralFiniteDifference(
498 test_x, direction,
g,
eps, evaluate, fd, analytical);
500 <<
"Shape gradient mode " << mode
501 <<
": FD=" << std::setprecision(16) << fd
502 <<
" analytical=" << analytical
503 <<
" error=" << std::abs(fd - analytical);
506 std::to_string(mode),
507 analytical, fd, {1e-6, 1e-6});
509 CHKERR eval_objective_and_gradient(tao, x0, &value,
g,
this);
513 if (
testing->checkTest(
"gradient_fd"))
517 tao,
"shape optimisation adjoint");
520 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Topology optimization completed";
573 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
574 const char *list_bases[LASBASETOPT] = {
"ainsworth",
"demkowicz"};
575 PetscInt choice_base_value = AINSWORTH;
577 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
579 switch (choice_base_value) {
583 <<
"Set AINSWORTH_LEGENDRE_BASE for displacements";
588 <<
"Set DEMKOWICZ_JACOBI_BASE for displacements";
622 auto project_ho_geometry = [&]() {
626 CHKERR project_ho_geometry();
657 auto create_adjoint_dm = [&]() {
660 auto add_field = [&]() {
665 for (
auto tt = MBEDGE; tt <= moab::CN::TypeDimensionMap[
SPACE_DIM].second;
675 auto add_adjoint_fe_impl = [&]() {
700 auto block_name =
"OPTIMISE";
704 std::regex((boost::format(
"%s(.*)") % block_name).str())
708 for (
auto bc : bcs) {
710 bc->getMeshset(),
SPACE_DIM - 1,
"ADJOINT_BOUNDARY_FE");
721 auto set_adjoint_dm_imp = [&]() {
727 CHKERR DMSetFromOptions(adjoint_dm);
734 CHKERR DMSetUp(adjoint_dm);
766 "REMOVE_ALL",
"U", 0, 3);
784 boost::make_shared<Range>(opt_ents));
786 boost::make_shared<Range>(opt_ents));
787 CHKERR DMSetUp(subset_dm_bdy);
795 CHKERR DMSetUp(subset_dm_domain);
798 auto remove_dofs = [&]() {
801 std::array<Range, 3> remove_dim_ents;
809 for (
int d = 0; d != 3; ++d) {
811 <<
"Removing topology modes on block OPT_REMOVE_" << (char)(
'X' + d)
812 <<
" with " << remove_dim_ents[d].size() <<
" entities";
820 CHKERR skin.find_skin(0, body_ents,
false, boundary_ents);
821 for (
int d = 0; d != 3; ++d) {
822 boundary_ents = subtract(boundary_ents, remove_dim_ents[d]);
824 ParallelComm *pcomm =
826 CHKERR pcomm->filter_pstatus(boundary_ents,
827 PSTATUS_SHARED | PSTATUS_MULTISHARED,
828 PSTATUS_NOT, -1,
nullptr);
829 for (
auto d =
SPACE_DIM - 2; d >= 0; --d) {
833 moab::Interface::UNION);
834 boundary_ents.merge(ents);
838 boundary_ents.merge(verts);
843 boundary_ents.merge(opt_ents);
845 "SUBSET_DOMAIN",
"ADJOINT_FIELD", boundary_ents);
846 for (
int d = 0; d != 3; ++d) {
848 "SUBSET_DOMAIN",
"ADJOINT_FIELD", remove_dim_ents[d], d, d);
863 auto get_lhs_fe = [&]() {
864 auto fe_lhs = boost::make_shared<BoundaryEle>(
mField);
865 fe_lhs->getRuleHook = [](int, int,
int p_data) {
866 return 2 * p_data + p_data - 1;
868 auto &pip = fe_lhs->getOpPtrVector();
873 pip.push_back(
new OpMass(
"ADJOINT_FIELD",
"ADJOINT_FIELD",
874 [](
double,
double,
double) {
return 1.; }));
878 auto get_rhs_fe = [&]() {
879 auto fe_rhs = boost::make_shared<BoundaryEle>(
mField);
880 fe_rhs->getRuleHook = [](int, int,
int p_data) {
881 return 2 * p_data + p_data - 1;
883 auto &pip = fe_rhs->getOpPtrVector();
890 auto block_name =
"OPTIMISE";
894 std::regex((boost::format(
"%s(.*)") % block_name).str())
903 struct OpMode :
public OP {
904 OpMode(
const std::string
name,
905 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
int id,
907 std::vector<std::array<double, 3>> mode_centroids,
908 std::vector<std::array<double, 6>> mode_bboxes,
int block_counter,
909 int mode_counter, boost::shared_ptr<Range> range =
nullptr)
910 :
OP(
name,
name, OP::OPROW, range), pythonPtr(python_ptr), iD(
id),
911 modeVecs(mode_vecs), modeCentroids(mode_centroids),
912 modeBboxes(mode_bboxes), blockCounter(block_counter),
913 modeCounter(mode_counter) {}
919 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
927 auto nb_base_functions = data.
getN().size2();
930 CHKERR pythonPtr->blockModes(iD, OP::getCoordsAtGaussPts(),
931 modeCentroids[blockCounter],
932 modeBboxes[blockCounter], blockModes);
934 auto nb_integration_pts = getGaussPts().size2();
935 if (blockModes.size2() != 3 * nb_integration_pts) {
937 <<
"Number of modes does not match number of integration points: "
938 << blockModes.size2() <<
"!=" << 3 * nb_integration_pts;
944 int nb_modes = blockModes.size1();
945 for (
auto mode = 0; mode != nb_modes; ++mode) {
948 auto t_mode = getFTensor1FromPtr<3>(&blockModes(mode, 0));
950 const double vol = OP::getMeasure();
952 auto t_w = OP::getFTensor0IntegrationWeight();
956 for (
int gg = 0; gg != nb_integration_pts; gg++) {
959 const double alpha = t_w * vol;
961 auto t_nf = getFTensor1FromPtr<SPACE_DIM>(nf.data().data());
963 for (; rr != nb_rows /
SPACE_DIM; ++rr) {
964 t_nf(
i) += alpha * t_base * t_mode(
i);
968 for (; rr < nb_base_functions; ++rr)
973 Vec vec = modeVecs[modeCounter + mode];
975 auto *indices = data.
getIndices().data().data();
976 auto *nf_data = nf.data().data();
984 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
986 std::vector<std::array<double, 3>> modeCentroids;
987 std::vector<std::array<double, 6>> modeBboxes;
989 std::vector<SmartPetscObj<Vec>> modeVecs;
994 auto solve_bdy = [&]() {
997 auto fe_lhs = get_lhs_fe();
998 auto fe_rhs = get_rhs_fe();
999 int block_counter = 0;
1000 int mode_counter = 0;
1001 for (
auto &bc : bcs) {
1002 auto id = bc->getMeshsetId();
1006 auto range = boost::make_shared<Range>(ents);
1007 auto &pip_rhs = fe_rhs->getOpPtrVector();
1010 mode_counter, range));
1017 mode_counter += nb_modes;
1019 <<
"Setting mode block block: " << bc->getName()
1020 <<
" with ID: " << bc->getMeshsetId()
1021 <<
" total modes: " << mode_counter;
1027 CHKERR VecGhostUpdateBegin(
v, ADD_VALUES, SCATTER_REVERSE);
1028 CHKERR VecGhostUpdateEnd(
v, ADD_VALUES, SCATTER_REVERSE);
1035 CHKERR MatAssemblyBegin(
M, MAT_FINAL_ASSEMBLY);
1036 CHKERR MatAssemblyEnd(
M, MAT_FINAL_ASSEMBLY);
1039 CHKERR KSPSetOperators(solver,
M,
M);
1040 CHKERR KSPSetFromOptions(solver);
1044 CHKERR KSPSolve(solver, f,
v);
1049 CHKERR VecGhostUpdateBegin(
v, INSERT_VALUES, SCATTER_FORWARD);
1050 CHKERR VecGhostUpdateEnd(
v, INSERT_VALUES, SCATTER_FORWARD);
1058 auto get_elastic_fe_lhs = [&]() {
1059 auto fe = boost::make_shared<DomainEle>(
mField);
1060 fe->getRuleHook = [](int, int,
int p_data) {
1061 return 2 * p_data + p_data - 1;
1063 auto &pip = fe->getOpPtrVector();
1066 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
1067 mField, pip,
"ADJOINT_FIELD",
"MAT_ADJOINT", Sev::noisy);
1071 auto get_elastic_fe_rhs = [&]() {
1072 auto fe = boost::make_shared<DomainEle>(
mField);
1073 fe->getRuleHook = [](int, int,
int p_data) {
1074 return 2 * p_data + p_data - 1;
1076 auto &pip = fe->getOpPtrVector();
1079 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1080 mField, pip,
"ADJOINT_FIELD",
"MAT_ADJOINT", Sev::noisy);
1084 auto adjoint_gradient_postprocess = [&](
auto mode) {
1086 auto post_proc_mesh = boost::make_shared<moab::Core>();
1087 auto post_proc_begin =
1088 boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
mField,
1090 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
1093 auto geom_vec = boost::make_shared<MatrixDouble>();
1096 boost::make_shared<PostProcEleDomain>(
mField, post_proc_mesh);
1098 post_proc_fe->getOpPtrVector(), {H1},
"GEOMETRY");
1099 post_proc_fe->getOpPtrVector().push_back(
1105 post_proc_fe->getOpPtrVector().push_back(
1109 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1113 {{
"MODE", geom_vec}},
1124 post_proc_begin->getFEMethod());
1128 post_proc_begin->getFEMethod());
1130 CHKERR post_proc_end->writeFile(
"mode_" + std::to_string(mode) +
".h5m");
1135 auto solve_domain = [&]() {
1137 auto fe_lhs = get_elastic_fe_lhs();
1138 auto fe_rhs = get_elastic_fe_rhs();
1147 CHKERR MatAssemblyBegin(
M, MAT_FINAL_ASSEMBLY);
1148 CHKERR MatAssemblyEnd(
M, MAT_FINAL_ASSEMBLY);
1150 auto solver =
createKSP(mField.get_comm());
1151 CHKERR KSPSetOperators(solver,
M,
M);
1152 CHKERR KSPSetFromOptions(solver);
1155 int mode_counter = 0;
1156 for (
auto &f : modeVecs) {
1157 CHKERR mField.getInterface<
FieldBlas>()->setField(0,
"ADJOINT_FIELD");
1165 CHKERR VecGhostUpdateBegin(
F, ADD_VALUES, SCATTER_REVERSE);
1166 CHKERR VecGhostUpdateEnd(
F, ADD_VALUES, SCATTER_REVERSE);
1168 CHKERR VecGhostUpdateBegin(
v, INSERT_VALUES, SCATTER_FORWARD);
1169 CHKERR VecGhostUpdateEnd(
v, INSERT_VALUES, SCATTER_FORWARD);
1183 for (
int i = 0;
i < modeVecs.size(); ++
i) {
1184 CHKERR adjoint_gradient_postprocess(
i);
1204 pip->getOpDomainLhsPipeline(), {H1},
"GEOMETRY");
1206 pip->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
1208 pip->getOpBoundaryRhsPipeline(), {NOSPACE},
"GEOMETRY");
1210 pip->getOpBoundaryLhsPipeline(), {NOSPACE},
"GEOMETRY");
1214 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
1215 mField, pip->getOpDomainLhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
1219 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1220 mField, pip->getOpDomainRhsPipeline(),
"U",
"MAT_ELASTIC", Sev::noisy);
1224 pip->getOpDomainRhsPipeline(),
mField,
"U", Sev::inform);
1230 pip->getOpBoundaryRhsPipeline(),
mField,
"U", -1, Sev::inform);
1233 pip->getOpBoundaryLhsPipeline(),
mField,
"U", Sev::noisy);
1246 CHKERR VecZeroEntries(d);
1249 auto set_essential_bc = [&]() {
1254 auto pre_proc_rhs = boost::make_shared<FEMethod>();
1255 auto post_proc_rhs = boost::make_shared<FEMethod>();
1256 auto post_proc_lhs = boost::make_shared<FEMethod>();
1258 auto get_pre_proc_hook = [&]() {
1262 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
1264 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1268 post_proc_rhs, 1.)();
1272 auto get_post_proc_hook_lhs = [
this, post_proc_lhs]() {
1276 post_proc_lhs, 1.)();
1280 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1281 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
1283 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
1284 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
1285 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
1289 auto setup_and_solve = [&](
auto solver) {
1291 BOOST_LOG_SCOPED_THREAD_ATTR(
"Timeline", attrs::timer());
1292 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp";
1294 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSetUp <= Done";
1295 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve";
1296 CHKERR KSPSolve(solver, f, d);
1297 MOFEM_LOG(
"TIMER", Sev::noisy) <<
"KSPSolve <= Done";
1304 CHKERR set_essential_bc();
1307 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
1308 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
1311 auto evaluate_field_at_the_point = [&]() {
1315 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
1318 field_eval_coords.data(), &coords_dim,
1323 auto vector_field_ptr = boost::make_shared<MatrixDouble>();
1324 auto field_eval_data =
1330 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1331 auto no_rule = [](int, int, int) {
return -1; };
1332 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
1333 field_eval_fe_ptr->getRuleHook = no_rule;
1335 field_eval_fe_ptr->getOpPtrVector().push_back(
1339 ->evalFEAtThePoint<SPACE_DIM>(
1345 if (vector_field_ptr->size1()) {
1346 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vector_field_ptr);
1348 MOFEM_LOG(
"FieldEvaluator", Sev::inform)
1349 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1);
1351 MOFEM_LOG(
"FieldEvaluator", Sev::inform)
1352 <<
"U_X: " << t_disp(0) <<
" U_Y: " << t_disp(1)
1353 <<
" U_Z: " << t_disp(2);
1361 CHKERR evaluate_field_at_the_point();
1375 "out_elastic_" + std::to_string(iter) +
".h5m",
1376 {{
"ADJOINT", adjoint_vector}}, {}, Sev::noisy);
1385template <
int SPACE_DIM>
1392 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1393 boost::shared_ptr<MatrixDouble> jac,
1394 boost::shared_ptr<MatrixDouble> diff_jac,
1395 boost::shared_ptr<VectorDouble> cof_vals)
1397 jac(jac), diffJac(diff_jac), cofVals(cof_vals) {}
1401 boost::shared_ptr<MatrixDouble>
jac;
1407template <
int SPACE_DIM>
1419 auto t_diff_symm = FTensor::diff_symmetrize<double>();
1422 const double vol = OP::getMeasure();
1424 auto t_w = OP::getFTensor0IntegrationWeight();
1426 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(jac));
1428 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(diffJac));
1435 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(commPtr->matGradPtr));
1437 auto t_cauchy_stress =
1438 getFTensor2SymmetricFromMat<SPACE_DIM>(*(commPtr->getMatCauchyStress()));
1441 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
1443 for (
int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1445 const double alpha = t_w * vol;
1453 t_diff_inv_jac(
i,
j) =
1454 -(t_inv_jac(
i,
I) * t_diff_jac(
I,
J)) * t_inv_jac(
J,
j);
1456 t_diff_grad(
i,
j) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j);
1460 t_diff_strain(
i,
j) = t_diff_symm(
i,
j,
k,
l) * t_diff_grad(
k,
l);
1464 t_diff_stress(
i,
j) = t_D(
i,
j,
k,
l) * t_diff_strain(
k,
l);
1467 auto t_nf = OP::template getNf<SPACE_DIM>();
1470 for (; rr != OP::nbRows /
SPACE_DIM; rr++) {
1473 t_diff_row_grad(
k) = t_row_grad(
j) * t_diff_inv_jac(
j,
k);
1476 t_nf(
j) += alpha * t_diff_row_grad(
i) * t_cauchy_stress(
i,
j);
1479 t_nf(
j) += (alpha * t_cof) * t_row_grad(
i) * t_cauchy_stress(
i,
j);
1482 t_nf(
j) += alpha * t_row_grad(
i) * t_diff_stress(
i,
j);
1487 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1506 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
1507 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1508 boost::shared_ptr<MatrixDouble> u_ptr)
1520 auto nb_gauss_pts = getGaussPts().size2();
1522 auto objective_dstress =
1523 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
1524 auto objective_dstrain =
1525 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
1527 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
1529 auto evaluate_python = [&]() {
1531 auto &coords = OP::getCoordsAtGaussPts();
1542 auto vol = OP::getMeasure();
1543 auto t_w = OP::getFTensor0IntegrationWeight();
1546 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
1550 auto t_obj_dstress =
1551 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
1552 auto t_obj_dstrain =
1553 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
1554 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
1556 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
1557 const double alpha = t_w * vol;
1559 t_adjoint_stress(
i,
j) =
1560 t_D(
i,
j,
k,
l) * t_obj_dstress(
k,
l) + t_obj_dstrain(
i,
j);
1562 auto t_nf = OP::template getNf<SPACE_DIM>();
1565 t_nf(
j) += alpha * t_row_grad(
i) * t_adjoint_stress(
i,
j);
1566 t_nf(
j) += alpha * t_row_base * t_obj_du(
j);
1584 CHKERR evaluate_python();
1591 boost::shared_ptr<MatrixDouble>
uPtr;
1597 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1598 boost::shared_ptr<MatrixDouble> jac_ptr,
1599 boost::shared_ptr<MatrixDouble> diff_jac,
1600 boost::shared_ptr<VectorDouble> cof_vals,
1601 boost::shared_ptr<MatrixDouble> d_grad_ptr,
1602 boost::shared_ptr<MatrixDouble> d_u_ptr,
1603 boost::shared_ptr<MatrixDouble> u_ptr,
1604 boost::shared_ptr<double> glob_objective_ptr,
1605 boost::shared_ptr<double> glob_objective_grad_ptr)
1634 auto t_diff_symm = FTensor::diff_symmetrize<double>();
1638 getGaussPts().size2();
1639 auto objective_ptr = boost::make_shared<MatrixDouble>(
1641 auto objective_dstress = boost::make_shared<MatrixDouble>(
1644 auto objective_dstrain = boost::make_shared<MatrixDouble>(
1648 boost::make_shared<MatrixDouble>(nb_gauss_pts,
SPACE_DIM);
1651 auto evaluate_python = [&]() {
1653 auto &coords = OP::getCoordsAtGaussPts();
1668 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
commPtr->matGradPtr));
1670 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(
commPtr->matDPtr));
1671 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
jacPtr));
1672 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
diffJacPtr));
1674 auto t_d_grad = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(
dGradPtr));
1677 auto t_obj_dstress =
1678 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
1679 auto t_obj_dstrain =
1680 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
1681 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
1682 auto t_d_u = getFTensor1FromMat<SPACE_DIM>(*
dUPtr);
1684 auto vol = OP::getMeasure();
1685 auto t_w = getFTensor0IntegrationWeight();
1686 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
1693 t_diff_inv_jac(
i,
j) =
1694 -(t_inv_jac(
i,
I) * t_diff_jac(
I,
J)) * t_inv_jac(
J,
j);
1696 t_diff_grad(
i,
j) = t_grad_u(
i,
k) * t_diff_inv_jac(
k,
j);
1699 t_d_strain(
i,
j) = t_diff_symm(
i,
j,
k,
l) * (
1709 auto alpha = t_w * vol;
1711 (*globObjectivePtr) += alpha * t_obj;
1712 (*globObjectiveGradPtr) +=
1716 t_obj_dstress(
i,
j) * (t_D(
i,
j,
k,
l) * t_d_strain(
k,
l))
1720 t_obj_dstrain(
i,
j) * t_d_strain(
i,
j)
1724 t_obj_du(
i) * t_d_u(
i)
1749 CHKERR evaluate_python();
1762 boost::shared_ptr<MatrixDouble>
uPtr;
1769 Vec objective_function_gradient,
1770 Vec adjoint_vector) {
1777 auto get_essential_fe = [
this]() {
1778 auto post_proc_rhs = boost::make_shared<FEMethod>();
1779 auto get_post_proc_hook_rhs = [
this, post_proc_rhs]() {
1783 post_proc_rhs, 0)();
1786 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1787 return post_proc_rhs;
1790 auto get_fd_direvative_fe = [&]() {
1791 auto fe = boost::make_shared<DomainEle>(
mField);
1793 auto &pip = fe->getOpPtrVector();
1796 HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
1797 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1802 auto calulate_fd_residual = [&](
auto eps,
auto diff_vec,
auto fd_vec) {
1805 constexpr bool debug =
false;
1811 auto norm2_field = [&](
const double val) {
1816 MPI_Allreduce(MPI_IN_PLACE, &nrm2, 1, MPI_DOUBLE, MPI_SUM,
1818 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Geometry norm: " << sqrt(nrm2);
1822 if constexpr (
debug)
1828 initial_current_geometry, INSERT_VALUES, SCATTER_FORWARD);
1829 CHKERR VecAssemblyBegin(initial_current_geometry);
1830 CHKERR VecAssemblyEnd(initial_current_geometry);
1832 if constexpr (
debug)
1835 auto perturb_geometry = [&](
auto eps,
auto diff_vec) {
1838 CHKERR VecCopy(initial_current_geometry, current_geometry);
1839 CHKERR VecAXPY(current_geometry,
eps, diff_vec);
1842 current_geometry, INSERT_VALUES, SCATTER_REVERSE);
1846 auto fe = get_fd_direvative_fe();
1849 auto calc_impl = [&](
auto f,
auto eps) {
1851 CHKERR VecZeroEntries(f);
1856 CHKERR VecAssemblyBegin(f);
1857 CHKERR VecAssemblyEnd(f);
1858 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
1859 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
1860 auto post_proc_rhs = get_essential_fe();
1861 post_proc_rhs->f = f;
1863 post_proc_rhs.get());
1868 CHKERR VecWAXPY(fd_vec, -1.0, fm, fp);
1869 CHKERR VecScale(fd_vec, 1.0 / (2.0 *
eps));
1873 initial_current_geometry, INSERT_VALUES, SCATTER_REVERSE);
1875 if constexpr (
debug)
1881 auto get_direvative_fe = [&](
auto diff_vec) {
1882 auto fe_adjoint = boost::make_shared<DomainEle>(
mField);
1884 auto &pip = fe_adjoint->getOpPtrVector();
1886 auto jac_ptr = boost::make_shared<MatrixDouble>();
1887 auto det_ptr = boost::make_shared<VectorDouble>();
1888 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1889 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
1890 auto cof_ptr = boost::make_shared<VectorDouble>();
1898 "GEOMETRY", jac_ptr));
1900 "U", diff_jac_ptr, diff_vec));
1902 pip.push_back(
new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
1905 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1906 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1908 "U", common_ptr, jac_ptr, diff_jac_ptr, cof_ptr));
1913 auto get_objective_fe = [&](
auto diff_vec,
auto grad_vec,
1914 auto glob_objective_ptr,
1915 auto glob_objective_grad_ptr) {
1916 auto fe_adjoint = boost::make_shared<DomainEle>(
mField);
1918 auto &pip = fe_adjoint->getOpPtrVector();
1921 auto jac_ptr = boost::make_shared<MatrixDouble>();
1922 auto det_ptr = boost::make_shared<VectorDouble>();
1923 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1924 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
1925 auto cof_ptr = boost::make_shared<VectorDouble>();
1926 auto d_grad_ptr = boost::make_shared<MatrixDouble>();
1927 auto d_u_ptr = boost::make_shared<MatrixDouble>();
1928 auto u_ptr = boost::make_shared<MatrixDouble>();
1933 "GEOMETRY", jac_ptr));
1938 pip.push_back(
new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
1940 "U", d_grad_ptr, grad_vec));
1945 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1946 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
1948 pythonPtr, common_ptr, jac_ptr, diff_jac_ptr, cof_ptr, d_grad_ptr,
1949 d_u_ptr, u_ptr, glob_objective_ptr, glob_objective_grad_ptr));
1960 CHKERR VecZeroEntries(zero_diff_vec);
1961 CHKERR VecZeroEntries(zero_state_sensitivity);
1962 CHKERR VecGhostUpdateBegin(zero_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1963 CHKERR VecGhostUpdateEnd(zero_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1964 CHKERR VecGhostUpdateBegin(zero_state_sensitivity, INSERT_VALUES,
1966 CHKERR VecGhostUpdateEnd(zero_state_sensitivity, INSERT_VALUES,
1969 auto adjoint_fe = get_direvative_fe(dm_diff_vec);
1970 auto objective_ptr_direct = boost::make_shared<double>(0.0);
1971 auto objective_grad_ptr_direct = boost::make_shared<double>(0.0);
1972 auto objective_fe_direct = get_objective_fe(
1973 dm_diff_vec, d, objective_ptr_direct, objective_grad_ptr_direct);
1974 auto objective_ptr_explicit = boost::make_shared<double>(0.0);
1975 auto objective_grad_ptr_explicit = boost::make_shared<double>(0.0);
1976 auto objective_fe_explicit =
1977 get_objective_fe(dm_diff_vec, zero_state_sensitivity,
1978 objective_ptr_explicit, objective_grad_ptr_explicit);
1979 auto objective_ptr_value = boost::make_shared<double>(0.0);
1980 auto objective_grad_ptr_value = boost::make_shared<double>(0.0);
1981 auto objective_fe_value =
1982 get_objective_fe(zero_diff_vec, zero_state_sensitivity,
1983 objective_ptr_value, objective_grad_ptr_value);
1985 auto set_variance_of_geometry =
1986 [&](
auto mode,
auto mod_vec) {
1994 dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1995 CHKERR VecGhostUpdateBegin(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1996 CHKERR VecGhostUpdateEnd(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
2000 auto calculate_variance_internal_forces = [&](
auto mode,
auto mod_vec) {
2002 CHKERR VecZeroEntries(f);
2003 CHKERR VecGhostUpdateBegin(f, INSERT_VALUES, SCATTER_FORWARD);
2004 CHKERR VecGhostUpdateEnd(f, INSERT_VALUES, SCATTER_FORWARD);
2007 CHKERR VecAssemblyBegin(f);
2008 CHKERR VecAssemblyEnd(f);
2009 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
2010 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
2011 auto post_proc_rhs = get_essential_fe();
2012 post_proc_rhs->f = f;
2014 post_proc_rhs.get());
2015 CHKERR VecScale(f, -1.0);
2018 constexpr bool debug =
true;
2019 if constexpr (
debug) {
2021 CHKERR VecNorm(f, NORM_2, &norm0);
2024 CHKERR calulate_fd_residual(
eps, dm_diff_vec, fd_check);
2026 CHKERR VecAXPY(fd_check, -1.0, f);
2027 CHKERR VecNorm(fd_check, NORM_2, &nrm);
2029 <<
" FD check for internal forces [ " << mode <<
" ]: " << nrm
2030 <<
" / " << norm0 <<
" ( " << (nrm / norm0) <<
" )";
2037 auto calculate_variance_of_displacement = [&](
auto mode,
auto mod_vec) {
2041 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
2042 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
2046 auto evaluate_objective_terms =
2047 [&](
auto objective_fe,
auto objective_ptr,
auto objective_grad_ptr,
2048 double &objective_value,
double &objective_gradient) {
2050 *objective_ptr = 0.0;
2051 *objective_grad_ptr = 0.0;
2054 std::array<double, 2> array = {*objective_ptr, *objective_grad_ptr};
2055 MPI_Allreduce(MPI_IN_PLACE, array.data(), 2, MPI_DOUBLE, MPI_SUM,
2057 objective_value = array[0];
2058 objective_gradient = array[1];
2062 auto calculate_objective_value = [&]() {
2064 double objective_value = 0;
2065 double objective_gradient = 0;
2066 CHKERR evaluate_objective_terms(objective_fe_value, objective_ptr_value,
2067 objective_grad_ptr_value, objective_value,
2068 objective_gradient);
2069 *objective_function_value = objective_value;
2073 auto calculate_variance_of_objective_function_dJ_du = [&](Vec dJ_du) {
2076 auto fe = boost::make_shared<DomainEle>(
mField);
2078 auto &pip = fe->getOpPtrVector();
2081 auto u_ptr = boost::make_shared<MatrixDouble>();
2084 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
2085 mField, pip,
"U",
"MAT_ELASTIC", Sev::noisy);
2088 CHKERR VecZeroEntries(dJ_du);
2091 CHKERR VecAssemblyBegin(dJ_du);
2092 CHKERR VecAssemblyEnd(dJ_du);
2094 auto post_proc_rhs = get_essential_fe();
2095 post_proc_rhs->f = dJ_du;
2097 post_proc_rhs.get());
2102 auto calculate_adjoint_lambda = [&](
auto lambda,
auto dJ_du) {
2105 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Solving for adjoint variable lambda";
2108 CHKERR VecGhostUpdateBegin(
lambda, INSERT_VALUES, SCATTER_FORWARD);
2109 CHKERR VecGhostUpdateEnd(
lambda, INSERT_VALUES, SCATTER_FORWARD);
2113 CHKERR VecZeroEntries(objective_function_gradient);
2114 CHKERR VecZeroEntries(adjoint_vector);
2116 CHKERR calculate_objective_value();
2118 <<
"Objective function: " << *objective_function_value;
2120 auto direct = [&]() {
2124 CHKERR set_variance_of_geometry(mode, mod_vec);
2125 CHKERR calculate_variance_internal_forces(mode, mod_vec);
2126 CHKERR calculate_variance_of_displacement(mode, mod_vec);
2127 double objective_value = 0;
2128 double objective_gradient = 0;
2129 CHKERR evaluate_objective_terms(objective_fe_direct, objective_ptr_direct,
2130 objective_grad_ptr_direct,
2131 objective_value, objective_gradient);
2132 CHKERR VecSetValue(objective_function_gradient, mode, objective_gradient,
2134 CHKERR VecAXPY(adjoint_vector, objective_gradient, dm_diff_vec);
2143 auto adjoint = [&]() {
2146 CHKERR calculate_variance_of_objective_function_dJ_du(dJ_du);
2153 CHKERR set_variance_of_geometry(mode, mod_vec);
2154 CHKERR calculate_variance_internal_forces(mode, mod_vec);
2155 double objective_value = 0;
2156 double objective_gradient_explicit = 0;
2157 CHKERR evaluate_objective_terms(
2158 objective_fe_explicit, objective_ptr_explicit,
2159 objective_grad_ptr_explicit, objective_value,
2160 objective_gradient_explicit);
2161 double lambda_dot_residual_variation = 0;
2162 CHKERR VecDot(
lambda, f, &lambda_dot_residual_variation);
2163 const double dJ_dp =
2164 objective_gradient_explicit + lambda_dot_residual_variation;
2165 CHKERR VecSetValue(objective_function_gradient, mode, dJ_dp,
2167 CHKERR VecAXPY(adjoint_vector, dJ_dp, dm_diff_vec);
2170 CHKERR VecAssemblyBegin(objective_function_gradient);
2171 CHKERR VecAssemblyEnd(objective_function_gradient);
2177 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Direct Sensitivity...";
2182 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Running Adjoint Sensitivity...";
2188 "Wrong sensitivity type selected");
2191 CHKERR VecAssemblyBegin(objective_function_gradient);
2192 CHKERR VecAssemblyEnd(objective_function_gradient);
2194 CHKERR VecAssemblyBegin(adjoint_vector);
2195 CHKERR VecAssemblyEnd(adjoint_vector);
2196 CHKERR VecGhostUpdateBegin(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2197 CHKERR VecGhostUpdateEnd(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2242 const char param_file[] =
"param_file.petsc";
2245 auto core_log = logging::core::get();
2257 DMType dm_name =
"DMMOFEM";
2259 DMType dm_name_mg =
"DMMOFEM_MG";
2264 moab::Core mb_instance;
2265 moab::Interface &moab = mb_instance;
2283 if (Py_FinalizeEx() < 0) {
2289 const std::string block_name,
int dim) {
2295 std::regex((boost::format(
"%s(.*)") % block_name).str())
2299 for (
auto bc : bcs) {
2303 "get meshset ents");
2307 for (
auto dd = dim - 1; dd >= 0; --dd) {
2311 moab::Interface::UNION),
2331 CHKERR moab.add_entities(*out_meshset, r);
2332 CHKERR moab.write_file(
name.c_str(),
"VTK",
"", out_meshset->get_ptr(), 1);
Calculate traction for linear problem.
Implementation of elastic spring bc.
Natural boundary condition applying pressure from fluid.
Implementation of Hookes operator Hookes for linear elastic problems in MoFEM.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
Implementation of natural boundary conditions.
Boundary conditions in domain, i.e. body forces.
Interface for Python-based objective function evaluation in topology optimization.
#define FTENSOR_INDEX(DIM, I)
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ν))
FormsIntegrators< DomainEleOp >::Assembly< A >::OpBase DomainBaseOp
[Postprocess results]
constexpr AssemblyType A
[Define dimension]
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::BoundaryEle BoundaryEle
Boundary finite elements.
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
constexpr double young_modulus
[Material properties for linear elasticity]
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
PetscBool is_plane_strain
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle DomainEle
Domain finite elements.
constexpr int SPACE_DIM
[Define dimension]
PostProcEleByDim< SPACE_DIM >::SideEle SideEle
SensitivityMethod derivative_type
constexpr IntegrationType I
Use Gauss quadrature for integration.
FormsIntegrators< DomainEleOp >::Assembly< A >::OpBase DomainBaseOp
[Postprocess results]
constexpr AssemblyType A
[Define dimension]
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::BoundaryEle BoundaryEle
Boundary finite elements.
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
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
MoFEMErrorCode TestingInterface::checkValue< TestType::DERIVATIVE >(const std::string &check_name, PetscReal actual, PetscReal expected, Tolerance tolerance, Sev error_severity, Sev success_severity) const
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 PetscOptionsGetReal(PetscOptions *, const char pre[], const char name[], PetscReal *dval, PetscBool *set)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PetscErrorCode PetscOptionsGetRealArray(PetscOptions *, const char pre[], const char name[], PetscReal dval[], PetscInt *nmax, PetscBool *set)
auto 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)
auto createGhostVector(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt nghost, const PetscInt ghosts[])
Create smart ghost vector.
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)
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
#define EXECUTABLE_DIMENSION
PetscBool do_eval_field
Evaluate field.
ElementsAndOps< SPACE_DIM >::SideEle SideEle
constexpr auto field_name
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.
static int integrationRule(int, int, int p_data)
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.
static int integrationRule(int, int, int order)
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.
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.
int nbRows
number of dofs on rows
int nbRowBaseFunctions
number or row base functions
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for MatrixDouble vector field values calculation.
Post post-proc data at points from hash maps.
Calculate directional derivative of the right hand side and compare it with tangent matrix derivative...
Template struct for dimension-specific finite element types.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
Problem manager is used to build and partition problems.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
EntityHandle & getMeshset()
Get the MeshSet object.
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
MoFEMErrorCode addBoundaryField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on boundary.
MoFEMErrorCode getOptions()
get options
MoFEMErrorCode getDM(DM *dm)
Get DM.
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
BitRefLevel & getBitRefLevelMask()
Get the BitRefLevelMask.
MoFEMErrorCode addDataField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add data field.
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
const std::string getProblemName() const
Get the Problem Name.
const std::string getDomainFEName() const
Get the Domain FE Name.
BitRefLevel & getBitRefLevel()
Get the BitRefLevel.
intrusive_ptr for managing petsc objects
virtual MoFEMErrorCode addTestCommandLine(const std::string &prefix, int number, const std::string &name, TestHook hook)=0
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
boost::shared_ptr< 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)
Class dedicated to integrate operator.
boost::shared_ptr< MatrixDouble > uPtr
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle