8#include <boost/python.hpp>
9#include <boost/python/def.hpp>
10#include <boost/python/numpy.hpp>
11namespace bp = boost::python;
12namespace np = boost::python::numpy;
73 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
74 boost::shared_ptr<MatrixDouble> stress_ptr,
75 boost::shared_ptr<MatrixDouble> strain_ptr,
76 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize =
true);
93 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
94 boost::shared_ptr<MatrixDouble> stress_ptr,
95 boost::shared_ptr<MatrixDouble> strain_ptr,
96 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize =
true);
113 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
114 boost::shared_ptr<MatrixDouble> stress_ptr,
115 boost::shared_ptr<MatrixDouble> strain_ptr,
116 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize =
true);
133 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
134 boost::shared_ptr<MatrixDouble> stress_ptr,
135 boost::shared_ptr<MatrixDouble> strain_ptr,
136 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize =
true);
140 boost::shared_ptr<MatrixDouble> u_ptr,
141 boost::shared_ptr<MatrixDouble> t_ptr,
142 boost::shared_ptr<VectorDouble> o_ptr,
143 bool symmetrize =
true);
147 boost::shared_ptr<MatrixDouble> u_ptr,
148 boost::shared_ptr<MatrixDouble> t_ptr,
149 boost::shared_ptr<MatrixDouble> o_ptr);
153 boost::shared_ptr<MatrixDouble> u_ptr,
154 boost::shared_ptr<MatrixDouble> t_ptr,
155 boost::shared_ptr<MatrixDouble> o_ptr);
175 std::array<double, 3> ¢roid,
198 np::ndarray coords, np::ndarray u,
200 np::ndarray stress, np::ndarray strain, np::ndarray &o
219 np::ndarray coords, np::ndarray u,
221 np::ndarray stress, np::ndarray strain, np::ndarray &o
240 np::ndarray coords, np::ndarray u,
242 np::ndarray stress, np::ndarray strain, np::ndarray &o
262 np::ndarray coords, np::ndarray u,
264 np::ndarray stress, np::ndarray strain, np::ndarray &o
270 np::ndarray coords, np::ndarray u,
272 np::ndarray
t, np::ndarray &o
278 np::ndarray coords, np::ndarray u,
280 np::ndarray
t, np::ndarray &o
286 np::ndarray coords, np::ndarray u,
288 np::ndarray
t, np::ndarray &o
308 int block_id, np::ndarray coords, np::ndarray centroid, np::ndarray bbodx,
366boost::shared_ptr<ObjectiveFunctionData>
368 auto ptr = boost::make_shared<ObjectiveFunctionDataImpl>();
402 auto main_module = bp::import(
"__main__");
410 }
catch (bp::error_already_set
const &) {
419 const auto nb_gauss_pts = s.size1();
427 auto t_s = getFTensor2SymmetricFromMat<SPACE_DIM>(s);
428 for (
size_t ii = 0; ii != nb_gauss_pts; ++ii) {
429 t_f(
i,
j) = t_s(
i,
j);
437 const auto nb_gauss_pts = s.size1();
444 auto t_s = getFTensor2SymmetricFromMat<SPACE_DIM>(s);
445 for (
size_t ii = 0; ii != nb_gauss_pts; ++ii) {
446 t_s(
i,
j) = (t_f(
i,
j) || t_f(
j,
i)) / 2.0;
480 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
481 boost::shared_ptr<MatrixDouble> stress_ptr,
482 boost::shared_ptr<MatrixDouble> strain_ptr,
483 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize) {
491 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
495 auto full_stress = symmetrize ?
copyToFull(*(stress_ptr)) : *(stress_ptr);
496 auto full_strain = symmetrize ?
copyToFull(*(strain_ptr)) : *(strain_ptr);
499 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
500 full_stress.size2());
501 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
502 full_strain.size2());
505 const auto nb_gauss_pts = full_strain.size1();
506 np::ndarray np_output =
507 np::empty(bp::make_tuple(nb_gauss_pts), np::dtype::get_builtin<double>());
514 if (np_output.get_nd() != 1 || np_output.get_shape()[0] != nb_gauss_pts) {
517 "Wrong shape of Objective Function from python expected (" +
518 std::to_string(nb_gauss_pts) +
"), got (" +
519 std::to_string(np_output.get_shape()[0]) +
")");
523 o_ptr->resize(1, nb_gauss_pts,
false);
524 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
525 std::copy(val_ptr, val_ptr + nb_gauss_pts, o_ptr->data().begin());
527 }
catch (bp::error_already_set
const &) {
566 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
567 boost::shared_ptr<MatrixDouble> stress_ptr,
568 boost::shared_ptr<MatrixDouble> strain_ptr,
569 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize) {
576 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
579 auto full_stress = symmetrize ?
copyToFull(*(stress_ptr)) : *(stress_ptr);
580 auto full_strain = symmetrize ?
copyToFull(*(strain_ptr)) : *(strain_ptr);
583 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
584 full_stress.size2());
585 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
586 full_strain.size2());
588 np::ndarray np_output =
589 np::empty(bp::make_tuple(full_strain.size1(), full_strain.size2()),
590 np::dtype::get_builtin<double>());
597 if (np_output.get_shape()[0] != full_strain.size1() ||
598 np_output.get_shape()[1] != full_strain.size2()) {
601 "Wrong shape of Objective Gradient from python expected (" +
602 std::to_string(full_strain.size1()) +
", " +
603 std::to_string(full_strain.size2()) +
"), got (" +
604 std::to_string(np_output.get_shape()[0]) +
", " +
605 std::to_string(np_output.get_shape()[1]) +
")");
609 o_ptr->resize(stress_ptr->size1(), stress_ptr->size2(),
false);
611 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
615 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
616 std::copy(val_ptr, val_ptr + stress_ptr->size1() * stress_ptr->size2(),
617 o_ptr->data().begin());
620 }
catch (bp::error_already_set
const &) {
660 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
661 boost::shared_ptr<MatrixDouble> stress_ptr,
662 boost::shared_ptr<MatrixDouble> strain_ptr,
663 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize) {
670 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
673 auto full_stress = symmetrize ?
copyToFull(*(stress_ptr)) : *(stress_ptr);
674 auto full_strain = symmetrize ?
copyToFull(*(strain_ptr)) : *(strain_ptr);
676 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
677 full_stress.size2());
678 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
679 full_strain.size2());
682 np::ndarray np_output =
683 np::empty(bp::make_tuple(full_strain.size1(), full_strain.size2()),
684 np::dtype::get_builtin<double>());
691 if (np_output.get_shape()[0] != full_strain.size1() ||
692 np_output.get_shape()[1] != full_strain.size2()) {
695 "Wrong shape of Objective Gradient from python expected (" +
696 std::to_string(full_strain.size1()) +
", " +
697 std::to_string(full_strain.size2()) +
"), got (" +
698 std::to_string(np_output.get_shape()[0]) +
", " +
699 std::to_string(np_output.get_shape()[1]) +
")");
702 o_ptr->resize(strain_ptr->size1(), strain_ptr->size2(),
false);
704 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
707 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
708 std::copy(val_ptr, val_ptr + strain_ptr->size1() * strain_ptr->size2(),
709 o_ptr->data().begin());
712 }
catch (bp::error_already_set
const &) {
754 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
755 boost::shared_ptr<MatrixDouble> stress_ptr,
756 boost::shared_ptr<MatrixDouble> strain_ptr,
757 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize) {
764 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
767 auto full_stress = symmetrize ?
copyToFull(*(stress_ptr)) : *(stress_ptr);
768 auto full_strain = symmetrize ?
copyToFull(*(strain_ptr)) : *(strain_ptr);
770 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
771 full_stress.size2());
772 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
773 full_strain.size2());
776 np::ndarray np_output =
777 np::empty(bp::make_tuple(u_ptr->size1(), u_ptr->size2()),
778 np::dtype::get_builtin<double>());
786 if (np_output.get_shape()[0] != u_ptr->size1() ||
787 np_output.get_shape()[1] != u_ptr->size2()) {
790 "Wrong shape of Objective Gradient from python expected (" +
791 std::to_string(u_ptr->size1()) +
", " +
792 std::to_string(u_ptr->size2()) +
"), got (" +
793 std::to_string(np_output.get_shape()[0]) +
", " +
794 std::to_string(np_output.get_shape()[1]) +
")");
798 o_ptr->resize(u_ptr->size1(), u_ptr->size2(),
false);
799 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
800 std::copy(val_ptr, val_ptr + u_ptr->size1() * u_ptr->size2(),
801 o_ptr->data().begin());
803 }
catch (bp::error_already_set
const &) {
812 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
813 boost::shared_ptr<MatrixDouble> t_ptr,
814 boost::shared_ptr<MatrixDouble> o_ptr) {
820 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
821 auto np_t =
convertToNumPy(t_ptr->data(), t_ptr->size1(), t_ptr->size2());
823 np::ndarray np_output =
824 np::empty(bp::make_tuple(u_ptr->size1(), u_ptr->size2()),
825 np::dtype::get_builtin<double>());
830 if (np_output.get_shape()[0] != u_ptr->size1() ||
831 np_output.get_shape()[1] != u_ptr->size2()) {
834 "Wrong shape of Objective Gradient from python expected (" +
835 std::to_string(u_ptr->size1()) +
", " +
836 std::to_string(u_ptr->size2()) +
"), got (" +
837 std::to_string(np_output.get_shape()[0]) +
", " +
838 std::to_string(np_output.get_shape()[1]) +
")");
841 o_ptr->resize(u_ptr->size1(), u_ptr->size2(),
false);
842 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
843 std::copy(val_ptr, val_ptr + u_ptr->size1() * u_ptr->size2(),
844 o_ptr->data().begin());
846 }
catch (bp::error_already_set
const &) {
854 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
855 boost::shared_ptr<MatrixDouble> t_ptr,
856 boost::shared_ptr<VectorDouble> o_ptr,
bool symmetrize) {
863 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
864 auto np_t =
convertToNumPy(t_ptr->data(), t_ptr->size1(), t_ptr->size2());
866 np::ndarray np_output = np::empty(bp::make_tuple(t_ptr->size2()),
867 np::dtype::get_builtin<double>());
872 if (np_output.get_nd() != 1 || np_output.get_shape()[0] != t_ptr->size2()) {
875 "Wrong shape of Objective Function from python expected (" +
876 std::to_string(t_ptr->size2()) +
"), got (" +
877 std::to_string(np_output.get_shape()[0]) +
")");
880 o_ptr->resize(t_ptr->size2(),
false);
881 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
882 std::copy(val_ptr, val_ptr + t_ptr->size2(), o_ptr->data().begin());
884 }
catch (bp::error_already_set
const &) {
892 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
893 boost::shared_ptr<MatrixDouble> t_ptr,
894 boost::shared_ptr<MatrixDouble> o_ptr) {
899 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
900 auto np_t =
convertToNumPy(t_ptr->data(), t_ptr->size1(), t_ptr->size2());
902 np::ndarray np_output =
903 np::empty(bp::make_tuple(u_ptr->size1(), u_ptr->size2()),
904 np::dtype::get_builtin<double>());
909 if (np_output.get_shape()[0] != u_ptr->size1() ||
910 np_output.get_shape()[1] != u_ptr->size2()) {
913 "Wrong shape of Objective Gradient from python expected (" +
914 std::to_string(u_ptr->size1()) +
", " +
915 std::to_string(u_ptr->size2()) +
"), got (" +
916 std::to_string(np_output.get_shape()[0]) +
", " +
917 std::to_string(np_output.get_shape()[1]) +
")");
920 o_ptr->resize(u_ptr->size1(), u_ptr->size2(),
false);
921 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
922 std::copy(val_ptr, val_ptr + u_ptr->size1() * u_ptr->size2(),
923 o_ptr->data().begin());
925 }
catch (bp::error_already_set
const &) {
968 int block_id,
MatrixDouble &coords, std::array<double, 3> ¢roid,
988 np::ndarray np_output =
989 np::empty(bp::make_tuple(nb_modes, coords.size1(), coords.size2()),
990 np::dtype::get_builtin<double>());
997 if (np_output.get_shape()[0] != nb_modes ||
998 np_output.get_shape()[1] != coords.size1() ||
999 np_output.get_shape()[2] != coords.size2()) {
1001 "Wrong shape of Modes from python expected (" +
1002 std::to_string(nb_modes) +
", " +
1003 std::to_string(coords.size1()) +
", " +
1004 std::to_string(coords.size2()) +
"), got (" +
1005 std::to_string(np_output.get_shape()[0]) +
", " +
1006 std::to_string(np_output.get_shape()[1]) +
", " +
1007 std::to_string(np_output.get_shape()[2]) +
")");
1011 o_ptr.resize(nb_modes, coords.size1() * coords.size2(),
false);
1012 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
1014 std::copy(val_ptr, val_ptr + coords.size1() * coords.size2() * nb_modes,
1015 o_ptr.data().begin());
1017 }
catch (bp::error_already_set
const &) {
1027 np::ndarray coords, np::ndarray u,
1029 np::ndarray stress, np::ndarray strain, np::ndarray &o
1035 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f"))) {
1037 o = bp::extract<np::ndarray>(
1039 }
else if (bp::extract<bool>(
1041 o = bp::extract<np::ndarray>(
1046 "Python function f_interior(coords,u,stress,strain) is not defined");
1049 }
catch (bp::error_already_set
const &) {
1059 np::ndarray coords, np::ndarray u,
1061 np::ndarray stress, np::ndarray strain, np::ndarray &o
1067 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_stress"))) {
1069 o = bp::extract<np::ndarray>(
1071 }
else if (bp::extract<bool>(
1073 o = bp::extract<np::ndarray>(
1074 mainNamespace[
"f_interior_stress"](coords, u, stress, strain));
1078 "Python function f_interior_stress(coords,u,stress,strain) is not defined");
1081 }
catch (bp::error_already_set
const &) {
1091 np::ndarray coords, np::ndarray u,
1093 np::ndarray stress, np::ndarray strain, np::ndarray &o
1099 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_strain"))) {
1101 o = bp::extract<np::ndarray>(
1103 }
else if (bp::extract<bool>(
1105 o = bp::extract<np::ndarray>(
1106 mainNamespace[
"f_interior_strain"](coords, u, stress, strain));
1110 "Python function f_interior_strain(coords,u,stress,strain) is not defined");
1113 }
catch (bp::error_already_set
const &) {
1123 np::ndarray coords, np::ndarray u,
1125 np::ndarray stress, np::ndarray strain, np::ndarray &o
1131 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_u"))) {
1133 o = bp::extract<np::ndarray>(
1135 }
else if (bp::extract<bool>(
1137 o = bp::extract<np::ndarray>(
1142 "Python function f_interior_u(coords,u,stress,strain) is not defined");
1145 }
catch (bp::error_already_set
const &) {
1155 np::ndarray coords, np::ndarray u,
1157 np::ndarray
t, np::ndarray &o
1163 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_boundary_t"))) {
1164 o = bp::extract<np::ndarray>(
mainNamespace[
"f_boundary_t"](coords, u,
t));
1168 "Python function f_boundary_t(coords,u,t) is not defined");
1171 }
catch (bp::error_already_set
const &) {
1180 np::ndarray coords, np::ndarray u,
1182 np::ndarray
t, np::ndarray &o
1188 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_boundary"))) {
1189 o = bp::extract<np::ndarray>(
mainNamespace[
"f_boundary"](coords, u,
t));
1190 }
else if (bp::extract<bool>(
1191 mainNamespace.attr(
"__contains__")(
"f_boundary_function"))) {
1192 o = bp::extract<np::ndarray>(
1197 "Python function f_boundary(coords,u,t) is not defined");
1200 }
catch (bp::error_already_set
const &) {
1209 np::ndarray coords, np::ndarray u,
1211 np::ndarray
t, np::ndarray &o
1217 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_boundary_u"))) {
1218 o = bp::extract<np::ndarray>(
mainNamespace[
"f_boundary_u"](coords, u,
t));
1222 "Python function f_boundary_u(coords,u,t) is not defined");
1225 }
catch (bp::error_already_set
const &) {
1237 if (bp::extract<bool>(
1239 modes = bp::extract<int>(
mainNamespace[
"number_of_modes"](block_id));
1243 "Python function number_of_modes(block_id) is not defined");
1246 }
catch (bp::error_already_set
const &) {
1256 np::ndarray centroid,
1261 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"block_modes"))) {
1262 o = bp::extract<np::ndarray>(
1263 mainNamespace[
"block_modes"](block_id, coords, centroid, bbodx));
1267 "Python function block_modes(block_id,coords,centroid,bbox) is not "
1270 }
catch (bp::error_already_set
const &) {
1301 auto dtype = np::dtype::get_builtin<double>();
1302 auto size = bp::make_tuple(rows, nb_gauss_pts);
1303 auto stride = bp::make_tuple(nb_gauss_pts *
sizeof(
double),
sizeof(
double));
1304 return (np::from_data(data.data(), dtype, size, stride, bp::object()));
1309 auto dtype = np::dtype::get_builtin<double>();
1310 auto size = bp::make_tuple(s);
1311 auto stride = bp::make_tuple(
sizeof(
double));
1312 return (np::from_data(ptr, dtype, size, stride, bp::object()));
Interface for Python-based objective function evaluation in topology optimization.
#define FTENSOR_INDEX(DIM, I)
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_OPERATION_UNSUCCESSFUL
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
auto getFTensor2FromMat(M &data)
Get tensor rank 2 (matrix) form data matrix.
auto getFTensor2FromPtr(double *ptr)
constexpr int SPACE_DIM
Space dimension of problem (2D or 3D), set at compile time.
boost::shared_ptr< ObjectiveFunctionData > create_python_objective_function(std::string py_file)
Factory function to create Python-integrated objective function interface.
constexpr double t
plate stiffness
Implementation of ObjectiveFunctionData interface using Python integration.
MoFEMErrorCode blockModesImpl(int block_id, np::ndarray coords, np::ndarray centroid, np::ndarray bbodx, np::ndarray &o_ptr)
Internal implementation for topology mode generation.
MoFEMErrorCode boundaryObjectiveFunctionImpl(np::ndarray coords, np::ndarray u, np::ndarray t, np::ndarray &o)
virtual ~ObjectiveFunctionDataImpl()=default
MoFEMErrorCode evalBoundaryObjectiveGradientTraction(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > t_ptr, boost::shared_ptr< MatrixDouble > o_ptr)
Evaluate gradient of objective function w.r.t. traction-like vector field.
MoFEMErrorCode boundaryObjectiveGradientUImpl(np::ndarray coords, np::ndarray u, np::ndarray t, np::ndarray &o)
MoFEMErrorCode evalInteriorObjectiveFunction(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr, bool symmetrize=true)
Evaluate objective function at current state.
bp::object mainNamespace
Main Python namespace for script execution.
MoFEMErrorCode interiorObjectiveGradientStrainImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Internal implementation for strain gradient computation.
MoFEMErrorCode initPython(const std::string py_file)
Initialize Python interpreter and load objective function script.
MoFEMErrorCode interiorObjectiveFunctionImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Internal implementation for objective function evaluation.
void copyToSymmetric(double *ptr, MatrixDouble &s)
Convert full matrix to symmetric tensor storage format.
MoFEMErrorCode evalInteriorObjectiveGradientStrain(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr, bool symmetrize=true)
Compute gradient of objective function with respect to strain.
MoFEMErrorCode blockModes(int block_id, MatrixDouble &coords, std::array< double, 3 > ¢roid, std::array< double, 6 > &bbodx, MatrixDouble &o_ptr)
Define spatial topology modes for design optimization.
MoFEMErrorCode evalBoundaryObjectiveFunction(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > t_ptr, boost::shared_ptr< VectorDouble > o_ptr, bool symmetrize=true)
np::ndarray convertToNumPy(std::vector< double > &data, int rows, int nb_gauss_pts)
Convert std::vector to NumPy array for Python interface.
MatrixDouble copyToFull(MatrixDouble &s)
Convert symmetric tensor storage to full matrix format.
MoFEMErrorCode interiorObjectiveGradientUImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Internal implementation for displacement gradient computation.
ObjectiveFunctionDataImpl()=default
MoFEMErrorCode numberOfModes(int block_id, int &modes)
Return number of topology optimization modes for given material block.
MoFEMErrorCode evalInteriorObjectiveGradientU(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr, bool symmetrize=true)
Compute gradient of objective function with respect to displacement.
MoFEMErrorCode interiorObjectiveGradientStressImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Internal implementation for stress gradient computation.
MoFEMErrorCode evalInteriorObjectiveGradientStress(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr, bool symmetrize=true)
Compute gradient of objective function with respect to stress.
MoFEMErrorCode evalBoundaryObjectiveGradientU(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > t_ptr, boost::shared_ptr< MatrixDouble > o_ptr)
MoFEMErrorCode boundaryObjectiveGradientTractionImpl(np::ndarray coords, np::ndarray u, np::ndarray t, np::ndarray &o)
Abstract interface for Python-defined objective functions.
#define EXECUTABLE_DIMENSION