v0.16.0
Loading...
Searching...
No Matches
AdaptiveOrderRef.hpp
Go to the documentation of this file.
1/**
2 * @file AdaptiveOrderRef.hpp
3 * @brief Calculate error indicators
4 * @date 2024-04-14
5 *
6 * @copyright Copyright (c) 2025
7 *
8 */
9
10static MoFEMErrorCode getTagHandle(MoFEM::Interface &m_field, const char *name,
11 DataType type, Tag &tag_handle) {
13 int int_val = 0;
14 double double_val = 0;
15 switch (type) {
16 case MB_TYPE_INTEGER:
17 CHKERR m_field.get_moab().tag_get_handle(
18 name, 1, type, tag_handle, MB_TAG_CREAT | MB_TAG_SPARSE, &int_val);
19 break;
20 case MB_TYPE_DOUBLE:
21 CHKERR m_field.get_moab().tag_get_handle(
22 name, 1, type, tag_handle, MB_TAG_CREAT | MB_TAG_SPARSE, &double_val);
23 break;
24 default:
25 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
26 "Wrong data type %d for tag", type);
27 }
29}
30
31static MoFEMErrorCode getDomainEntsPart(MoFEM::Interface &m_field,
32 Range &domain_ents_part) {
34 auto simple = m_field.getInterface<Simple>();
35 Range domain_ents;
36 CHKERR m_field.get_moab().get_entities_by_dimension(simple->getMeshset(),
37 SPACE_DIM, domain_ents);
38 ParallelComm *pcomm =
39 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
40 CHKERR pcomm->filter_pstatus(domain_ents, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
41 &domain_ents_part);
43}
44
45static MoFEMErrorCode copyTagOnSkin(MoFEM::Interface &m_field, const char *name,
46 DataType type) {
48 auto simple = m_field.getInterface<Simple>();
49
50 Range all_boundary_ents;
51 CHKERR m_field.get_moab().get_entities_by_handle(simple->getBoundaryMeshSet(),
52 all_boundary_ents);
53
54 Range domain_ents_part;
55 CHKERR getDomainEntsPart(m_field, domain_ents_part);
56 Range domain_faces, boundary_faces;
57 CHKERR m_field.get_moab().get_adjacencies(domain_ents_part, SPACE_DIM - 1,
58 true, domain_faces,
59 moab::Interface::UNION);
60 boundary_faces = intersect(domain_faces, all_boundary_ents);
61
62 Tag th;
63 CHKERR getTagHandle(m_field, name, type, th);
64
65 for (auto &face_ent : boundary_faces) {
66 Range adj_tet;
67 CHKERR m_field.get_moab().get_adjacencies(&face_ent, 1, SPACE_DIM, true,
68 adj_tet, moab::Interface::UNION);
69 if (adj_tet.size() != 1)
72 "There should be only one ent adjacent to the boundary ent");
73
74 std::variant<int, double> data;
75
76 switch (type) {
77 case MB_TYPE_INTEGER:
78 data = int{};
79 break;
80 case MB_TYPE_DOUBLE:
81 data = double{};
82 break;
83 default:
84 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
85 "Wrong data type %d for tag", type);
86 }
87
88 std::visit(
89 [&](auto &val) {
90 CHKERR m_field.get_moab().tag_get_data(th, adj_tet, &val);
91 CHKERR m_field.get_moab().tag_set_data(th, &face_ent, 1, &val);
92 },
93 data);
94 }
95
97}
98
101 boost::shared_ptr<MatrixDouble> stress_ptr,
102 boost::shared_ptr<MatrixDouble> traction_ptr)
103 : SideEleOp(field_name, SideEleOp::OPROW, false), stressPtr(stress_ptr),
104 tractionJumpPtr(traction_ptr) {
105 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
106 doEntities[MBVERTEX] = true;
107 }
108
109 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
113 auto nb_gauss_pts = getGaussPts().size2();
114
115 // auto n_total_side_eles = getLoopSize();
116 auto n_InLoop = getNinTheLoop();
117 auto e_sense = getSkeletonSense();
118
119 if (n_InLoop == 0) {
120 tractionJumpPtr->resize(nb_gauss_pts, SPACE_DIM, false);
121 tractionJumpPtr->clear();
122 }
123
124 auto t_normal = getFTensor1NormalsAtGaussPts();
125 auto t_stress = getFTensor2SymmetricFromMat<SPACE_DIM>(*stressPtr);
126 auto t_traction = getFTensor1FromMat<SPACE_DIM>(*tractionJumpPtr);
127
128 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
129 FTensor::Tensor1<double, 3> t_unit_normal;
130 t_unit_normal(i) = t_normal(i);
131 t_unit_normal.normalize();
132
133 t_traction(i) -= e_sense * (t_stress(i, j) * t_unit_normal(j));
134
135 ++t_normal;
136 ++t_stress;
137 ++t_traction;
138 }
140 }
141
142private:
143 boost::shared_ptr<MatrixDouble> stressPtr;
144 boost::shared_ptr<MatrixDouble> tractionJumpPtr;
145};
146
147MoFEMErrorCode ElasticAdaptiveExample::refineOrder(int ref_level) {
149 auto simple = mField.getInterface<Simple>();
150 auto comm = mField.getInterface<CommInterface>();
151
152 CHKERR PetscOptionsGetReal(PETSC_NULLPTR, "", "-ref_adapt_threshold",
153 &refAdaptThreshold, PETSC_NULLPTR);
154
155 Tag th_error_ind, th_order;
156 CHKERR getTagHandle(mField, "SOLUTION_ERROR", MB_TYPE_DOUBLE, th_error_ind);
157 CHKERR getTagHandle(mField, "ORDER", MB_TYPE_INTEGER, th_order);
158
159 std::vector<Range> refinement_levels(ref_level + 2);
160
161 Range domain_ents_part;
162 CHKERR getDomainEntsPart(mField, domain_ents_part);
163
164 for (auto ent : domain_ents_part) {
165 double err_indic = 0;
166 CHKERR mField.get_moab().tag_get_data(th_error_ind, &ent, 1, &err_indic);
167 int order;
168 CHKERR mField.get_moab().tag_get_data(th_order, &ent, 1, &order);
169
170 if (err_indic > refAdaptThreshold * errorIndicMean) {
171 order += 1;
172 refinement_levels[order - oRder].insert(ent);
173 }
174 }
175
176 for (int ll = refinement_levels.size() - 1; ll > 1; ll--) {
177 CHKERR comm->synchroniseEntities(refinement_levels[ll]);
178
179 Range face_ents;
180 CHKERR mField.get_moab().get_adjacencies(refinement_levels[ll],
181 SPACE_DIM - 1, true, face_ents,
182 moab::Interface::UNION);
183 Range tets;
184 CHKERR mField.get_moab().get_adjacencies(face_ents, SPACE_DIM, true, tets,
185 moab::Interface::UNION);
186 tets = subtract(tets, refinement_levels[ll]);
187 refinement_levels[ll - 1].merge(tets);
188 }
189
190 for (int ll = 1; ll < refinement_levels.size(); ll++) {
191
192 if (oRder + ll > 8) {
193 MOFEM_LOG("WORLD", Sev::warning)
194 << "setting approximation order higher than 8 is not currently "
195 "supported"
196 << endl;
197 } else {
198
199 for (auto ent : refinement_levels[ll]) {
200 int order = oRder + ll;
201 CHKERR mField.get_moab().tag_set_data(th_order, &ent, 1, &order);
202 }
203
204 Range ents_to_refine;
205 ents_to_refine.merge(refinement_levels[ll]);
206 for (int d = 1; d < SPACE_DIM; ++d) {
207 Range lower_dim_ents;
208 CHKERR mField.get_moab().get_adjacencies(refinement_levels[ll], d, true,
209 lower_dim_ents,
210 moab::Interface::UNION);
211 ents_to_refine.merge(lower_dim_ents);
212 }
213
214 CHKERR comm->synchroniseEntities(ents_to_refine);
215
216 CHKERR simple->setFieldOrder("U", oRder + ll, &ents_to_refine);
217 }
218 }
219
220 CHKERR copyTagOnSkin(mField, "ORDER", MB_TYPE_INTEGER);
221
222 CHKERR comm->synchroniseFieldEntities("U");
223 CHKERR simple->reSetUp();
224
226
228}
229
232 PipelineManager *pipeline_mng = mField.getInterface<PipelineManager>();
233 auto simple = mField.getInterface<Simple>();
234
235 Tag th_error_ind;
236 CHKERR getTagHandle(mField, "SOLUTION_ERROR", MB_TYPE_DOUBLE, th_error_ind);
237
238 pipeline_mng->getSkeletonRhsFE().reset();
239
240 auto integration_rule = [](int, int, int p_data) { return 2 * p_data + 1; };
241 CHKERR pipeline_mng->setSkeletonRhsIntegrationRule(integration_rule);
242
243 auto op_loop_side =
244 new OpLoopSide<SideEle>(mField, simple->getDomainFEName(), SPACE_DIM);
245
247 op_loop_side->getOpPtrVector(), {H1}, "GEOMETRY");
248
249 // Use HookeOps commonDataFactory to get matStrainPtr and matCauchyStressPtr
250 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEle>(
251 mField, op_loop_side->getOpPtrVector(), "U", "MAT_ELASTIC", Sev::verbose);
252
253 auto mat_jump_ptr = boost::make_shared<MatrixDouble>();
254 op_loop_side->getOpPtrVector().push_back(new OpCalculateTractionJump(
255 "U", common_ptr->getMatCauchyStress(), mat_jump_ptr));
256
257 auto *op_ptr = new BoundaryEleOp(NOSPACE, BoundaryEleOp::OPSPACE);
258 op_ptr->doWorkRhsHook = [&](DataOperator *base_op_ptr, int side,
259 EntityType type,
260 EntitiesFieldData::EntData &data) {
263 auto op_ptr = static_cast<BoundaryEleOp *>(base_op_ptr);
264 auto fe_ent = op_ptr->getFEEntityHandle();
265
266 auto t_jump = getFTensor1FromMat<SPACE_DIM>(*mat_jump_ptr);
267 auto t_w = op_ptr->getFTensor0IntegrationWeight();
268 double err_int = 0;
269 const auto nb_gauss_pts = op_ptr->getGaussPts().size2();
270 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
271 err_int += t_w * (t_jump(i) * t_jump(i));
272 ++t_jump;
273 ++t_w;
274 }
275 double err_measure = sqrt(err_int);
276 CHKERR mField.get_moab().tag_set_data(th_error_ind, &fe_ent, 1,
277 &err_measure);
278
280 };
281
282 pipeline_mng->getOpSkeletonRhsPipeline().push_back(op_loop_side);
283 pipeline_mng->getOpSkeletonRhsPipeline().push_back(op_ptr);
284
285 Range fe_ents;
286 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM - 1, fe_ents);
287 double zero = 0;
288 CHKERR mField.get_moab().tag_clear_data(th_error_ind, fe_ents, &zero);
289
290 CHKERR DMoFEMLoopFiniteElements(simple->getDM(), simple->getSkeletonFEName(),
291 pipeline_mng->getSkeletonRhsFE());
292
293 pipeline_mng->getSkeletonRhsFE().reset();
294
295 Range domain_ents_part;
296 CHKERR getDomainEntsPart(mField, domain_ents_part);
297
298 ParallelComm *pcomm =
299 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
300 Range empty_range;
301 CHKERR pcomm->reduce_tags(th_error_ind, MPI_SUM, empty_range);
302
303 std::array<double, 3> error_indic_loc = {0.0, 0.0, 0.0};
304
305 for (auto domain_ent : domain_ents_part) {
306 Range face_ents;
307 CHKERR mField.get_moab().get_adjacencies(
308 &domain_ent, 1, SPACE_DIM - 1, true, face_ents, moab::Interface::UNION);
309
310 double err_indic_sum = 0;
311 for (auto face_ent : face_ents) {
312 double err_indic = 0;
313 CHKERR mField.get_moab().tag_get_data(th_error_ind, &face_ent, 1,
314 &err_indic);
315 err_indic_sum += err_indic;
316 }
317 CHKERR mField.get_moab().tag_set_data(th_error_ind, &domain_ent, 1,
318 &err_indic_sum);
319
320 error_indic_loc[IndicInds::ERROR_TOT] += err_indic_sum;
321
322 const EntityHandle *vert_conn;
323 int vert_num;
324 CHKERR mField.get_moab().get_connectivity(domain_ent, vert_conn, vert_num,
325 true);
326 std::vector<double> vpos(3 * vert_num);
327 CHKERR mField.get_moab().get_coords(vert_conn, vert_num, &vpos[0]);
328 double vol = Tools::tetVolume(vpos.data());
329
330 error_indic_loc[IndicInds::ERROR_NORM] += err_indic_sum * vol;
331 }
332
333 CHKERR copyTagOnSkin(mField, "SOLUTION_ERROR", MB_TYPE_DOUBLE);
334
335 error_indic_loc[IndicInds::COUNT_ENTS] =
336 static_cast<double>(domain_ents_part.size());
337
338 std::array<double, 3> error_indic_glob = {0.0, 0.0, 0.0};
339
340 MPI_Allreduce(&error_indic_loc[0], &error_indic_glob[0], 3, MPI_DOUBLE,
341 MPI_SUM, mField.get_comm());
342
343 errorIndicMean = error_indic_glob[IndicInds::ERROR_TOT] /
344 error_indic_glob[IndicInds::COUNT_ENTS];
345
346 MOFEM_LOG("WORLD", Sev::inform) << "Global error indicator (norm): "
347 << error_indic_glob[IndicInds::ERROR_NORM];
348 MOFEM_LOG("WORLD", Sev::inform)
349 << "Global error indicator (mean): " << errorIndicMean;
350
352}
static MoFEMErrorCode getTagHandle(MoFEM::Interface &m_field, const char *name, DataType type, Tag &tag_handle)
static MoFEMErrorCode getDomainEntsPart(MoFEM::Interface &m_field, Range &domain_ents_part)
static MoFEMErrorCode copyTagOnSkin(MoFEM::Interface &m_field, const char *name, DataType type)
std::string type
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
constexpr int SPACE_DIM
BoundaryEle::UserDataOperator BoundaryEleOp
Tensor1< T, Tensor_Dim > normalize()
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
@ NOSPACE
Definition definitions.h:83
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ 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.
constexpr int order
auto integration_rule
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
constexpr auto field_name
MoFEMErrorCode refineOrder(int ref_level)
MoFEMErrorCode computeErrorIndicators()
MoFEM::Interface & mField
MoFEMErrorCode boundaryCondition()
[Set up problem]
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
boost::shared_ptr< MatrixDouble > tractionJumpPtr
OpCalculateTractionJump(const std::string field_name, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > traction_ptr)
boost::shared_ptr< MatrixDouble > stressPtr