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<VectorDouble> 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 &) {
423 auto t_f = getFTensor2FromMat<3, 3>(f);
424 auto t_s = getFTensor2SymmetricFromMat<SPACE_DIM>(s);
425 for (
int ii = 0; ii != s.size2(); ++ii) {
426 t_f(
i,
j) = t_s(
i,
j);
438 ptr + 0 * s.size2(), ptr + 1 * s.size2(),
439 ptr + 2 * s.size2(), ptr + 3 * s.size2(),
440 ptr + 4 * s.size2(), ptr + 5 * s.size2(),
441 ptr + 6 * s.size2(), ptr + 7 * s.size2(),
445 auto t_s = getFTensor2SymmetricFromMat<SPACE_DIM>(s);
446 for (
int ii = 0; ii != s.size2(); ++ii) {
447 t_s(
i,
j) = (t_f(
i,
j) || t_f(
j,
i)) / 2.0;
481 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
482 boost::shared_ptr<MatrixDouble> stress_ptr,
483 boost::shared_ptr<MatrixDouble> strain_ptr,
484 boost::shared_ptr<VectorDouble> o_ptr,
bool symmetrize) {
492 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
496 auto full_stress = symmetrize ?
copyToFull(*(stress_ptr)) : *(stress_ptr);
497 auto full_strain = symmetrize ?
copyToFull(*(strain_ptr)) : *(strain_ptr);
500 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
501 full_stress.size2());
502 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
503 full_strain.size2());
506 np::ndarray np_output = np::empty(bp::make_tuple(strain_ptr->size2()),
507 np::dtype::get_builtin<double>());
514 if (np_output.get_nd() != 1 ||
515 np_output.get_shape()[0] != strain_ptr->size2()) {
518 "Wrong shape of Objective Function from python expected (" +
519 std::to_string(strain_ptr->size2()) +
"), got (" +
520 std::to_string(np_output.get_shape()[0]) +
")");
524 o_ptr->resize(stress_ptr->size2(),
false);
525 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
526 std::copy(val_ptr, val_ptr + strain_ptr->size2(), o_ptr->data().begin());
528 }
catch (bp::error_already_set
const &) {
567 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
568 boost::shared_ptr<MatrixDouble> stress_ptr,
569 boost::shared_ptr<MatrixDouble> strain_ptr,
570 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize) {
577 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
580 auto full_stress = symmetrize ?
copyToFull(*(stress_ptr)) : *(stress_ptr);
581 auto full_strain = symmetrize ?
copyToFull(*(strain_ptr)) : *(strain_ptr);
584 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
585 full_stress.size2());
586 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
587 full_strain.size2());
589 np::ndarray np_output =
590 np::empty(bp::make_tuple(full_strain.size1(), full_strain.size2()),
591 np::dtype::get_builtin<double>());
598 if (np_output.get_shape()[0] != full_strain.size1() ||
599 np_output.get_shape()[1] != full_strain.size2()) {
602 "Wrong shape of Objective Gradient from python expected (" +
603 std::to_string(full_strain.size1()) +
", " +
604 std::to_string(full_strain.size2()) +
"), got (" +
605 std::to_string(np_output.get_shape()[0]) +
", " +
606 std::to_string(np_output.get_shape()[1]) +
")");
610 o_ptr->resize(stress_ptr->size1(), stress_ptr->size2(),
false);
611 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
615 }
catch (bp::error_already_set
const &) {
655 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
656 boost::shared_ptr<MatrixDouble> stress_ptr,
657 boost::shared_ptr<MatrixDouble> strain_ptr,
658 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize) {
665 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
668 auto full_stress = symmetrize ?
copyToFull(*(stress_ptr)) : *(stress_ptr);
669 auto full_strain = symmetrize ?
copyToFull(*(strain_ptr)) : *(strain_ptr);
671 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
672 full_stress.size2());
673 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
674 full_strain.size2());
677 np::ndarray np_output =
678 np::empty(bp::make_tuple(full_strain.size1(), full_strain.size2()),
679 np::dtype::get_builtin<double>());
686 if (np_output.get_shape()[0] != full_strain.size1() ||
687 np_output.get_shape()[1] != full_strain.size2()) {
690 "Wrong shape of Objective Gradient from python expected (" +
691 std::to_string(full_strain.size1()) +
", " +
692 std::to_string(full_strain.size2()) +
"), got (" +
693 std::to_string(np_output.get_shape()[0]) +
", " +
694 std::to_string(np_output.get_shape()[1]) +
")");
697 o_ptr->resize(strain_ptr->size1(), strain_ptr->size2(),
false);
698 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
701 }
catch (bp::error_already_set
const &) {
743 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
744 boost::shared_ptr<MatrixDouble> stress_ptr,
745 boost::shared_ptr<MatrixDouble> strain_ptr,
746 boost::shared_ptr<MatrixDouble> o_ptr,
bool symmetrize) {
753 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
756 auto full_stress = symmetrize ?
copyToFull(*(stress_ptr)) : *(stress_ptr);
757 auto full_strain = symmetrize ?
copyToFull(*(strain_ptr)) : *(strain_ptr);
759 auto np_stress =
convertToNumPy(full_stress.data(), full_stress.size1(),
760 full_stress.size2());
761 auto np_strain =
convertToNumPy(full_strain.data(), full_strain.size1(),
762 full_strain.size2());
765 np::ndarray np_output =
766 np::empty(bp::make_tuple(u_ptr->size1(), u_ptr->size2()),
767 np::dtype::get_builtin<double>());
775 if (np_output.get_shape()[0] != u_ptr->size1() ||
776 np_output.get_shape()[1] != u_ptr->size2()) {
779 "Wrong shape of Objective Gradient from python expected (" +
780 std::to_string(u_ptr->size1()) +
", " +
781 std::to_string(u_ptr->size2()) +
"), got (" +
782 std::to_string(np_output.get_shape()[0]) +
", " +
783 std::to_string(np_output.get_shape()[1]) +
")");
787 o_ptr->resize(u_ptr->size1(), u_ptr->size2(),
false);
788 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
789 std::copy(val_ptr, val_ptr + u_ptr->size1() * u_ptr->size2(),
790 o_ptr->data().begin());
792 }
catch (bp::error_already_set
const &) {
801 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
802 boost::shared_ptr<MatrixDouble> t_ptr,
803 boost::shared_ptr<MatrixDouble> o_ptr) {
809 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
810 auto np_t =
convertToNumPy(t_ptr->data(), t_ptr->size1(), t_ptr->size2());
812 np::ndarray np_output =
813 np::empty(bp::make_tuple(u_ptr->size1(), u_ptr->size2()),
814 np::dtype::get_builtin<double>());
819 if (np_output.get_shape()[0] != u_ptr->size1() ||
820 np_output.get_shape()[1] != u_ptr->size2()) {
823 "Wrong shape of Objective Gradient from python expected (" +
824 std::to_string(u_ptr->size1()) +
", " +
825 std::to_string(u_ptr->size2()) +
"), got (" +
826 std::to_string(np_output.get_shape()[0]) +
", " +
827 std::to_string(np_output.get_shape()[1]) +
")");
830 o_ptr->resize(u_ptr->size1(), u_ptr->size2(),
false);
831 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
832 std::copy(val_ptr, val_ptr + u_ptr->size1() * u_ptr->size2(),
833 o_ptr->data().begin());
835 }
catch (bp::error_already_set
const &) {
843 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
844 boost::shared_ptr<MatrixDouble> t_ptr,
845 boost::shared_ptr<VectorDouble> o_ptr,
bool symmetrize) {
852 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
853 auto np_t =
convertToNumPy(t_ptr->data(), t_ptr->size1(), t_ptr->size2());
855 np::ndarray np_output = np::empty(bp::make_tuple(t_ptr->size2()),
856 np::dtype::get_builtin<double>());
861 if (np_output.get_nd() != 1 || np_output.get_shape()[0] != t_ptr->size2()) {
864 "Wrong shape of Objective Function from python expected (" +
865 std::to_string(t_ptr->size2()) +
"), got (" +
866 std::to_string(np_output.get_shape()[0]) +
")");
869 o_ptr->resize(t_ptr->size2(),
false);
870 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
871 std::copy(val_ptr, val_ptr + t_ptr->size2(), o_ptr->data().begin());
873 }
catch (bp::error_already_set
const &) {
881 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
882 boost::shared_ptr<MatrixDouble> t_ptr,
883 boost::shared_ptr<MatrixDouble> o_ptr) {
888 auto np_u =
convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
889 auto np_t =
convertToNumPy(t_ptr->data(), t_ptr->size1(), t_ptr->size2());
891 np::ndarray np_output =
892 np::empty(bp::make_tuple(u_ptr->size1(), u_ptr->size2()),
893 np::dtype::get_builtin<double>());
898 if (np_output.get_shape()[0] != u_ptr->size1() ||
899 np_output.get_shape()[1] != u_ptr->size2()) {
902 "Wrong shape of Objective Gradient from python expected (" +
903 std::to_string(u_ptr->size1()) +
", " +
904 std::to_string(u_ptr->size2()) +
"), got (" +
905 std::to_string(np_output.get_shape()[0]) +
", " +
906 std::to_string(np_output.get_shape()[1]) +
")");
909 o_ptr->resize(u_ptr->size1(), u_ptr->size2(),
false);
910 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
911 std::copy(val_ptr, val_ptr + u_ptr->size1() * u_ptr->size2(),
912 o_ptr->data().begin());
914 }
catch (bp::error_already_set
const &) {
957 int block_id,
MatrixDouble &coords, std::array<double, 3> ¢roid,
977 np::ndarray np_output =
978 np::empty(bp::make_tuple(nb_modes, coords.size1(), coords.size2()),
979 np::dtype::get_builtin<double>());
986 if (np_output.get_shape()[0] != nb_modes ||
987 np_output.get_shape()[1] != coords.size1() ||
988 np_output.get_shape()[2] != coords.size2()) {
990 "Wrong shape of Modes from python expected (" +
991 std::to_string(nb_modes) +
", " +
992 std::to_string(coords.size1()) +
", " +
993 std::to_string(coords.size2()) +
"), got (" +
994 std::to_string(np_output.get_shape()[0]) +
", " +
995 std::to_string(np_output.get_shape()[1]) +
", " +
996 std::to_string(np_output.get_shape()[2]) +
")");
1000 o_ptr.resize(nb_modes, coords.size1() * coords.size2(),
false);
1001 double *val_ptr =
reinterpret_cast<double *
>(np_output.get_data());
1003 std::copy(val_ptr, val_ptr + coords.size1() * coords.size2() * nb_modes,
1004 o_ptr.data().begin());
1006 }
catch (bp::error_already_set
const &) {
1016 np::ndarray coords, np::ndarray u,
1018 np::ndarray stress, np::ndarray strain, np::ndarray &o
1024 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f"))) {
1026 o = bp::extract<np::ndarray>(
1028 }
else if (bp::extract<bool>(
1030 o = bp::extract<np::ndarray>(
1035 "Python function f_interior(coords,u,stress,strain) is not defined");
1038 }
catch (bp::error_already_set
const &) {
1048 np::ndarray coords, np::ndarray u,
1050 np::ndarray stress, np::ndarray strain, np::ndarray &o
1056 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_stress"))) {
1058 o = bp::extract<np::ndarray>(
1060 }
else if (bp::extract<bool>(
1062 o = bp::extract<np::ndarray>(
1063 mainNamespace[
"f_interior_stress"](coords, u, stress, strain));
1067 "Python function f_interior_stress(coords,u,stress,strain) is not defined");
1070 }
catch (bp::error_already_set
const &) {
1080 np::ndarray coords, np::ndarray u,
1082 np::ndarray stress, np::ndarray strain, np::ndarray &o
1088 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_strain"))) {
1090 o = bp::extract<np::ndarray>(
1092 }
else if (bp::extract<bool>(
1094 o = bp::extract<np::ndarray>(
1095 mainNamespace[
"f_interior_strain"](coords, u, stress, strain));
1099 "Python function f_interior_strain(coords,u,stress,strain) is not defined");
1102 }
catch (bp::error_already_set
const &) {
1112 np::ndarray coords, np::ndarray u,
1114 np::ndarray stress, np::ndarray strain, np::ndarray &o
1120 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_u"))) {
1122 o = bp::extract<np::ndarray>(
1124 }
else if (bp::extract<bool>(
1126 o = bp::extract<np::ndarray>(
1131 "Python function f_interior_u(coords,u,stress,strain) is not defined");
1134 }
catch (bp::error_already_set
const &) {
1144 np::ndarray coords, np::ndarray u,
1146 np::ndarray
t, np::ndarray &o
1152 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_boundary_t"))) {
1153 o = bp::extract<np::ndarray>(
mainNamespace[
"f_boundary_t"](coords, u,
t));
1157 "Python function f_boundary_t(coords,u,t) is not defined");
1160 }
catch (bp::error_already_set
const &) {
1169 np::ndarray coords, np::ndarray u,
1171 np::ndarray
t, np::ndarray &o
1177 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_boundary"))) {
1178 o = bp::extract<np::ndarray>(
mainNamespace[
"f_boundary"](coords, u,
t));
1179 }
else if (bp::extract<bool>(
1180 mainNamespace.attr(
"__contains__")(
"f_boundary_function"))) {
1181 o = bp::extract<np::ndarray>(
1186 "Python function f_boundary(coords,u,t) is not defined");
1189 }
catch (bp::error_already_set
const &) {
1198 np::ndarray coords, np::ndarray u,
1200 np::ndarray
t, np::ndarray &o
1206 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"f_boundary_u"))) {
1207 o = bp::extract<np::ndarray>(
mainNamespace[
"f_boundary_u"](coords, u,
t));
1211 "Python function f_boundary_u(coords,u,t) is not defined");
1214 }
catch (bp::error_already_set
const &) {
1226 if (bp::extract<bool>(
1228 modes = bp::extract<int>(
mainNamespace[
"number_of_modes"](block_id));
1232 "Python function number_of_modes(block_id) is not defined");
1235 }
catch (bp::error_already_set
const &) {
1245 np::ndarray centroid,
1250 if (bp::extract<bool>(
mainNamespace.attr(
"__contains__")(
"block_modes"))) {
1251 o = bp::extract<np::ndarray>(
1252 mainNamespace[
"block_modes"](block_id, coords, centroid, bbodx));
1256 "Python function block_modes(block_id,coords,centroid,bbox) is not "
1259 }
catch (bp::error_already_set
const &) {
1290 auto dtype = np::dtype::get_builtin<double>();
1291 auto size = bp::make_tuple(rows, nb_gauss_pts);
1292 auto stride = bp::make_tuple(nb_gauss_pts *
sizeof(
double),
sizeof(
double));
1293 return (np::from_data(data.data(), dtype, size, stride, bp::object()));
1298 auto dtype = np::dtype::get_builtin<double>();
1299 auto size = bp::make_tuple(s);
1300 auto stride = bp::make_tuple(
sizeof(
double));
1301 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
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)
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< VectorDouble > o_ptr, bool symmetrize=true)
Evaluate objective function at current state.
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)
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