v0.16.3
Loading...
Searching...
No Matches
TestingContact.hpp
Go to the documentation of this file.
1/** Final-state pressure checks for the Hertz-contact tests. */
2
3namespace ContactOps {
4
5/**
6 * Compare the magnitude of the contact traction against an analytical
7 * pressure distribution, integrated as an L2 error over the contact
8 * boundary, using the final accepted field state.
9 */
11
12 ContactPressureNormCheck(MoFEM::Interface &m_field, double tol_norm,
13 std::string check_name)
14 : mField(m_field), tolNorm(tol_norm), checkName(std::move(check_name)) {
15 }
16
17 virtual ~ContactPressureNormCheck() = default;
18
19 MoFEMErrorCode operator()(DM dm) {
21
22 Range contact_range;
23 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
24 std::regex((boost::format("%s(.*)") % "CONTACT").str()))) {
25 auto meshset = m->getMeshset();
26 Range contact_meshset_range;
27 CHKERR mField.get_moab().get_entities_by_dimension(
28 meshset, SPACE_DIM - 1, contact_meshset_range, true);
29 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
30 contact_meshset_range);
31 contact_range.merge(contact_meshset_range);
32 }
33 auto contact_range_ptr = boost::make_shared<Range>(contact_range);
34
35 struct OpCalcTractionMagnitude : public BoundaryEleOp {
36 OpCalcTractionMagnitude(boost::shared_ptr<MatrixDouble> traction_ptr,
37 boost::shared_ptr<VectorDouble> mag_ptr)
38 : BoundaryEleOp(NOSPACE, OPSPACE), tractionPtr(traction_ptr),
39 magPtr(mag_ptr) {}
40 MoFEMErrorCode doWork(int, EntityType, EntitiesFieldData::EntData &) {
42 const auto nb_gauss_pts = getGaussPts().size2();
43 magPtr->resize(nb_gauss_pts);
44 using DL = DataLayoutTraits<DataLayout::GaussByCoeffs>;
45 auto t_traction = MatrixSizeHelper<
46 GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::get(
47 *tractionPtr, nb_gauss_pts)();
48 auto t_mag = getFTensor0FromVec(*magPtr);
49 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
50 t_mag = t_traction.l2();
51 ++t_traction;
52 ++t_mag;
53 }
55 }
56
57 private:
58 boost::shared_ptr<MatrixDouble> tractionPtr;
59 boost::shared_ptr<VectorDouble> magPtr;
60 };
61
62 auto fe = boost::make_shared<BoundaryEle>(mField);
63 CHKERR AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
64 fe->getOpPtrVector(), {HDIV}, "GEOMETRY");
65 // We have to integrate on curved face geometry, thus integration weight
66 // have to adjusted.
67 fe->getOpPtrVector().push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
68 fe->getRuleHook = [](int, int, int approx_order) {
69 return 2 * approx_order + geom_order - 1;
70 };
71
72 struct OpResetTraction : public BoundaryEleOp {
73 boost::shared_ptr<MatrixDouble> tractionPtr;
74 OpResetTraction(boost::shared_ptr<MatrixDouble> ptr)
75 : BoundaryEleOp(NOSPACE, OPSPACE), tractionPtr(ptr) {}
76 MoFEMErrorCode doWork(int, EntityType, EntitiesFieldData::EntData &) override {
78 using DL = DataLayoutTraits<DataLayout::GaussByCoeffs>;
79 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
80 *tractionPtr, getGaussPts().size2());
81 tractionPtr->clear();
83 }
84 };
85 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
86 fe->getOpPtrVector().push_back(
87 new OpResetTraction(common_data_ptr->contactTractionPtr()));
88 fe->getOpPtrVector().push_back(
89 new OpCalculateHVecTensorTrace<SPACE_DIM, BoundaryEleOp>(
90 "SIGMA", common_data_ptr->contactTractionPtr()));
91
92 auto mag_traction_ptr = boost::make_shared<VectorDouble>();
93 fe->getOpPtrVector().push_back(new OpCalcTractionMagnitude(
94 common_data_ptr->contactTractionPtr(), mag_traction_ptr));
95
96 auto analytical_pressure_ptr = boost::make_shared<VectorDouble>();
97 fe->getOpPtrVector().push_back(new OpGetTensor0fromFunc(
98 analytical_pressure_ptr,
99 [this](double x, double y, double z) {
100 return analyticalPressure(x, y, z);
101 }));
102
103 enum { NORM, LAST_NORM };
104 auto norm_vec = createVectorMPI(
105 mField.get_comm(), (mField.get_comm_rank() == 0) ? LAST_NORM : 0,
106 LAST_NORM);
107 fe->getOpPtrVector().push_back(new OpCalcNormL2Tensor0(
108 mag_traction_ptr, norm_vec, NORM, analytical_pressure_ptr,
109 contact_range_ptr));
110
111 CHKERR VecZeroEntries(norm_vec);
112 CHKERR DMoFEMLoopFiniteElements(dm, "bFE", fe);
113 CHKERR VecAssemblyBegin(norm_vec);
114 CHKERR VecAssemblyEnd(norm_vec);
115
116 double norm = 0.;
117 if (!mField.get_comm_rank()) {
118 const double *norm_ptr;
119 CHKERR VecGetArrayRead(norm_vec, &norm_ptr);
120 norm = std::sqrt(norm_ptr[NORM]);
121 CHKERR VecRestoreArrayRead(norm_vec, &norm_ptr);
122 }
123 CHKERR MPI_Bcast(&norm, 1, MPI_DOUBLE, 0, mField.get_comm());
124
125 CHKERR mField.getInterface<TestingInterface>()
126 ->checkError<TestType::SCALAR>(checkName, norm, 0., {tolNorm, 0.});
127
129 }
130
131protected:
132 /** Analytical pressure at a boundary gauss point's physical coordinates. */
133 virtual double analyticalPressure(double x, double y, double z) const = 0;
134
136 double tolNorm;
137 std::string checkName;
138};
139
140/** Test 2: Hertz cylinder-on-plane contact, plane strain. */
143
144protected:
145 double analyticalPressure(double x, double y, double) const override {
146 double E_star = young_modulus / (1 - poisson_ratio * poisson_ratio);
147 double R = 100.;
148 double a = 1;
149 double r = std::sqrt((x * x) + (y * y));
150 if (r > a)
151 return 0.;
152 return E_star / (2. * R) * std::sqrt(a * a - r * r);
153 }
154};
155
156/** Test 5: Hertz sphere-on-plane contact, axisymmetric. */
159
160protected:
161 double analyticalPressure(double x, double y, double) const override {
162 double E_star = young_modulus / (1 - poisson_ratio * poisson_ratio);
163 double R = 100.;
164 double d = 0.01;
165 double F = (4. / 3.) * E_star * std::sqrt(R) * std::pow(d, 1.5);
166 double a = std::pow((3. * F * R) / (4. * E_star), 1. / 3.);
167 double p_max = (3. * F) / (2. * M_PI * a * a);
168 double r = std::sqrt((x * x) + (y * y));
169 if (r > a)
170 return 0.;
171 return p_max * std::sqrt(1 - ((r * r) / (a * a)));
172 }
173};
174
175} // namespace ContactOps
PetscInt size
constexpr double a
constexpr int SPACE_DIM
BoundaryEle::UserDataOperator BoundaryEleOp
@ NOSPACE
Definition definitions.h:83
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
@ R
@ F
double young_modulus
Young modulus.
Definition plastic.cpp:126
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:127
int geom_order
Order if fixed.
Definition plastic.cpp:142
static constexpr int approx_order
FTensor::Index< 'm', 3 > m
virtual double analyticalPressure(double x, double y, double z) const =0
virtual ~ContactPressureNormCheck()=default
ContactPressureNormCheck(MoFEM::Interface &m_field, double tol_norm, std::string check_name)
double analyticalPressure(double x, double y, double) const override
double analyticalPressure(double x, double y, double) const override
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.