8 #ifndef __CONTACTOPS_HPP__
9 #define __CONTACTOPS_HPP__
14 struct CommonData :
public boost::enable_shared_from_this<CommonData> {
28 static SmartPetscObj<Vec>
32 constexpr
int ghosts[] = {0, 1, 2, 3, 4};
58 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
63 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &
contactDisp);
67 return boost::shared_ptr<MatrixDouble>(shared_from_this(),
72 return boost::shared_ptr<VectorDouble>(shared_from_this(), &
sdfVals);
76 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &
gradsSdf);
80 return boost::shared_ptr<MatrixDouble>(shared_from_this(), &
hessSdf);
84 return boost::shared_ptr<VectorDouble>(shared_from_this(), &
constraintVals);
95 SDFPython() =
default;
96 virtual ~SDFPython() =
default;
103 auto main_module = bp::import(
"__main__");
104 mainNamespace = main_module.attr(
"__dict__");
105 bp::exec_file(py_file.c_str(), mainNamespace, mainNamespace);
107 sdfFun = mainNamespace[
"sdf"];
108 sdfGradFun = mainNamespace[
"grad_sdf"];
109 sdfHessFun = mainNamespace[
"hess_sdf"];
111 }
catch (bp::error_already_set
const &) {
119 template <
typename T>
120 inline std::vector<T>
121 py_list_to_std_vector(
const boost::python::object &iterable) {
122 return std::vector<T>(boost::python::stl_input_iterator<T>(iterable),
123 boost::python::stl_input_iterator<T>());
128 double delta_t,
double t, np::ndarray x, np::ndarray y, np::ndarray z,
129 np::ndarray tx, np::ndarray ty, np::ndarray tz,
int block_id,
137 sdf = bp::extract<np::ndarray>(
138 sdfFun(delta_t,
t, x, y, z, tx, ty, tz, block_id));
140 }
catch (bp::error_already_set
const &) {
150 double delta_t,
double t, np::ndarray x, np::ndarray y, np::ndarray z,
151 np::ndarray tx, np::ndarray ty, np::ndarray tz,
int block_id,
159 grad_sdf = bp::extract<np::ndarray>(
160 sdfGradFun(delta_t,
t, x, y, z, tx, ty, tz, block_id));
162 }
catch (bp::error_already_set
const &) {
172 double delta_t,
double t, np::ndarray x, np::ndarray y, np::ndarray z,
173 np::ndarray tx, np::ndarray ty, np::ndarray tz,
int block_id,
181 hess_sdf = bp::extract<np::ndarray>(
182 sdfHessFun(delta_t,
t, x, y, z, tx, ty, tz, block_id));
184 }
catch (bp::error_already_set
const &) {
193 bp::object mainNamespace;
195 bp::object sdfGradFun;
196 bp::object sdfHessFun;
199 static boost::weak_ptr<SDFPython> sdfPythonWeakPtr;
201 inline np::ndarray convert_to_numpy(
VectorDouble &data,
int nb_gauss_pts,
203 auto dtype = np::dtype::get_builtin<double>();
204 auto size = bp::make_tuple(nb_gauss_pts);
205 auto stride = bp::make_tuple(3 *
sizeof(
double));
206 return (np::from_data(&data[
id], dtype, size, stride, bp::object()));
212 double delta_t,
double t,
int nb_gauss_pts,
MatrixDouble &spatial_coords,
216 double delta_t,
double t,
int nb_gauss_pts,
MatrixDouble &spatial_coords,
220 double delta_t,
double t,
int nb_gauss_pts,
MatrixDouble &spatial_coords,
230 if (
auto sdf_ptr = sdfPythonWeakPtr.lock()) {
232 VectorDouble v_spatial_coords = m_spatial_coords.data();
235 bp::list python_coords;
236 bp::list python_normals;
238 for (
int idx = 0; idx < 3; ++idx) {
239 python_coords.append(
240 convert_to_numpy(v_spatial_coords, nb_gauss_pts, idx));
241 python_normals.append(
242 convert_to_numpy(v_normal_at_pts, nb_gauss_pts, idx));
245 np::ndarray np_sdf = np::empty(bp::make_tuple(nb_gauss_pts),
246 np::dtype::get_builtin<double>());
248 bp::extract<np::ndarray>(python_coords[0]),
249 bp::extract<np::ndarray>(python_coords[1]),
250 bp::extract<np::ndarray>(python_coords[2]),
251 bp::extract<np::ndarray>(python_normals[0]),
252 bp::extract<np::ndarray>(python_normals[1]),
253 bp::extract<np::ndarray>(python_normals[2]),
255 "Failed python call");
257 double *sdf_val_ptr =
reinterpret_cast<double *
>(np_sdf.get_data());
260 v_sdf.resize(nb_gauss_pts,
false);
262 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg)
263 v_sdf[gg] = *(sdf_val_ptr + gg);
269 v_sdf.resize(nb_gauss_pts,
false);
270 auto t_coords = getFTensor1FromPtr<3>(&m_spatial_coords(0, 0));
272 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
273 v_sdf[gg] = -t_coords(2) - 0.1;
285 if (
auto sdf_ptr = sdfPythonWeakPtr.lock()) {
287 VectorDouble v_spatial_coords = m_spatial_coords.data();
290 bp::list python_coords;
291 bp::list python_normals;
293 for (
int idx = 0; idx < 3; ++idx) {
294 python_coords.append(
295 convert_to_numpy(v_spatial_coords, nb_gauss_pts, idx));
296 python_normals.append(
297 convert_to_numpy(v_normal_at_pts, nb_gauss_pts, idx));
300 np::ndarray np_grad_sdf = np::empty(bp::make_tuple(nb_gauss_pts, 3),
301 np::dtype::get_builtin<double>());
303 delta_t,
t, bp::extract<np::ndarray>(python_coords[0]),
304 bp::extract<np::ndarray>(python_coords[1]),
305 bp::extract<np::ndarray>(python_coords[2]),
306 bp::extract<np::ndarray>(python_normals[0]),
307 bp::extract<np::ndarray>(python_normals[1]),
308 bp::extract<np::ndarray>(python_normals[2]), block_id,
310 "Failed python call");
312 double *grad_ptr =
reinterpret_cast<double *
>(np_grad_sdf.get_data());
315 m_grad_sdf.resize(3, nb_gauss_pts,
false);
316 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
317 for (
int idx = 0; idx < 3; ++idx)
318 m_grad_sdf(idx, gg) = *(grad_ptr + (3 * gg + idx));
324 m_grad_sdf.resize(3, nb_gauss_pts,
false);
327 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
329 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
330 t_grad_sdf(
i) = t_grad_sdf_set(
i);
342 if (
auto sdf_ptr = sdfPythonWeakPtr.lock()) {
344 VectorDouble v_spatial_coords = m_spatial_coords.data();
347 bp::list python_coords;
348 bp::list python_normals;
350 for (
int idx = 0; idx < 3; ++idx) {
351 python_coords.append(
352 convert_to_numpy(v_spatial_coords, nb_gauss_pts, idx));
353 python_normals.append(
354 convert_to_numpy(v_normal_at_pts, nb_gauss_pts, idx));
357 np::ndarray np_hess_sdf = np::empty(bp::make_tuple(nb_gauss_pts, 6),
358 np::dtype::get_builtin<double>());
360 delta_t,
t, bp::extract<np::ndarray>(python_coords[0]),
361 bp::extract<np::ndarray>(python_coords[1]),
362 bp::extract<np::ndarray>(python_coords[2]),
363 bp::extract<np::ndarray>(python_normals[0]),
364 bp::extract<np::ndarray>(python_normals[1]),
365 bp::extract<np::ndarray>(python_normals[2]), block_id,
367 "Failed python call");
369 double *hess_ptr =
reinterpret_cast<double *
>(np_hess_sdf.get_data());
372 m_hess_sdf.resize(6, nb_gauss_pts,
false);
373 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
374 for (
int idx = 0; idx < 6; ++idx)
375 m_hess_sdf(idx, gg) =
376 *(hess_ptr + (6 * gg + idx));
382 m_hess_sdf.resize(6, nb_gauss_pts,
false);
386 auto t_hess_sdf = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
388 for (
size_t gg = 0; gg < nb_gauss_pts; ++gg) {
389 t_hess_sdf(
i,
j) = t_hess_sdf_set(
i,
j);
395 template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
398 template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
401 template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
404 template <
int DIM, IntegrationType I,
typename AssemblyBoundaryEleOp>
407 template <
int DIM, IntegrationType I,
typename AssemblyBoundaryEleOp>
410 template <
int DIM, IntegrationType I,
typename AssemblyBoundaryEleOp>
413 template <
typename T1,
typename T2,
int DIM1,
int DIM2>
416 size_t nb_gauss_pts) {
418 m_spatial_coords.clear();
419 auto t_spatial_coords = getFTensor1FromPtr<3>(&m_spatial_coords(0, 0));
421 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
422 t_spatial_coords(
i) = t_coords(
i) + t_disp(
i);
427 return m_spatial_coords;
430 template <
typename T1,
int DIM1>
432 size_t nb_gauss_pts) {
434 m_normals_at_pts.clear();
436 auto t_set_normal = getFTensor1FromMat<3>(m_normals_at_pts);
437 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
438 t_set_normal(
i) = t_normal_at_pts(
i) / t_normal_at_pts.l2();
442 return m_normals_at_pts;
445 template <
int DIM,
typename BoundaryEleOp>
449 boost::shared_ptr<CommonData> common_data_ptr,
double scale = 1,
459 template <
int DIM,
typename BoundaryEleOp>
463 boost::shared_ptr<CommonData> common_data_ptr,
465 boost::shared_ptr<Range> contact_range_ptr =
nullptr);
478 template <
int DIM,
typename BoundaryEleOp>
493 template <
int DIM,
typename AssemblyBoundaryEleOp>
497 boost::shared_ptr<CommonData> common_data_ptr,
510 template <
int DIM,
typename AssemblyBoundaryEleOp>
514 const std::string col_field_name,
515 boost::shared_ptr<CommonData> common_data_ptr,
530 template <
int DIM,
typename AssemblyBoundaryEleOp>
534 const std::string row_field_name,
const std::string col_field_name,
535 boost::shared_ptr<CommonData> common_data_ptr,
550 template <
int DIM, IntegrationType I>
554 template <
int DIM, IntegrationType I>
558 template <
int DIM, IntegrationType I>
566 template <
int DIM, IntegrationType I>
570 template <
int DIM, IntegrationType I>
574 template <
int DIM, IntegrationType I>
581 constexpr
auto eps = std::numeric_limits<float>::epsilon();
582 if (std::abs(x) <
eps)
590 inline double w(
const double sdf,
const double tn) {
608 template <
int DIM,
typename BoundaryEleOp>
609 OpAssembleTotalContactTractionImpl<DIM, GAUSS, BoundaryEleOp>::
610 OpAssembleTotalContactTractionImpl(
611 boost::shared_ptr<CommonData> common_data_ptr,
double scale,
614 commonDataPtr(common_data_ptr), scaleTraction(
scale),
617 template <
int DIM,
typename BoundaryEleOp>
626 auto t_w = BoundaryEleOp::getFTensor0IntegrationWeight();
627 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
628 auto t_coords = BoundaryEleOp::getFTensor1CoordsAtGaussPts();
630 const auto nb_gauss_pts = BoundaryEleOp::getGaussPts().size2();
631 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
632 double jacobian = 1.;
633 if (isAxisymmetric) {
634 jacobian = 2. * M_PI * t_coords(0);
636 const double alpha = t_w * jacobian * BoundaryEleOp::getMeasure();
637 t_sum_t(
i) += alpha * t_traction(
i);
643 t_sum_t(
i) *= scaleTraction;
645 constexpr
int ind[] = {0, 1, 2};
651 template <
int DIM,
typename BoundaryEleOp>
655 boost::shared_ptr<Range> contact_range_ptr)
658 contactRange(contact_range_ptr) {}
660 template <
int DIM,
typename BoundaryEleOp>
666 auto fe_type = BoundaryEleOp::getFEType();
668 const auto fe_ent = BoundaryEleOp::getFEEntityHandle();
670 if (contactRange->find(fe_ent) != contactRange->end()) {
675 auto t_w = BoundaryEleOp::getFTensor0IntegrationWeight();
676 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
677 auto t_coords = BoundaryEleOp::getFTensor1CoordsAtGaussPts();
679 auto t_grad = getFTensor2FromMat<DIM, DIM>(commonDataPtr->contactDispGrad);
680 auto t_normal_at_pts = BoundaryEleOp::getFTensor1NormalsAtGaussPts();
682 const auto nb_gauss_pts = BoundaryEleOp::getGaussPts().size2();
684 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
685 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
687 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
689 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
690 auto ts_time = BoundaryEleOp::getTStime();
691 auto ts_time_step = BoundaryEleOp::getTStimeStep();
694 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
695 m_spatial_coords, m_normals_at_pts, block_id);
696 auto m_grad_sdf = gradSurfaceDistanceFunction(
697 ts_time_step, ts_time, nb_gauss_pts, m_spatial_coords, m_normals_at_pts,
700 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
701 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
702 double jacobian = 1.;
703 if (isAxisymmetric) {
704 jacobian = 2. * M_PI * t_coords(0);
706 auto tn = -t_traction(
i) * t_grad_sdf(
i);
708 double alpha = t_w * jacobian;
717 t_normal_current(
i) = det * (invF(
j,
i) * t_normal_at_pts(
j));
719 alpha *= sqrt(t_normal_current(
i) * t_normal_current(
i));
721 if (fe_type == MBTRI) {
737 constexpr
int ind[] = {3, 4};
744 template <
int DIM,
typename BoundaryEleOp>
746 boost::shared_ptr<CommonData> common_data_ptr)
748 commonDataPtr(common_data_ptr) {}
750 template <
int DIM,
typename BoundaryEleOp>
756 const auto nb_gauss_pts = BoundaryEleOp::getGaussPts().size2();
757 auto &sdf_vec = commonDataPtr->sdfVals;
758 auto &grad_mat = commonDataPtr->gradsSdf;
759 auto &hess_mat = commonDataPtr->hessSdf;
760 auto &constraint_vec = commonDataPtr->constraintVals;
761 auto &contactTraction_mat = commonDataPtr->contactTraction;
763 sdf_vec.resize(nb_gauss_pts,
false);
764 grad_mat.resize(DIM, nb_gauss_pts,
false);
765 hess_mat.resize((DIM * (DIM + 1)) / 2, nb_gauss_pts,
false);
766 constraint_vec.resize(nb_gauss_pts,
false);
768 auto t_traction = getFTensor1FromMat<DIM>(contactTraction_mat);
771 auto t_grad_sdf = getFTensor1FromMat<DIM>(grad_mat);
772 auto t_hess_sdf = getFTensor2SymmetricFromMat<DIM>(hess_mat);
775 auto t_disp = getFTensor1FromMat<DIM>(commonDataPtr->contactDisp);
776 auto t_coords = BoundaryEleOp::getFTensor1CoordsAtGaussPts();
777 auto t_normal_at_pts = BoundaryEleOp::getFTensor1NormalsAtGaussPts();
782 auto ts_time = BoundaryEleOp::getTStime();
783 auto ts_time_step = BoundaryEleOp::getTStimeStep();
786 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
787 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
789 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
795 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
796 m_spatial_coords, m_normals_at_pts, block_id);
799 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
800 m_spatial_coords, m_normals_at_pts, block_id);
803 hessSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
804 m_spatial_coords, m_normals_at_pts, block_id);
807 auto t_grad_sdf_v = getFTensor1FromMat<3>(m_grad_sdf);
808 auto t_hess_sdf_v = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
822 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
824 auto tn = -t_traction(
i) * t_grad_sdf_v(
i);
828 t_grad_sdf(
i) = t_grad_sdf_v(
i);
829 t_hess_sdf(
i,
j) = t_hess_sdf_v(
i,
j);
838 template <
int DIM,
typename AssemblyBoundaryEleOp>
841 boost::shared_ptr<CommonData> common_data_ptr,
847 template <
int DIM,
typename AssemblyBoundaryEleOp>
858 const size_t nb_gauss_pts = AssemblyBoundaryEleOp::getGaussPts().size2();
862 auto t_normal_at_pts = AssemblyBoundaryEleOp::getFTensor1NormalsAtGaussPts();
864 auto t_w = AssemblyBoundaryEleOp::getFTensor0IntegrationWeight();
865 auto t_disp = getFTensor1FromMat<DIM>(commonDataPtr->contactDisp);
866 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
867 auto t_coords = AssemblyBoundaryEleOp::getFTensor1CoordsAtGaussPts();
869 size_t nb_base_functions = data.getN().size2() / 3;
870 auto t_base = data.getFTensor1N<3>();
873 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
874 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
876 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
878 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
880 auto ts_time = AssemblyBoundaryEleOp::getTStime();
881 auto ts_time_step = AssemblyBoundaryEleOp::getTStimeStep();
887 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
888 m_spatial_coords, m_normals_at_pts, block_id);
891 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
892 m_spatial_coords, m_normals_at_pts, block_id);
895 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
897 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
899 auto t_nf = getFTensor1FromPtr<DIM>(&nf[0]);
901 double jacobian = 1.;
902 if (isAxisymmetric) {
903 jacobian = 2. * M_PI * t_coords(0);
905 const double alpha = t_w * jacobian * AssemblyBoundaryEleOp::getMeasure();
907 auto tn = -t_traction(
i) * t_grad_sdf(
i);
911 t_cP(
i,
j) = (
c * t_grad_sdf(
i)) * t_grad_sdf(
j);
922 t_cP(
i,
j) * t_disp(
j) +
923 c * (t_sdf * t_grad_sdf(
i));
927 const double beta = alpha * (t_base(
i) * t_normal(
i));
928 t_nf(
i) -= beta * t_rhs(
i);
933 for (; bb < nb_base_functions; ++bb)
948 template <
int DIM,
typename AssemblyBoundaryEleOp>
951 const std::string col_field_name,
952 boost::shared_ptr<CommonData> common_data_ptr,
957 AssemblyBoundaryEleOp::sYmm =
false;
960 template <
int DIM,
typename AssemblyBoundaryEleOp>
971 const size_t nb_gauss_pts = AssemblyBoundaryEleOp::getGaussPts().size2();
974 auto t_normal_at_pts = AssemblyBoundaryEleOp::getFTensor1NormalsAtGaussPts();
975 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
976 auto t_coords = AssemblyBoundaryEleOp::getFTensor1CoordsAtGaussPts();
978 auto t_w = AssemblyBoundaryEleOp::getFTensor0IntegrationWeight();
979 auto t_row_base = row_data.getFTensor1N<3>();
980 size_t nb_face_functions = row_data.getN().size2() / 3;
983 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
984 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
986 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
988 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
990 auto ts_time = AssemblyBoundaryEleOp::getTStime();
991 auto ts_time_step = AssemblyBoundaryEleOp::getTStimeStep();
997 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
998 m_spatial_coords, m_normals_at_pts, block_id);
1001 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1002 m_spatial_coords, m_normals_at_pts, block_id);
1005 hessSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1006 m_spatial_coords, m_normals_at_pts, block_id);
1009 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
1010 auto t_hess_sdf = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
1012 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1014 double jacobian = 1.;
1015 if (isAxisymmetric) {
1016 jacobian = 2. * M_PI * t_coords(0);
1018 const double alpha = t_w * jacobian * AssemblyBoundaryEleOp::getMeasure();
1020 auto tn = -t_traction(
i) * t_grad_sdf(
i);
1024 t_cP(
i,
j) = (
c * t_grad_sdf(
i)) * t_grad_sdf(
j);
1034 (t_hess_sdf(
i,
j) * (t_grad_sdf(
k) * t_traction(
k)) +
1035 t_grad_sdf(
i) * t_hess_sdf(
k,
j) * t_traction(
k)) +
1036 c * t_sdf * t_hess_sdf(
i,
j);
1042 auto t_mat = getFTensor2FromArray<DIM, DIM, DIM>(locMat, DIM * rr);
1044 const double row_base = t_row_base(
i) * t_normal(
i);
1046 auto t_col_base = col_data.getFTensor0N(gg, 0);
1048 const double beta = alpha * row_base * t_col_base;
1050 t_mat(
i,
j) -= beta * t_res_dU(
i,
j);
1058 for (; rr < nb_face_functions; ++rr)
1073 template <
int DIM,
typename AssemblyBoundaryEleOp>
1076 const std::string row_field_name,
const std::string col_field_name,
1081 AssemblyBoundaryEleOp::sYmm =
false;
1084 template <
int DIM,
typename AssemblyBoundaryEleOp>
1095 const size_t nb_gauss_pts = AssemblyBoundaryEleOp::getGaussPts().size2();
1098 auto t_normal_at_pts = AssemblyBoundaryEleOp::getFTensor1NormalsAtGaussPts();
1099 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
1100 auto t_coords = AssemblyBoundaryEleOp::getFTensor1CoordsAtGaussPts();
1102 auto t_w = AssemblyBoundaryEleOp::getFTensor0IntegrationWeight();
1103 auto t_row_base = row_data.getFTensor1N<3>();
1104 size_t nb_face_functions = row_data.getN().size2() / 3;
1107 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
1108 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
1110 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
1112 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
1114 auto ts_time = AssemblyBoundaryEleOp::getTStime();
1115 auto ts_time_step = AssemblyBoundaryEleOp::getTStimeStep();
1121 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1122 m_spatial_coords, m_normals_at_pts, block_id);
1125 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1126 m_spatial_coords, m_normals_at_pts, block_id);
1129 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
1131 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1133 double jacobian = 1.;
1134 if (isAxisymmetric) {
1135 jacobian = 2. * M_PI * t_coords(0);
1137 const double alpha = t_w * jacobian * AssemblyBoundaryEleOp::getMeasure();
1139 auto tn = -t_traction(
i) * t_grad_sdf(
i);
1143 t_cP(
i,
j) = (
c * t_grad_sdf(
i)) * t_grad_sdf(
j);
1153 auto t_mat = getFTensor2FromArray<DIM, DIM, DIM>(locMat, DIM * rr);
1154 const double row_base = t_row_base(
i) * t_normal(
i);
1156 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1158 const double col_base = t_col_base(
i) * t_normal(
i);
1159 const double beta = alpha * row_base * col_base;
1161 t_mat(
i,
j) -= beta * t_res_dt(
i,
j);
1169 for (; rr < nb_face_functions; ++rr)
1183 template <
int DIM, AssemblyType A, IntegrationType I,
typename DomainEleOp>
1185 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1189 using B =
typename FormsIntegrators<DomainEleOp>::template Assembly<
1190 A>::template LinearForm<I>;
1191 using OpMixDivURhs =
typename B::template OpMixDivTimesU<3, DIM, DIM>;
1192 using OpMixDivUCylRhs =
1193 typename B::template OpMixDivTimesU<3, DIM, DIM, CYLINDRICAL>;
1195 using OpMixLambdaGradURhs =
typename B::template OpMixTensorTimesGradU<DIM>;
1196 using OpMixUTimesDivLambdaRhs =
1197 typename B::template OpMixVecTimesDivLambda<SPACE_DIM>;
1198 using OpMixUTimesLambdaRhs =
1201 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1202 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
1203 auto div_stress_ptr = boost::make_shared<MatrixDouble>();
1204 auto contact_stress_ptr = boost::make_shared<MatrixDouble>();
1209 return 2. * M_PI *
r;
1214 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1215 u, common_data_ptr->contactDispPtr()));
1217 new OpCalculateHVecTensorField<DIM, DIM>(sigma, contact_stress_ptr));
1221 new OpCalculateHVecTensorDivergence<DIM, DIM>(sigma, div_stress_ptr));
1223 pip.push_back(
new OpCalculateHVecTensorDivergence<DIM, DIM, CYLINDRICAL>(
1224 sigma, div_stress_ptr));
1231 new OpMixDivURhs(sigma, common_data_ptr->contactDispPtr(), jacobian));
1233 pip.push_back(
new OpMixDivUCylRhs(sigma, common_data_ptr->contactDispPtr(),
1237 pip.push_back(
new OpMixLambdaGradURhs(sigma, mat_grad_ptr, jacobian));
1238 pip.push_back(
new OpMixUTimesDivLambdaRhs(u, div_stress_ptr, jacobian));
1239 pip.push_back(
new OpMixUTimesLambdaRhs(u, contact_stress_ptr, jacobian));
1245 using OpMixLhs::OpMixLhs;
1247 EntityType col_type,
1251 auto side_fe_entity = OpMixLhs::getSidePtrFE()->getFEEntityHandle();
1252 auto side_fe_data = OpMixLhs::getSideEntity(row_side, row_type);
1254 if (side_fe_entity == side_fe_data) {
1255 CHKERR OpMixLhs::doWork(row_side, col_side, row_type, col_type, row_data,
1262 template <
int DIM, AssemblyType A, IntegrationType I,
typename DomainEle>
1265 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1266 std::string fe_domain_name, std::string sigma, std::string u,
1267 std::string geom, ForcesAndSourcesCore::RuleHookFun rule,
1273 auto op_loop_side =
new OpLoopSide<DomainEle>(
1274 m_field, fe_domain_name, DIM, Sev::noisy,
1275 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>());
1276 pip.push_back(op_loop_side);
1281 using B =
typename FormsIntegrators<DomainEleOp>::template Assembly<
1284 using OpMixDivULhs =
typename B::template OpMixDivTimesVec<DIM>;
1285 using OpMixDivUCylLhs =
1286 typename B::template OpMixDivTimesVec<DIM, CYLINDRICAL>;
1287 using OpLambdaGraULhs =
typename B::template OpMixTensorTimesGrad<DIM>;
1293 auto unity = []() {
return 1; };
1297 return 2. * M_PI *
r;
1303 op_loop_side->getOpPtrVector().push_back(
1304 new OpMixDivULhsSide(sigma, u, unity, jacobian,
true));
1306 op_loop_side->getOpPtrVector().push_back(
1307 new OpMixDivUCylLhsSide(sigma, u, unity, jacobian,
true));
1309 op_loop_side->getOpPtrVector().push_back(
1310 new OpLambdaGraULhsSide(sigma, u, unity, jacobian,
true));
1312 op_loop_side->getSideFEPtr()->getRuleHook = rule;
1316 template <
int DIM, AssemblyType A, IntegrationType I,
typename BoundaryEleOp>
1318 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1324 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1326 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1327 u, common_data_ptr->contactDispPtr()));
1328 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1329 sigma, common_data_ptr->contactTractionPtr()));
1331 new typename C::template Assembly<A>::template OpConstrainBoundaryLhs_dU<
1333 pip.push_back(
new typename C::template Assembly<A>::
1334 template OpConstrainBoundaryLhs_dTraction<DIM, GAUSS>(
1340 template <
int DIM, AssemblyType A, IntegrationType I,
typename BoundaryEleOp>
1342 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1348 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1350 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1351 u, common_data_ptr->contactDispPtr()));
1352 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1353 sigma, common_data_ptr->contactTractionPtr()));
1355 new typename C::template Assembly<A>::template OpConstrainBoundaryRhs<
1361 template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
1363 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1369 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1370 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1371 sigma, common_data_ptr->contactTractionPtr()));
1372 pip.push_back(
new typename C::template OpAssembleTotalContactTraction<DIM, I>(
1378 template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
1380 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1381 OpLoopSide<SideEle> *op_loop_side, std::string sigma, std::string u,
1383 boost::shared_ptr<Range> contact_range_ptr =
nullptr) {
1387 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1389 op_loop_side->getOpPtrVector().push_back(
1391 "U", common_data_ptr->contactDispGradPtr()));
1393 if (contact_range_ptr) {
1394 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1395 u, common_data_ptr->contactDispPtr()));
1396 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1397 sigma, common_data_ptr->contactTractionPtr()));
1398 pip.push_back(op_loop_side);
1399 pip.push_back(
new typename C::template OpAssembleTotalContactArea<DIM, I>(
1407 #endif // __CONTACTOPS_HPP__