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();
860 auto &nf = AssemblyBoundaryEleOp::locF;
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));
926 for (; bb != AssemblyBoundaryEleOp::nbRows / DIM; ++bb) {
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();
972 auto &locMat = AssemblyBoundaryEleOp::locMat;
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;
985 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
986 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
988 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
990 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
992 auto ts_time = AssemblyBoundaryEleOp::getTStime();
993 auto ts_time_step = AssemblyBoundaryEleOp::getTStimeStep();
999 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1000 m_spatial_coords, m_normals_at_pts, block_id);
1003 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1004 m_spatial_coords, m_normals_at_pts, block_id);
1007 hessSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1008 m_spatial_coords, m_normals_at_pts, block_id);
1011 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
1012 auto t_hess_sdf = getFTensor2SymmetricFromMat<3>(m_hess_sdf);
1014 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1016 double jacobian = 1.;
1017 if (isAxisymmetric) {
1018 jacobian = 2. * M_PI * t_coords(0);
1020 const double alpha = t_w * jacobian * AssemblyBoundaryEleOp::getMeasure();
1022 auto tn = -t_traction(
i) * t_grad_sdf(
i);
1026 t_cP(
i,
j) = (
c * t_grad_sdf(
i)) * t_grad_sdf(
j);
1036 (t_hess_sdf(
i,
j) * (t_grad_sdf(
k) * t_traction(
k)) +
1037 t_grad_sdf(
i) * t_hess_sdf(
k,
j) * t_traction(
k)) +
1038 c * t_sdf * t_hess_sdf(
i,
j);
1042 for (; rr != AssemblyBoundaryEleOp::nbRows / DIM; ++rr) {
1044 auto t_mat = getFTensor2FromArray<DIM, DIM, DIM>(locMat, DIM * rr);
1046 const double row_base = t_row_base(
i) * t_normal(
i);
1048 auto t_col_base = col_data.getFTensor0N(gg, 0);
1049 for (
size_t cc = 0; cc != AssemblyBoundaryEleOp::nbCols / DIM; ++cc) {
1050 const double beta = alpha * row_base * t_col_base;
1052 t_mat(
i,
j) -= beta * t_res_dU(
i,
j);
1060 for (; rr < nb_face_functions; ++rr)
1075 template <
int DIM,
typename AssemblyBoundaryEleOp>
1078 const std::string row_field_name,
const std::string col_field_name,
1083 AssemblyBoundaryEleOp::sYmm =
false;
1086 template <
int DIM,
typename AssemblyBoundaryEleOp>
1097 const size_t nb_gauss_pts = AssemblyBoundaryEleOp::getGaussPts().size2();
1098 auto &locMat = AssemblyBoundaryEleOp::locMat;
1100 auto t_normal_at_pts = AssemblyBoundaryEleOp::getFTensor1NormalsAtGaussPts();
1101 auto t_traction = getFTensor1FromMat<DIM>(commonDataPtr->contactTraction);
1102 auto t_coords = AssemblyBoundaryEleOp::getFTensor1CoordsAtGaussPts();
1104 auto t_w = AssemblyBoundaryEleOp::getFTensor0IntegrationWeight();
1105 auto t_row_base = row_data.getFTensor1N<3>();
1106 size_t nb_face_functions = row_data.getN().size2() / 3;
1109 BoundaryEleOp::getFTensor1CoordsAtGaussPts(),
1110 getFTensor1FromMat<DIM>(commonDataPtr->contactDisp), nb_gauss_pts);
1112 BoundaryEleOp::getFTensor1NormalsAtGaussPts(), nb_gauss_pts);
1114 auto t_normal = getFTensor1FromMat<3>(m_normals_at_pts);
1116 auto ts_time = AssemblyBoundaryEleOp::getTStime();
1117 auto ts_time_step = AssemblyBoundaryEleOp::getTStimeStep();
1123 surfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1124 m_spatial_coords, m_normals_at_pts, block_id);
1127 gradSurfaceDistanceFunction(ts_time_step, ts_time, nb_gauss_pts,
1128 m_spatial_coords, m_normals_at_pts, block_id);
1131 auto t_grad_sdf = getFTensor1FromMat<3>(m_grad_sdf);
1133 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1135 double jacobian = 1.;
1136 if (isAxisymmetric) {
1137 jacobian = 2. * M_PI * t_coords(0);
1139 const double alpha = t_w * jacobian * AssemblyBoundaryEleOp::getMeasure();
1141 auto tn = -t_traction(
i) * t_grad_sdf(
i);
1145 t_cP(
i,
j) = (
c * t_grad_sdf(
i)) * t_grad_sdf(
j);
1153 for (; rr != AssemblyBoundaryEleOp::nbRows / DIM; ++rr) {
1155 auto t_mat = getFTensor2FromArray<DIM, DIM, DIM>(locMat, DIM * rr);
1156 const double row_base = t_row_base(
i) * t_normal(
i);
1158 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
1159 for (
size_t cc = 0; cc != AssemblyBoundaryEleOp::nbCols / DIM; ++cc) {
1160 const double col_base = t_col_base(
i) * t_normal(
i);
1161 const double beta = alpha * row_base * col_base;
1163 t_mat(
i,
j) -= beta * t_res_dt(
i,
j);
1171 for (; rr < nb_face_functions; ++rr)
1185 template <
int DIM, AssemblyType A, IntegrationType I,
typename DomainEleOp>
1187 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1191 using B =
typename FormsIntegrators<DomainEleOp>::template Assembly<
1192 A>::template LinearForm<I>;
1193 using OpMixDivURhs =
typename B::template OpMixDivTimesU<3, DIM, DIM>;
1194 using OpMixDivUCylRhs =
1195 typename B::template OpMixDivTimesU<3, DIM, DIM, CYLINDRICAL>;
1197 using OpMixLambdaGradURhs =
typename B::template OpMixTensorTimesGradU<DIM>;
1198 using OpMixUTimesDivLambdaRhs =
1199 typename B::template OpMixVecTimesDivLambda<SPACE_DIM>;
1200 using OpMixUTimesLambdaRhs =
1203 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1204 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
1205 auto div_stress_ptr = boost::make_shared<MatrixDouble>();
1206 auto contact_stress_ptr = boost::make_shared<MatrixDouble>();
1211 return 2. * M_PI *
r;
1216 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1217 u, common_data_ptr->contactDispPtr()));
1219 new OpCalculateHVecTensorField<DIM, DIM>(sigma, contact_stress_ptr));
1223 new OpCalculateHVecTensorDivergence<DIM, DIM>(sigma, div_stress_ptr));
1225 pip.push_back(
new OpCalculateHVecTensorDivergence<DIM, DIM, CYLINDRICAL>(
1226 sigma, div_stress_ptr));
1233 new OpMixDivURhs(sigma, common_data_ptr->contactDispPtr(), jacobian));
1235 pip.push_back(
new OpMixDivUCylRhs(sigma, common_data_ptr->contactDispPtr(),
1239 pip.push_back(
new OpMixLambdaGradURhs(sigma, mat_grad_ptr, jacobian));
1240 pip.push_back(
new OpMixUTimesDivLambdaRhs(u, div_stress_ptr, jacobian));
1241 pip.push_back(
new OpMixUTimesLambdaRhs(u, contact_stress_ptr, jacobian));
1247 using OpMixLhs::OpMixLhs;
1249 EntityType col_type,
1253 auto side_fe_entity = OpMixLhs::getSidePtrFE()->getFEEntityHandle();
1254 auto side_fe_data = OpMixLhs::getSideEntity(row_side, row_type);
1256 if (side_fe_entity == side_fe_data) {
1257 CHKERR OpMixLhs::doWork(row_side, col_side, row_type, col_type, row_data,
1264 template <
int DIM, AssemblyType A, IntegrationType I,
typename DomainEle>
1267 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1268 std::string fe_domain_name, std::string sigma, std::string u,
1269 std::string geom, ForcesAndSourcesCore::RuleHookFun rule,
1275 auto op_loop_side =
new OpLoopSide<DomainEle>(
1276 m_field, fe_domain_name, DIM, Sev::noisy,
1277 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>());
1278 pip.push_back(op_loop_side);
1280 CHKERR AddHOOps<DIM, DIM, DIM>::add(op_loop_side->getOpPtrVector(),
1283 using B =
typename FormsIntegrators<DomainEleOp>::template Assembly<
1286 using OpMixDivULhs =
typename B::template OpMixDivTimesVec<DIM>;
1287 using OpMixDivUCylLhs =
1288 typename B::template OpMixDivTimesVec<DIM, CYLINDRICAL>;
1289 using OpLambdaGraULhs =
typename B::template OpMixTensorTimesGrad<DIM>;
1295 auto unity = []() {
return 1; };
1299 return 2. * M_PI *
r;
1305 op_loop_side->getOpPtrVector().push_back(
1306 new OpMixDivULhsSide(sigma, u, unity, jacobian,
true));
1308 op_loop_side->getOpPtrVector().push_back(
1309 new OpMixDivUCylLhsSide(sigma, u, unity, jacobian,
true));
1311 op_loop_side->getOpPtrVector().push_back(
1312 new OpLambdaGraULhsSide(sigma, u, unity, jacobian,
true));
1314 op_loop_side->getSideFEPtr()->getRuleHook = rule;
1318 template <
int DIM, AssemblyType A, IntegrationType I,
typename BoundaryEleOp>
1320 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1326 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1328 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1329 u, common_data_ptr->contactDispPtr()));
1330 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1331 sigma, common_data_ptr->contactTractionPtr()));
1333 new typename C::template Assembly<A>::template OpConstrainBoundaryLhs_dU<
1335 pip.push_back(
new typename C::template Assembly<A>::
1336 template OpConstrainBoundaryLhs_dTraction<DIM, GAUSS>(
1342 template <
int DIM, AssemblyType A, IntegrationType I,
typename BoundaryEleOp>
1344 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1350 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1352 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1353 u, common_data_ptr->contactDispPtr()));
1354 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1355 sigma, common_data_ptr->contactTractionPtr()));
1357 new typename C::template Assembly<A>::template OpConstrainBoundaryRhs<
1363 template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
1365 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1371 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1372 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1373 sigma, common_data_ptr->contactTractionPtr()));
1374 pip.push_back(
new typename C::template OpAssembleTotalContactTraction<DIM, I>(
1380 template <
int DIM, IntegrationType I,
typename BoundaryEleOp>
1382 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1383 OpLoopSide<SideEle> *op_loop_side, std::string sigma, std::string u,
1385 boost::shared_ptr<Range> contact_range_ptr =
nullptr) {
1389 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
1391 op_loop_side->getOpPtrVector().push_back(
1393 "U", common_data_ptr->contactDispGradPtr()));
1395 if (contact_range_ptr) {
1396 pip.push_back(
new OpCalculateVectorFieldValues<DIM>(
1397 u, common_data_ptr->contactDispPtr()));
1398 pip.push_back(
new OpCalculateHVecTensorTrace<DIM, BoundaryEleOp>(
1399 sigma, common_data_ptr->contactTractionPtr()));
1400 pip.push_back(op_loop_side);
1401 pip.push_back(
new typename C::template OpAssembleTotalContactArea<DIM, I>(
1409 #endif // __CONTACTOPS_HPP__