v0.15.5
Loading...
Searching...
No Matches
Smoother.hpp
Go to the documentation of this file.
1#ifndef __SMOOTHER_HPP__
2#define __SMOOTHER_HPP__
3
4#ifndef WITH_ADOL_C
5#error "MoFEM need to be compiled with ADOL-C"
6#endif
7
8struct Smoother {
9
10 static MoFEMErrorCode extractMeshEdges(MoFEM::Interface &m_field,
11 Range &output_edges,
12 Range &output_vertices) {
14
15 Range fineFeatureTris;
16 FTENSOR_INDEX(3, i);
17 Range vols;
18 CHKERR m_field.get_moab().get_entities_by_dimension(0, 3, vols);
19 if (vols.empty()) {
20 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
21 "no 3d entities found in the mesh");
22 }
23
24 Skinner skinner(&m_field.get_moab());
25 Range skin_tris;
26 CHKERR skinner.find_skin(0, vols, false, skin_tris);
27 if (skin_tris.empty()) {
28 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
29 "no skin triangles found in the mesh");
30 }
31
32 auto tri_normal = [&](const EntityHandle tri,
35 CHKERR m_field.getInterface<Tools>()->getTriNormal(tri, &normal(0));
36 normal.normalize();
38 };
39
40 const double fine_planar_cos = std::cos(1e-6); //FIXME: parameter?
41
42 Range skin_edges;
43 CHKERR m_field.get_moab().get_adjacencies(skin_tris, 1, true, skin_edges,
44 moab::Interface::UNION);
45
46 for (auto edge : skin_edges) {
47 Range adj_tris;
48 CHKERR m_field.get_moab().get_adjacencies(&edge, 1, 2, false, adj_tris,
49 moab::Interface::UNION);
50 adj_tris = intersect(adj_tris, skin_tris);
51 if (adj_tris.size() != 2) {
52 continue;
53 }
54
57 CHKERR tri_normal(adj_tris[0], n0);
58 CHKERR tri_normal(adj_tris[1], n1);
59 const double dot = n0(i) * n1(i);
60 if (std::abs(dot) <= fine_planar_cos) {
61 fineFeatureTris.insert(adj_tris[0]);
62 fineFeatureTris.insert(adj_tris[1]);
63 output_edges.insert(edge);
64 }
65 }
66
67 std::map<EntityHandle, std::vector<EntityHandle>> vert_edges;
68 for (auto edge : output_edges) {
69 const EntityHandle *conn = nullptr;
70 int nconn = 0;
71 CHKERR m_field.get_moab().get_connectivity(edge, conn, nconn, false);
72 if (nconn != 2)
73 continue;
74 vert_edges[conn[0]].push_back(edge);
75 vert_edges[conn[1]].push_back(edge);
76 }
77
78 Range straight_edges;
79 for (auto edge : output_edges) {
80 const EntityHandle *conn = nullptr;
81 int nconn = 0;
82 CHKERR m_field.get_moab().get_connectivity(edge, conn, nconn, false);
83 if (nconn != 2)
84 continue;
85
86 bool keep_edge = true;
87 for (int vv = 0; vv < 2; ++vv) {
88 const auto v = conn[vv];
89 const auto it = vert_edges.find(v);
90 if (it == vert_edges.end()) {
91 keep_edge = false;
92 break;
93 }
94 const auto &inc_edges = it->second;
95 if (inc_edges.size() > 2) {
96 keep_edge = false;
97 break;
98 }
99 if (inc_edges.size() == 2) {
100 const auto other_edge =
101 (inc_edges[0] == edge) ? inc_edges[1] : inc_edges[0];
102 const EntityHandle *conn_other = nullptr;
103 int nconn_other = 0;
104 CHKERR m_field.get_moab().get_connectivity(other_edge, conn_other,
105 nconn_other, false);
106 if (nconn_other != 2) {
107 keep_edge = false;
108 break;
109 }
110 const EntityHandle v_other =
111 (conn_other[0] == v) ? conn_other[1] : conn_other[0];
112
113 double pv[3], pa[3], pb[3];
114 CHKERR m_field.get_moab().get_coords(&v, 1, pv);
115 EntityHandle va = conn[1 - vv];
116 CHKERR m_field.get_moab().get_coords(&va, 1, pa);
117 CHKERR m_field.get_moab().get_coords(&v_other, 1, pb);
118
122 &pv[0], &pv[1], &pv[2]);
124 &pa[0], &pa[1], &pa[2]);
126 &pb[0], &pb[1], &pb[2]);
127 a(i) = t_pa(i) - t_pv(i);
128 b(i) = t_pb(i) - t_pv(i);
129 const double na = a.l2();
130 const double nb = b.l2();
131 if (na == 0 || nb == 0) {
132 keep_edge = false;
133 break;
134 }
135 const double dot = (a(i) * b(i)) / (na * nb);
136 if (std::abs(dot) < fine_planar_cos) {
137 keep_edge = false;
138 break;
139 }
140 }
141 }
142
143 if (keep_edge) {
144 straight_edges.insert(edge);
145 }
146 }
147
148 output_edges = straight_edges;
149 output_vertices.clear();
150 if (!output_edges.empty()) {
151 std::map<EntityHandle, int> vert_count;
152 for (auto edge : output_edges) {
153 const EntityHandle *conn = nullptr;
154 int nconn = 0;
155 CHKERR m_field.get_moab().get_connectivity(edge, conn, nconn, false);
156 if (nconn != 2)
157 continue;
158 vert_count[conn[0]]++;
159 vert_count[conn[1]]++;
160 }
161 Range filtered_edges;
162 for (auto edge : output_edges) {
163 const EntityHandle *conn = nullptr;
164 int nconn = 0;
165 CHKERR m_field.get_moab().get_connectivity(edge, conn, nconn, false);
166 if (nconn != 2)
167 continue;
168 const int d0 = vert_count[conn[0]];
169 const int d1 = vert_count[conn[1]];
170 if (!(d0 == 1 && d1 == 1)) {
171 filtered_edges.insert(edge);
172 for (int vv = 0; vv < 2; ++vv) {
173 const auto v = conn[vv];
174 auto it = vert_count.find(v);
175 if (it != vert_count.end() && it->second == 1) {
176 output_vertices.insert(v);
177 }
178 }
179 }
180 }
181 output_edges = filtered_edges;
182 }
183
184 if (!fineFeatureTris.empty())
185 CHKERR CutMeshInterface::SaveData(m_field.get_moab())(
186 "tri_features_test.vtk", fineFeatureTris);
187 if (!output_edges.empty())
188 CHKERR CutMeshInterface::SaveData(m_field.get_moab())(
189 "edges_test.vtk", output_edges);
190 if (!output_vertices.empty())
191 CHKERR CutMeshInterface::SaveData(m_field.get_moab())(
192 "vertices_test.vtk", output_vertices);
193
195 }
196
198 using LinearForm = FormsIntegrators<DomainEleOp>::Assembly<PETSC>::LinearForm<
199 GAUSS>;
201 FormsIntegrators<DomainEleOp>::Assembly<PETSC>::BiLinearForm<GAUSS>;
202 using OpInternalForcePiola = LinearForm::OpGradTimesTensor<1, 3, 3>;
203 using OpKPiola = BiLinearForm::OpGradTensorGrad<1, 3, 3, 1>;
204
205 struct CommonData {
206 boost::shared_ptr<MatrixDouble> matGradPtr;
207 boost::shared_ptr<MatrixDouble> matFirstPiolaStressPtr;
208 boost::shared_ptr<MatrixDouble> matTangentPtr;
209 std::string spatialPositions;
210 std::string meshPositions;
211 std::vector<MatrixDouble> sTress;
212
214 : matGradPtr(new MatrixDouble()),
215 matFirstPiolaStressPtr(new MatrixDouble()),
216 matTangentPtr(new MatrixDouble()) {}
217 };
218
219 template <typename TYPE>
220 struct CalculatePK1;
221
222 struct BlockData {
224 boost::shared_ptr<CalculatePK1<adouble>>
226 boost::shared_ptr<CalculatePK1<double>>
228 };
229
230 std::map<int, BlockData> setOfBlocks;
231
233
234 template <typename TYPE>
235 struct CalculatePK1 : public DomainEleOp {
236
241
245 MatrixBoundedArray<TYPE, 9> F, invF, P;
247
248 int gG = 0; ///< Gauss point number
249 CommonData *commonDataPtr = nullptr; ///< common data shared between entities (f.e.
250 ///< field values at Gauss pts.)
252 *opPtr = nullptr; ///< pointer to finite element tetrahedral operator
253
254 virtual MoFEMErrorCode calculateP_PiolaKirchhoffI() {
257 }
258
259 protected:
260 inline static auto resizeAndSet(MatrixBoundedArray<TYPE, 9> &m) {
261 m.resize(3, 3, false);
262 return getFTensor2FromArray3by3(m, FTensor::Number<0>(), 0);
263 }
264 };
265
266 // struct MyVolumeFE : public MoFEM::VolumeElementForcesAndSourcesCore {
267
268 // std::string meshPositionsFieldName = "NONE";
269 // int addToRule = 0;
270
271 // MyVolumeFE(MoFEM::Interface &m_field)
272 // : MoFEM::VolumeElementForcesAndSourcesCore(m_field) {}
273 // };
274
276 boost::shared_ptr<MyVolumeFE> feRhsPtr;
277 boost::shared_ptr<MyVolumeFE> feLhsPtr;
278
279 MyVolumeFE &feRhs; ///< calculate right hand side for tetrahedral elements
280 MyVolumeFE &getLoopFeRhs() { return feRhs; } ///< get rhs volume element
281 MyVolumeFE &feLhs; ///< calculate left hand side for tetrahedral elements
282 MyVolumeFE &getLoopFeLhs() { return feLhs; } ///< get lhs volume element
283
285 : feRhsPtr(new MyVolumeFE(m_field)),
286 feLhsPtr(new MyVolumeFE(m_field)), feRhs(*feRhsPtr), feLhs(*feLhsPtr) {}
287
288
290 : public DomainEleOp {
291
294 const int tag;
295 const bool computeJacobian;
296 VectorDouble activeVars;
297 VectorDouble results;
298 MatrixDouble jacMat;
299
300 OpJacobianSmoother(const std::string field_name, BlockData &data,
301 CommonData &common_data, int tag, bool jacobian)
303 commonData(common_data), tag(tag), computeJacobian(jacobian) {
304 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
305 }
306
307 MoFEMErrorCode doWork(int side, EntityType type,
308 EntitiesFieldData::EntData &data) {
310
311 if (type != MBVERTEX)
313
314 const auto nb_gauss_pts = getGaussPts().size2();
315 auto &mat_grad = *commonData.matGradPtr;
316 if (mat_grad.size2() != nb_gauss_pts)
318
319 auto t_grad = getFTensor2FromMat<3, 3>(mat_grad);
320
321 FTensor::Index<'i', 3> i;
322 FTensor::Index<'j', 3> j;
323 FTensor::Index<'k', 3> k;
324 FTensor::Index<'l', 3> l;
325
326 if (!computeJacobian) {
327 auto &mat_p = *commonData.matFirstPiolaStressPtr;
328 mat_p.resize(9, nb_gauss_pts, false);
329 mat_p.clear();
330 auto t_p = getFTensor2FromMat<3, 3>(mat_p);
331 if (!dAta.materialDoublePtr) {
332 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
333 "Material pointer not set");
334 }
335 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
336 dAta.materialDoublePtr->opPtr = this;
337 dAta.materialDoublePtr->gG = gg;
338 for (int ii = 0; ii < 3; ++ii) {
339 for (int jj = 0; jj < 3; ++jj) {
340 dAta.materialDoublePtr->F(ii, jj) = t_grad(ii, jj);
341 }
342 }
343
344 CHKERR dAta.materialDoublePtr->calculateP_PiolaKirchhoffI();
345 for (int ii = 0; ii < 3; ++ii)
346 for (int jj = 0; jj < 3; ++jj)
347 t_p(ii, jj) = dAta.materialDoublePtr->P(ii, jj);
348
349 ++t_grad;
350 ++t_p;
351 }
353 }
354
356 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
357 "AD material pointer not set");
358 }
359
360 MatrixDouble &mat_tangent = *commonData.matTangentPtr;
361 mat_tangent.resize(81, nb_gauss_pts, false);
362 mat_tangent.clear();
363 auto t_dP_dF = getFTensor4FromMat<3, 3, 3, 3, 1>(mat_tangent);
364
365 activeVars.resize(9, false);
366 results.resize(9, false);
367 jacMat.resize(9, 9, false);
368
369 bool tag_recorded = false;
370 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
371 int idx = 0;
372 for (int ii = 0; ii < 3; ++ii) {
373 for (int jj = 0; jj < 3; ++jj) {
374 activeVars[idx++] = t_grad(ii, jj);
375 }
376 }
377
378 if (!tag_recorded) {
379 trace_on(tag);
380 idx = 0;
381 dAta.materialAdoublePtr->opPtr = this;
382 dAta.materialAdoublePtr->gG = gg;
383 for (int ii = 0; ii < 3; ++ii) {
384 for (int jj = 0; jj < 3; ++jj) {
385 dAta.materialAdoublePtr->F(ii, jj) <<= activeVars[idx++];
386 }
387 }
388 CHKERR dAta.materialAdoublePtr->calculateP_PiolaKirchhoffI();
389 idx = 0;
390 for (int ii = 0; ii < 3; ++ii) {
391 for (int jj = 0; jj < 3; ++jj) {
392 dAta.materialAdoublePtr->P(ii, jj) >>= results[idx++];
393 }
394 }
395 trace_off();
396 tag_recorded = true;
397 }
398
399 double *jac_ptr[9];
400 for (int rr = 0; rr < 9; ++rr)
401 jac_ptr[rr] = &jacMat(rr, 0);
402
403 int r = ::jacobian(tag, 9, 9, &activeVars[0], jac_ptr);
404 if (r < 0)
405 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
406 "ADOL-C function evaluation with error");
407
408 for (int ii = 0; ii < 3; ++ii) {
409 for (int jj = 0; jj < 3; ++jj) {
410 for (int kk = 0; kk < 3; ++kk) {
411 for (int ll = 0; ll < 3; ++ll) {
412 t_dP_dF(ii, jj, kk, ll) =
413 jacMat(ii * 3 + jj, kk * 3 + ll);
414 }
415 }
416 }
417 }
418
419 ++t_grad;
420 ++t_dP_dF;
421 }
422
424 }
425 };
426
427};
428
429#endif //__SMOOTHER_HPP__
ForcesAndSourcesCore::UserDataOperator UserDataOperator
#define FTENSOR_INDEX(DIM, I)
constexpr double a
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'l', 3 > l
constexpr auto field_name
FTensor::Index< 'm', 3 > m
virtual moab::Interface & get_moab()=0
std::array< bool, MBMAXTYPE > doEntities
If true operator is executed for entity.
Deprecated interface functions.
@ OPROW
operator doWork function is executed on FE rows
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
boost::shared_ptr< CalculatePK1< double > > materialDoublePtr
Definition Smoother.hpp:227
boost::shared_ptr< CalculatePK1< adouble > > materialAdoublePtr
Definition Smoother.hpp:225
FTensor::Tensor2< FTensor::PackPtr< TYPE *, 0 >, 3, 3 > t_P
Definition Smoother.hpp:246
FTensor::Index< 'i', 3 > i
Definition Smoother.hpp:242
FTensor::Index< 'k', 3 > k
Definition Smoother.hpp:244
virtual MoFEMErrorCode calculateP_PiolaKirchhoffI()
Definition Smoother.hpp:254
MoFEM::VolumeElementForcesAndSourcesCore::UserDataOperator * opPtr
pointer to finite element tetrahedral operator
Definition Smoother.hpp:252
CalculatePK1(const std::string field_name)
Definition Smoother.hpp:237
FTensor::Index< 'j', 3 > j
Definition Smoother.hpp:243
MatrixBoundedArray< TYPE, 9 > F
Definition Smoother.hpp:245
int gG
Gauss point number.
Definition Smoother.hpp:248
CommonData * commonDataPtr
field values at Gauss pts.)
Definition Smoother.hpp:249
MatrixBoundedArray< TYPE, 9 > invF
Definition Smoother.hpp:245
static auto resizeAndSet(MatrixBoundedArray< TYPE, 9 > &m)
Definition Smoother.hpp:260
FTensor::Tensor2< FTensor::PackPtr< TYPE *, 0 >, 3, 3 > t_F
Definition Smoother.hpp:246
MatrixBoundedArray< TYPE, 9 > P
Definition Smoother.hpp:245
FTensor::Tensor2< FTensor::PackPtr< TYPE *, 0 >, 3, 3 > t_invF
Definition Smoother.hpp:246
boost::shared_ptr< MatrixDouble > matTangentPtr
Definition Smoother.hpp:208
std::string meshPositions
Definition Smoother.hpp:210
std::vector< MatrixDouble > sTress
Definition Smoother.hpp:211
std::string spatialPositions
Definition Smoother.hpp:209
boost::shared_ptr< MatrixDouble > matFirstPiolaStressPtr
Definition Smoother.hpp:207
boost::shared_ptr< MatrixDouble > matGradPtr
Definition Smoother.hpp:206
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Definition Smoother.hpp:307
OpJacobianSmoother(const std::string field_name, BlockData &data, CommonData &common_data, int tag, bool jacobian)
Definition Smoother.hpp:300
MyVolumeFE & feLhs
calculate left hand side for tetrahedral elements
Definition Smoother.hpp:281
BiLinearForm::OpGradTensorGrad< 1, 3, 3, 1 > OpKPiola
Definition Smoother.hpp:203
MyVolumeFE & getLoopFeLhs()
get lhs volume element
Definition Smoother.hpp:282
std::map< int, BlockData > setOfBlocks
Definition Smoother.hpp:230
Smoother(MoFEM::Interface &m_field)
Definition Smoother.hpp:284
CommonData commonData
Definition Smoother.hpp:232
boost::shared_ptr< MyVolumeFE > feLhsPtr
Definition Smoother.hpp:277
static MoFEMErrorCode extractMeshEdges(MoFEM::Interface &m_field, Range &output_edges, Range &output_vertices)
Definition Smoother.hpp:10
MyVolumeFE & getLoopFeRhs()
get rhs volume element
Definition Smoother.hpp:280
LinearForm::OpGradTimesTensor< 1, 3, 3 > OpInternalForcePiola
Definition Smoother.hpp:202
boost::shared_ptr< MyVolumeFE > feRhsPtr
Definition Smoother.hpp:276
MyVolumeFE & feRhs
calculate right hand side for tetrahedral elements
Definition Smoother.hpp:279