8#ifndef __CONTACTOPS_HPP__
9#define __CONTACTOPS_HPP__
24struct CommonData :
public boost::enable_shared_from_this<CommonData> {
38 static SmartPetscObj<Vec>
72 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
77 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &
contactDisp);
81 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
86 return boost::shared_ptr<VectorDouble>(shared_from_this(), &
sdfVals);
90 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &
gradsSdf);
94 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &
hessSdf);
98 return boost::shared_ptr<VectorDouble>(shared_from_this(), &
constraintVals);
107#ifdef ENABLE_PYTHON_BINDING
109 SDFPython() =
default;
110 virtual ~SDFPython() =
default;
112 MoFEMErrorCode sdfInit(
const std::string py_file) {
117 auto main_module = bp::import(
"__main__");
118 mainNamespace = main_module.attr(
"__dict__");
119 bp::exec_file(py_file.c_str(), mainNamespace, mainNamespace);
121 sdfFun = mainNamespace[
"sdf"];
122 sdfGradFun = mainNamespace[
"grad_sdf"];
123 sdfHessFun = mainNamespace[
"hess_sdf"];
125 }
catch (bp::error_already_set
const &) {
133 template <
typename T>
134 inline std::vector<T>
135 py_list_to_std_vector(
const boost::python::object &iterable) {
136 return std::vector<T>(boost::python::stl_input_iterator<T>(iterable),
137 boost::python::stl_input_iterator<T>());
142 double delta_t,
double t, np::ndarray x, np::ndarray y, np::ndarray z,
143 np::ndarray tx, np::ndarray ty, np::ndarray tz,
int block_id,
151 sdf = bp::extract<np::ndarray>(
152 sdfFun(delta_t,
t, x, y, z, tx, ty, tz, block_id));
154 }
catch (bp::error_already_set
const &) {
164 double delta_t,
double t, np::ndarray x, np::ndarray y, np::ndarray z,
165 np::ndarray tx, np::ndarray ty, np::ndarray tz,
int block_id,
166 np::ndarray &grad_sdf
173 grad_sdf = bp::extract<np::ndarray>(
174 sdfGradFun(delta_t,
t, x, y, z, tx, ty, tz, block_id));
176 }
catch (bp::error_already_set
const &) {
186 double delta_t,
double t, np::ndarray x, np::ndarray y, np::ndarray z,
187 np::ndarray tx, np::ndarray ty, np::ndarray tz,
int block_id,
188 np::ndarray &hess_sdf
195 hess_sdf = bp::extract<np::ndarray>(
196 sdfHessFun(delta_t,
t, x, y, z, tx, ty, tz, block_id));
198 }
catch (bp::error_already_set
const &) {
207 bp::object mainNamespace;
209 bp::object sdfGradFun;
210 bp::object sdfHessFun;
213static boost::weak_ptr<SDFPython> sdfPythonWeakPtr;
215inline np::ndarray convert_to_numpy(VectorDouble &data,
int nb_gauss_pts,
217 auto dtype = np::dtype::get_builtin<double>();
218 auto size = bp::make_tuple(nb_gauss_pts);
219 auto stride = bp::make_tuple(3 *
sizeof(
double));
220 return (np::from_data(&data[
id], dtype,
size, stride, bp::object()));
226 double delta_t,
double t,
int nb_gauss_pts, MatrixDouble &spatial_coords,
227 MatrixDouble &normals_at_pts,
int block_id)>;
230 double delta_t,
double t,
int nb_gauss_pts, MatrixDouble &spatial_coords,
231 MatrixDouble &normals_at_pts,
int block_id)>;
234 double delta_t,
double t,
int nb_gauss_pts, MatrixDouble &spatial_coords,
235 MatrixDouble &normals_at_pts,
int block_id)>;
239 MatrixDouble &m_spatial_coords,
240 MatrixDouble &m_normals_at_pts,
243#ifdef ENABLE_PYTHON_BINDING
244 if (
auto sdf_ptr = sdfPythonWeakPtr.lock()) {
246 VectorDouble v_spatial_coords = m_spatial_coords.data();
247 VectorDouble v_normal_at_pts = m_normals_at_pts.data();
249 bp::list python_coords;
250 bp::list python_normals;
252 for (
int idx = 0; idx < 3; ++idx) {
253 python_coords.append(
254 convert_to_numpy(v_spatial_coords, nb_gauss_pts, idx));
255 python_normals.append(
256 convert_to_numpy(v_normal_at_pts, nb_gauss_pts, idx));
259 np::ndarray np_sdf = np::empty(bp::make_tuple(nb_gauss_pts),
260 np::dtype::get_builtin<double>());
262 bp::extract<np::ndarray>(python_coords[0]),
263 bp::extract<np::ndarray>(python_coords[1]),
264 bp::extract<np::ndarray>(python_coords[2]),
265 bp::extract<np::ndarray>(python_normals[0]),
266 bp::extract<np::ndarray>(python_normals[1]),
267 bp::extract<np::ndarray>(python_normals[2]),
269 "Failed python call");
272 if (np_sdf.get_nd() != 1 || np_sdf.get_shape()[0] != nb_gauss_pts) {
275 "Wrong number of dimensions or size of SDF returned from "
276 "python, expected: dim 1, got: " +
277 std::to_string(np_sdf.get_nd()) +
", expected size: (" +
278 std::to_string(nb_gauss_pts) +
")");
281 double *sdf_val_ptr =
reinterpret_cast<double *
>(np_sdf.get_data());
284 v_sdf.resize(nb_gauss_pts,
false);
286 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg)
287 v_sdf[gg] = *(sdf_val_ptr + gg);
293 v_sdf.resize(nb_gauss_pts,
false);
294 auto t_coords = getFTensor1FromPtr<3>(&m_spatial_coords(0, 0));
296 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
297 v_sdf[gg] = -t_coords(2) - 0.1;
306 MatrixDouble &m_spatial_coords,
307 MatrixDouble &m_normals_at_pts,
int block_id) {
308#ifdef ENABLE_PYTHON_BINDING
309 if (
auto sdf_ptr = sdfPythonWeakPtr.lock()) {
311 VectorDouble v_spatial_coords = m_spatial_coords.data();
312 VectorDouble v_normal_at_pts = m_normals_at_pts.data();
314 bp::list python_coords;
315 bp::list python_normals;
317 for (
int idx = 0; idx < 3; ++idx) {
318 python_coords.append(
319 convert_to_numpy(v_spatial_coords, nb_gauss_pts, idx));
320 python_normals.append(
321 convert_to_numpy(v_normal_at_pts, nb_gauss_pts, idx));
324 np::ndarray np_grad_sdf = np::empty(bp::make_tuple(nb_gauss_pts, 3),
325 np::dtype::get_builtin<double>());
327 delta_t,
t, bp::extract<np::ndarray>(python_coords[0]),
328 bp::extract<np::ndarray>(python_coords[1]),
329 bp::extract<np::ndarray>(python_coords[2]),
330 bp::extract<np::ndarray>(python_normals[0]),
331 bp::extract<np::ndarray>(python_normals[1]),
332 bp::extract<np::ndarray>(python_normals[2]), block_id,
334 "Failed python call");
337 if (np_grad_sdf.get_shape()[0] != nb_gauss_pts ||
338 np_grad_sdf.get_shape()[1] != 3) {
340 "Wrong shape of gradient of SDF returned from "
341 "python, expected: (" +
342 std::to_string(nb_gauss_pts) +
", 3), got: (" +
343 std::to_string(np_grad_sdf.get_shape()[0]) +
", " +
344 std::to_string(np_grad_sdf.get_shape()[1]) +
")");
347 double *grad_ptr =
reinterpret_cast<double *
>(np_grad_sdf.get_data());
349 MatrixDouble m_grad_sdf;
350 m_grad_sdf.resize(nb_gauss_pts, 3,
false);
351 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
352 for (
int idx = 0; idx < 3; ++idx)
353 m_grad_sdf(gg, idx) = *(grad_ptr + (3 * gg + idx));
358 MatrixDouble m_grad_sdf;
359 m_grad_sdf.resize(nb_gauss_pts, 3,
false);
362 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
364 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
365 t_grad_sdf(
i) = t_grad_sdf_set(
i);
374 MatrixDouble &m_spatial_coords,
375 MatrixDouble &m_normals_at_pts,
int block_id) {
376#ifdef ENABLE_PYTHON_BINDING
377 if (
auto sdf_ptr = sdfPythonWeakPtr.lock()) {
379 VectorDouble v_spatial_coords = m_spatial_coords.data();
380 VectorDouble v_normal_at_pts = m_normals_at_pts.data();
382 bp::list python_coords;
383 bp::list python_normals;
385 for (
int idx = 0; idx < 3; ++idx) {
386 python_coords.append(
387 convert_to_numpy(v_spatial_coords, nb_gauss_pts, idx));
388 python_normals.append(
389 convert_to_numpy(v_normal_at_pts, nb_gauss_pts, idx));
392 np::ndarray np_hess_sdf = np::empty(bp::make_tuple(nb_gauss_pts, 6),
393 np::dtype::get_builtin<double>());
395 delta_t,
t, bp::extract<np::ndarray>(python_coords[0]),
396 bp::extract<np::ndarray>(python_coords[1]),
397 bp::extract<np::ndarray>(python_coords[2]),
398 bp::extract<np::ndarray>(python_normals[0]),
399 bp::extract<np::ndarray>(python_normals[1]),
400 bp::extract<np::ndarray>(python_normals[2]), block_id,
402 "Failed python call");
405 if (np_hess_sdf.get_shape()[0] != nb_gauss_pts ||
406 np_hess_sdf.get_shape()[1] != 6) {
408 "Wrong shape of Hessian of SDF returned from "
409 "python, expected: (" +
410 std::to_string(nb_gauss_pts) +
", 6), got: (" +
411 std::to_string(np_hess_sdf.get_shape()[0]) +
", " +
412 std::to_string(np_hess_sdf.get_shape()[1]) +
")");
415 double *hess_ptr =
reinterpret_cast<double *
>(np_hess_sdf.get_data());
417 MatrixDouble m_hess_sdf;
418 m_hess_sdf.resize(nb_gauss_pts, 6,
false);
419 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
420 for (
int idx = 0; idx < 6; ++idx)
421 m_hess_sdf(gg, idx) = *(hess_ptr + (6 * gg + idx));
426 MatrixDouble m_hess_sdf;
427 m_hess_sdf.resize(nb_gauss_pts, 6,
false);
431 auto t_hess_sdf = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
433 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
434 t_hess_sdf(
i,
j) = t_hess_sdf_set(
i,
j);
440template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
443template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
446template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
449template <
int DIM, IntegrationType I,
typename AssemblyBoundaryEleOp>
452template <
int DIM, IntegrationType I,
typename AssemblyBoundaryEleOp>
455template <
int DIM, IntegrationType I,
typename AssemblyBoundaryEleOp>
458template <
typename T1,
typename T2,
int DIM1,
int DIM2>
461 size_t nb_gauss_pts) {
462 MatrixDouble m_spatial_coords(nb_gauss_pts, 3);
463 m_spatial_coords.clear();
464 auto t_spatial_coords = getFTensor1FromPtr<3>(&m_spatial_coords(0, 0));
466 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
467 t_spatial_coords(
i) = t_coords(
i) + t_disp(
i);
472 return m_spatial_coords;
475template <
typename T1,
int DIM1>
477 size_t nb_gauss_pts) {
478 MatrixDouble m_normals_at_pts(nb_gauss_pts, 3);
479 m_normals_at_pts.clear();
481 auto t_set_normal = getFTensor1FromMat<3>(m_normals_at_pts);
482 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
483 t_set_normal(
i) = t_normal_at_pts(
i) / t_normal_at_pts.l2();
487 return m_normals_at_pts;
490template <
int DIM,
typename BoundaryEleOp>
494 boost::shared_ptr<CommonData> common_data_ptr,
double scale = 1,
496 MoFEMErrorCode doWork(
int side, EntityType
type,
EntData &data);
504template <
int DIM,
typename BoundaryEleOp>
508 boost::shared_ptr<CommonData> common_data_ptr,
510 boost::shared_ptr<Range> contact_range_ptr =
nullptr);
511 MoFEMErrorCode doWork(
int side, EntityType
type,
EntData &data);
523template <
int DIM,
typename BoundaryEleOp>
526 MoFEMErrorCode doWork(
int side, EntityType
type,
EntData &data);
538template <
int DIM,
typename AssemblyBoundaryEleOp>
542 boost::shared_ptr<CommonData> common_data_ptr,
544 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data);
555template <
int DIM,
typename AssemblyBoundaryEleOp>
559 const std::string col_field_name,
560 boost::shared_ptr<CommonData> common_data_ptr,
562 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
563 EntitiesFieldData::EntData &col_data);
575template <
int DIM,
typename AssemblyBoundaryEleOp>
579 const std::string row_field_name,
const std::string col_field_name,
580 boost::shared_ptr<CommonData> common_data_ptr,
582 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
583 EntitiesFieldData::EntData &col_data);
595 template <
int DIM, IntegrationType I>
599 template <
int DIM, IntegrationType I>
603 template <
int DIM, IntegrationType I>
611 template <
int DIM, IntegrationType I>
615 template <
int DIM, IntegrationType I>
619 template <
int DIM, IntegrationType I>
626 constexpr auto eps = std::numeric_limits<float>::epsilon();
627 if (std::abs(x) <
eps)
635inline double w(
const double sdf,
const double tn) {
653template <
int DIM,
typename BoundaryEleOp>
656 boost::shared_ptr<CommonData> common_data_ptr,
double scale,
659 commonDataPtr(common_data_ptr), scaleTraction(
scale),
662template <
int DIM,
typename BoundaryEleOp>
671 auto t_w = BoundaryEleOp::getFTensor0IntegrationWeight();
672 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
673 auto t_coords = BoundaryEleOp::getFTensor1CoordsAtGaussPts();
675 const auto nb_gauss_pts = BoundaryEleOp::getGaussPts().size2();
676 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
678 if (isAxisymmetric) {
681 const double alpha = t_w *
jacobian * BoundaryEleOp::getMeasure();
682 t_sum_t(
i) += alpha * t_traction(
i);
688 t_sum_t(
i) *= scaleTraction;
690 constexpr int ind[] = {
TX,
TY,
TZ};
691 CHKERR VecSetValues(commonDataPtr->totalTractionAndArea, 3, ind, &t_sum_t(0),
696template <
int DIM,
typename BoundaryEleOp>
700 boost::shared_ptr<Range> contact_range_ptr)
703 contactRange(contact_range_ptr) {}
705template <
int DIM,
typename BoundaryEleOp>
711 auto fe_type = BoundaryEleOp::getFEType();
713 const auto fe_ent = BoundaryEleOp::getFEEntityHandle();
715 if (contactRange->find(fe_ent) != contactRange->end()) {
720 auto t_w = BoundaryEleOp::getFTensor0IntegrationWeight();
721 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
722 auto t_coords = BoundaryEleOp::getFTensor1CoordsAtGaussPts();
724 auto t_grad = getFTensor2FromMat<DIM, DIM>(commonDataPtr->contactDispGrad);
725 auto t_normal_at_pts = BoundaryEleOp::getFTensor1NormalsAtGaussPts();
727 const auto nb_gauss_pts = BoundaryEleOp::getGaussPts().size2();
729 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
730 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
732 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
734 auto ts_time = BoundaryEleOp::getTStime();
735 auto ts_time_step = BoundaryEleOp::getTStimeStep();
738 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
739 m_spatial_coords, m_normals_at_pts, block_id);
740 auto m_grad_sdf = gradSurfaceDistanceFunction(
741 ts_time_step, ts_time, nb_gauss_pts, m_spatial_coords, m_normals_at_pts,
743 auto t_sdf = getFTensor0FromVec(v_sdf);
744 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
745 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
747 if (isAxisymmetric) {
750 auto tn = -t_traction(
i) * t_grad_sdf(
i);
758 F(
i,
j) = t_grad(
i,
j) + kronecker_delta(
i,
j);
759 auto det = determinantTensor(
F);
760 CHKERR invertTensor(
F, det, invF);
761 t_normal_current(
i) = det * (invF(
j,
i) * t_normal_at_pts(
j));
763 alpha *= sqrt(t_normal_current(
i) * t_normal_current(
i));
765 if (fe_type == MBTRI) {
782 CHKERR VecSetValues(commonDataPtr->totalTractionAndArea, 2, ind, &t_sum_a(0),
788template <
int DIM,
typename BoundaryEleOp>
790 boost::shared_ptr<CommonData> common_data_ptr)
792 commonDataPtr(common_data_ptr) {}
794template <
int DIM,
typename BoundaryEleOp>
800 const auto nb_gauss_pts = BoundaryEleOp::getGaussPts().size2();
801 auto &sdf_vec = commonDataPtr->sdfVals;
802 auto &grad_mat = commonDataPtr->gradsSdf;
803 auto &hess_mat = commonDataPtr->hessSdf;
804 auto &constraint_vec = commonDataPtr->constraintVals;
805 auto &contactTraction_mat = commonDataPtr->contactTraction;
807 sdf_vec.resize(nb_gauss_pts,
false);
808 grad_mat.resize(nb_gauss_pts, DIM,
false);
809 hess_mat.resize(nb_gauss_pts, (DIM * (DIM + 1)) / 2,
false);
810 constraint_vec.resize(nb_gauss_pts,
false);
812 auto t_traction = getFTensor1FromMat<DIM>(contactTraction_mat);
814 auto t_sdf = getFTensor0FromVec(sdf_vec);
815 auto t_grad_sdf = getFTensor1FromMat<DIM>(grad_mat);
816 auto t_hess_sdf = getFTensor2SymmetricFromMat<DIM>(hess_mat);
817 auto t_constraint = getFTensor0FromVec(constraint_vec);
819 auto t_disp = getFTensor1FromMat<DIM>(commonDataPtr->contactDisp);
823 auto ts_time = BoundaryEleOp::getTStime();
824 auto ts_time_step = BoundaryEleOp::getTStimeStep();
827 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
828 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
830 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
836 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
837 m_spatial_coords, m_normals_at_pts, block_id);
840 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
841 m_spatial_coords, m_normals_at_pts, block_id);
844 hessSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
845 m_spatial_coords, m_normals_at_pts, block_id);
847 auto t_sdf_v = getFTensor0FromVec(v_sdf);
848 auto t_grad_sdf_v = getFTensor1FromMat<3>(m_grad_sdf);
849 auto t_hess_sdf_v = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
863 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
865 auto tn = -t_traction(
i) * t_grad_sdf_v(
i);
869 t_grad_sdf(
i) = t_grad_sdf_v(
i);
870 t_hess_sdf(
i,
j) = t_hess_sdf_v(
i,
j);
879template <
int DIM,
typename AssemblyBoundaryEleOp>
882 boost::shared_ptr<CommonData> common_data_ptr,
888template <
int DIM,
typename AssemblyBoundaryEleOp>
891 EntitiesFieldData::EntData &data) {
899 const size_t nb_gauss_pts = AssemblyBoundaryEleOp::getGaussPts().size2();
901 auto &nf = AssemblyBoundaryEleOp::locF;
903 auto t_w = AssemblyBoundaryEleOp::getFTensor0IntegrationWeight();
904 auto t_disp = getFTensor1FromMat<DIM>(commonDataPtr->contactDisp);
905 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
906 auto t_coords = AssemblyBoundaryEleOp::getFTensor1CoordsAtGaussPts();
908 size_t nb_base_functions = data.getN().size2() / 3;
909 auto t_base = data.getFTensor1N<3>();
912 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
913 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
915 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
917 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
919 auto ts_time = AssemblyBoundaryEleOp::getTStime();
920 auto ts_time_step = AssemblyBoundaryEleOp::getTStimeStep();
926 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
927 m_spatial_coords, m_normals_at_pts, block_id);
930 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
931 m_spatial_coords, m_normals_at_pts, block_id);
933 auto t_sdf = getFTensor0FromVec(v_sdf);
934 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
936 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
938 auto t_nf = getFTensor1FromPtr<DIM>(&nf[0]);
941 if (isAxisymmetric) {
944 const double alpha = t_w *
jacobian * AssemblyBoundaryEleOp::getMeasure();
946 auto tn = -t_traction(
i) * t_grad_sdf(
i);
950 t_cP(
i,
j) = (
c * t_grad_sdf(
i)) * t_grad_sdf(
j);
952 t_cQ(
i,
j) = kronecker_delta(
i,
j) - t_cP(
i,
j);
961 t_cP(
i,
j) * t_disp(
j) +
962 c * (t_sdf * t_grad_sdf(
i));
965 for (; bb != AssemblyBoundaryEleOp::nbRows / DIM; ++bb) {
966 const double beta = alpha * (t_base(
i) * t_normal(
i));
967 t_nf(
i) -= beta * t_rhs(
i);
972 for (; bb < nb_base_functions; ++bb)
987template <
int DIM,
typename AssemblyBoundaryEleOp>
990 const std::string col_field_name,
991 boost::shared_ptr<CommonData> common_data_ptr,
996 AssemblyBoundaryEleOp::sYmm =
false;
999template <
int DIM,
typename AssemblyBoundaryEleOp>
1002 EntitiesFieldData::EntData &row_data,
1003 EntitiesFieldData::EntData &col_data) {
1010 const size_t nb_gauss_pts = AssemblyBoundaryEleOp::getGaussPts().size2();
1011 auto &locMat = AssemblyBoundaryEleOp::locMat;
1013 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
1014 auto t_coords = AssemblyBoundaryEleOp::getFTensor1CoordsAtGaussPts();
1016 auto t_w = AssemblyBoundaryEleOp::getFTensor0IntegrationWeight();
1017 auto t_row_base = row_data.getFTensor1N<3>();
1018 size_t nb_face_functions = row_data.getN().size2() / 3;
1021 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
1022 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
1024 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
1026 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
1028 auto ts_time = AssemblyBoundaryEleOp::getTStime();
1029 auto ts_time_step = AssemblyBoundaryEleOp::getTStimeStep();
1035 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1036 m_spatial_coords, m_normals_at_pts, block_id);
1039 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1040 m_spatial_coords, m_normals_at_pts, block_id);
1043 hessSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1044 m_spatial_coords, m_normals_at_pts, block_id);
1046 auto t_sdf = getFTensor0FromVec(v_sdf);
1047 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
1048 auto t_hess_sdf = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
1050 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1053 if (isAxisymmetric) {
1054 jacobian = 2. * M_PI * t_coords(0);
1056 const double alpha = t_w *
jacobian * AssemblyBoundaryEleOp::getMeasure();
1058 auto tn = -t_traction(
i) * t_grad_sdf(
i);
1062 t_cP(
i,
j) = (
c * t_grad_sdf(
i)) * t_grad_sdf(
j);
1064 t_cQ(
i,
j) = kronecker_delta(
i,
j) - t_cP(
i,
j);
1067 t_res_dU(
i,
j) = kronecker_delta(
i,
j) + t_cP(
i,
j);
1072 (t_hess_sdf(
i,
j) * (t_grad_sdf(
k) * t_traction(
k)) +
1073 t_grad_sdf(
i) * t_hess_sdf(
k,
j) * t_traction(
k)) +
1074 c * t_sdf * t_hess_sdf(
i,
j);
1078 for (; rr != AssemblyBoundaryEleOp::nbRows / DIM; ++rr) {
1080 auto t_mat = getFTensor2FromArray<DIM, DIM, DIM>(locMat, DIM * rr);
1082 const double row_base = t_row_base(
i) * t_normal(
i);
1084 auto t_col_base = col_data.getFTensor0N(gg, 0);
1085 for (
size_t cc = 0; cc != AssemblyBoundaryEleOp::nbCols / DIM; ++cc) {
1086 const double beta = alpha * row_base * t_col_base;
1088 t_mat(
i,
j) -= beta * t_res_dU(
i,
j);
1096 for (; rr < nb_face_functions; ++rr)
1111template <
int DIM,
typename AssemblyBoundaryEleOp>
1114 const std::string row_field_name,
const std::string col_field_name,
1119 AssemblyBoundaryEleOp::sYmm =
false;
1122template <
int DIM,
typename AssemblyBoundaryEleOp>
1125 iNtegrate(EntitiesFieldData::EntData &row_data,
1126 EntitiesFieldData::EntData &col_data) {
1133 const size_t nb_gauss_pts = AssemblyBoundaryEleOp::getGaussPts().size2();
1134 auto &locMat = AssemblyBoundaryEleOp::locMat;
1136 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
1137 auto t_coords = AssemblyBoundaryEleOp::getFTensor1CoordsAtGaussPts();
1139 auto t_w = AssemblyBoundaryEleOp::getFTensor0IntegrationWeight();
1140 auto t_row_base = row_data.getFTensor1N<3>();
1141 size_t nb_face_functions = row_data.getN().size2() / 3;
1144 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
1145 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
1147 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
1149 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
1151 auto ts_time = AssemblyBoundaryEleOp::getTStime();
1152 auto ts_time_step = AssemblyBoundaryEleOp::getTStimeStep();
1158 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1159 m_spatial_coords, m_normals_at_pts, block_id);
1162 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1163 m_spatial_coords, m_normals_at_pts, block_id);
1165 auto t_sdf = getFTensor0FromVec(v_sdf);
1166 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
1168 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1171 if (isAxisymmetric) {
1172 jacobian = 2. * M_PI * t_coords(0);
1174 const double alpha = t_w *
jacobian * AssemblyBoundaryEleOp::getMeasure();
1176 auto tn = -t_traction(
i) * t_grad_sdf(
i);
1180 t_cP(
i,
j) = (
c * t_grad_sdf(
i)) * t_grad_sdf(
j);
1182 t_cQ(
i,
j) = kronecker_delta(
i,
j) - t_cP(
i,
j);
1188 for (; rr != AssemblyBoundaryEleOp::nbRows / DIM; ++rr) {
1190 auto t_mat = getFTensor2FromArray<DIM, DIM, DIM>(locMat, DIM * rr);
1191 const double row_base = t_row_base(
i) * t_normal(
i);
1193 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1194 for (
size_t cc = 0; cc != AssemblyBoundaryEleOp::nbCols / DIM; ++cc) {
1195 const double col_base = t_col_base(
i) * t_normal(
i);
1196 const double beta = alpha * row_base * col_base;
1198 t_mat(
i,
j) -= beta * t_res_dt(
i,
j);
1206 for (; rr < nb_face_functions; ++rr)
1220template <
int DIM, AssemblyType A, IntegrationType I,
typename DomainEleOp>
1222 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1226 using B =
typename FormsIntegrators<DomainEleOp>::template Assembly<
1228 using OpMixDivURhs =
typename B::template OpMixDivTimesU<3, DIM, DIM>;
1229 using OpMixDivUCylRhs =
1230 typename B::template OpMixDivTimesU<3, DIM, DIM, CYLINDRICAL>;
1232 using OpMixLambdaGradURhs =
typename B::template OpMixTensorTimesGradU<DIM>;
1233 using OpMixUTimesDivLambdaRhs =
1234 typename B::template OpMixVecTimesDivLambda<SPACE_DIM>;
1235 using OpMixUTimesLambdaRhs =
1238 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1239 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
1240 auto div_stress_ptr = boost::make_shared<MatrixDouble>();
1241 auto contact_stress_ptr = boost::make_shared<MatrixDouble>();
1246 return 2. * M_PI * r;
1251 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1252 u, common_data_ptr->contactDispPtr()));
1254 new OpCalculateHVecTensorField<DIM, DIM>(sigma, contact_stress_ptr));
1258 new OpCalculateHVecTensorDivergence<DIM, DIM>(sigma, div_stress_ptr));
1260 pip.push_back(
new OpCalculateHVecTensorDivergence<DIM, DIM, CYLINDRICAL>(
1261 sigma, div_stress_ptr));
1264 pip.push_back(
new OpCalculateVectorFieldGradient<DIM, DIM>(u, mat_grad_ptr));
1268 new OpMixDivURhs(sigma, common_data_ptr->contactDispPtr(),
jacobian));
1270 pip.push_back(
new OpMixDivUCylRhs(sigma, common_data_ptr->contactDispPtr(),
1274 pip.push_back(
new OpMixLambdaGradURhs(sigma, mat_grad_ptr,
jacobian));
1275 pip.push_back(
new OpMixUTimesDivLambdaRhs(u, div_stress_ptr,
jacobian));
1276 pip.push_back(
new OpMixUTimesLambdaRhs(u, contact_stress_ptr,
jacobian));
1282 using OpMixLhs::OpMixLhs;
1283 MoFEMErrorCode
doWork(
int row_side,
int col_side, EntityType row_type,
1284 EntityType col_type,
1285 EntitiesFieldData::EntData &row_data,
1286 EntitiesFieldData::EntData &col_data) {
1288 auto side_fe_entity = OpMixLhs::getSidePtrFE()->getFEEntityHandle();
1289 auto side_fe_data = OpMixLhs::getSideEntity(row_side, row_type);
1291 if (side_fe_entity == side_fe_data) {
1292 CHKERR OpMixLhs::doWork(row_side, col_side, row_type, col_type, row_data,
1299template <
int DIM, AssemblyType A, IntegrationType I,
typename DomainEle>
1302 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1303 std::string fe_domain_name, std::string sigma, std::string u,
1304 std::string geom, ForcesAndSourcesCore::RuleHookFun rule,
1308 using DomainEleOp =
typename DomainEle::UserDataOperator;
1310 auto op_loop_side =
new OpLoopSide<DomainEle>(
1311 m_field, fe_domain_name, DIM, Sev::noisy,
1312 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>());
1313 pip.push_back(op_loop_side);
1315 CHKERR AddHOOps<DIM, DIM, DIM>::add(op_loop_side->getOpPtrVector(),
1318 using B =
typename FormsIntegrators<DomainEleOp>::template Assembly<
1321 using OpMixDivULhs =
typename B::template OpMixDivTimesVec<DIM>;
1322 using OpMixDivUCylLhs =
1323 typename B::template OpMixDivTimesVec<DIM, CYLINDRICAL>;
1324 using OpLambdaGraULhs =
typename B::template OpMixTensorTimesGrad<DIM>;
1330 auto unity = []() {
return 1; };
1334 return 2. * M_PI * r;
1340 op_loop_side->getOpPtrVector().push_back(
1341 new OpMixDivULhsSide(sigma, u, unity,
jacobian,
true));
1343 op_loop_side->getOpPtrVector().push_back(
1344 new OpMixDivUCylLhsSide(sigma, u, unity,
jacobian,
true));
1346 op_loop_side->getOpPtrVector().push_back(
1347 new OpLambdaGraULhsSide(sigma, u, unity,
jacobian,
true));
1349 op_loop_side->getSideFEPtr()->getRuleHook = rule;
1353template <
int DIM, AssemblyType A, IntegrationType I,
typename BoundaryEleOp>
1355 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1361 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1363 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1364 u, common_data_ptr->contactDispPtr()));
1365 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1366 sigma, common_data_ptr->contactTractionPtr()));
1368 new typename C::template Assembly<A>::template OpConstrainBoundaryLhs_dU<
1370 pip.push_back(
new typename C::template Assembly<A>::
1371 template OpConstrainBoundaryLhs_dTraction<DIM, GAUSS>(
1377template <
int DIM, AssemblyType A, IntegrationType I,
typename BoundaryEleOp>
1379 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1385 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1387 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1388 u, common_data_ptr->contactDispPtr()));
1389 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1390 sigma, common_data_ptr->contactTractionPtr()));
1392 new typename C::template Assembly<A>::template OpConstrainBoundaryRhs<
1398template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
1400 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1406 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1407 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1408 sigma, common_data_ptr->contactTractionPtr()));
1409 pip.push_back(
new typename C::template OpAssembleTotalContactTraction<DIM, I>(
1415template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
1417 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1418 OpLoopSide<SideEle> *op_loop_side, std::string sigma, std::string u,
1420 boost::shared_ptr<Range> contact_range_ptr =
nullptr) {
1424 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1426 op_loop_side->getOpPtrVector().push_back(
1427 new OpCalculateVectorFieldGradient<SPACE_DIM, SPACE_DIM>(
1428 "U", common_data_ptr->contactDispGradPtr()));
1430 if (contact_range_ptr) {
1431 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1432 u, common_data_ptr->contactDispPtr()));
1433 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1434 sigma, common_data_ptr->contactTractionPtr()));
1435 pip.push_back(op_loop_side);
1436 pip.push_back(
new typename C::template OpAssembleTotalContactArea<DIM, I>(
SmartPetscObj< Mat > jacobian
#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 ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_OPERATION_UNSUCCESSFUL
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
hess_sdf(delta_t, t, x, y, z, tx, ty, tz, block_id)
grad_sdf(delta_t, t, x, y, z, tx, ty, tz, block_id)
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
constexpr double t
plate stiffness
constexpr auto field_name
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)