v0.16.0
Loading...
Searching...
No Matches
HighOrderGeometryRef.hpp
Go to the documentation of this file.
1/**
2 * @file HighOrderGeometryRef.hpp
3 * @brief Higher Order Geometry refinement
4 * @date 2025-05-1
5 *
6 * @copyright Copyright (c) 2025
7 *
8 */
9
10/**
11 * @brief Calculate geometry error and save on a tag
12 */
13
16 auto simple = mField.getInterface<Simple>();
17
18 double def_val_tag = 0.0;
19 Tag tag_err;
20 CHKERR mField.get_moab().tag_get_handle("GEOMETRY_ERROR", 1, MB_TYPE_DOUBLE,
21 tag_err, MB_TAG_CREAT | MB_TAG_SPARSE,
22 &def_val_tag);
23
24 auto LoCoordsPtr = boost::make_shared<MatrixDouble>();
25 auto *op_ptr = new BoundaryEleOp(NOSPACE, BoundaryEleOp::OPSPACE);
26 op_ptr->doWorkRhsHook = [&](DataOperator *base_op_ptr, int side,
27 EntityType type,
28 EntitiesFieldData::EntData &data) {
30 auto op_ptr = static_cast<BoundaryEleOp *>(base_op_ptr);
31 *LoCoordsPtr = op_ptr->getCoordsAtGaussPts();
33 };
34
35 auto *op_ptr_ho = new BoundaryEleOp(NOSPACE, BoundaryEleOp::OPSPACE);
36 op_ptr_ho->doWorkRhsHook = [&](DataOperator *base_op_ptr, int side,
37 EntityType type,
38 EntitiesFieldData::EntData &data) {
40 auto op_ptr_ho = static_cast<BoundaryEleOp *>(base_op_ptr);
41 auto fe_ent = op_ptr_ho->getFEEntityHandle();
43 MatrixDouble &lo_mat = *LoCoordsPtr;
44 MatrixDouble &ho_mat = op_ptr_ho->getCoordsAtGaussPts();
45 auto t_lo_coords = getFTensor1FromMat<SPACE_DIM>(lo_mat);
46 auto t_ho_coords = getFTensor1FromMat<SPACE_DIM>(ho_mat);
47 auto t_w = op_ptr_ho->getFTensor0IntegrationWeight();
48 double err_int = 0;
49 const auto nb_gauss_pts = op_ptr_ho->getGaussPts().size2();
50 // E = sqrt( int (x-xh)*(x-xh) da ) / face_area
51 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
52 err_int += t_w * ((t_lo_coords(i) - t_ho_coords(i)) *
53 (t_lo_coords(i) - t_ho_coords(i)));
54 ++t_lo_coords;
55 ++t_ho_coords;
56 ++t_w;
57 }
58 const double err_measure = sqrt(err_int) / op_ptr_ho->getMeasure();
59 if (err_measure > std::numeric_limits<float>::epsilon()) {
60 meanError[IndicInds::ERROR_TOT] += err_measure;
62 }
63
64 CHKERR mField.get_moab().tag_set_data(tag_err, &fe_ent, 1, &err_measure);
65 Range adj_tet;
66 CHKERR mField.get_moab().get_adjacencies(&fe_ent, 1, SPACE_DIM, false,
67 adj_tet);
68 if (adj_tet.size() != 1)
71 "There should be only one ent adjacent to the boundary ent");
72 auto tet_ent = *adj_tet.begin();
73 double tet_err_measure = 0;
74 CHKERR mField.get_moab().tag_get_data(tag_err, &tet_ent, 1,
75 &tet_err_measure);
76 if (err_measure > tet_err_measure) {
77 CHKERR mField.get_moab().tag_set_data(tag_err, &tet_ent, 1, &err_measure);
78 }
79
81 };
82
83 auto fe = boost::make_shared<BoundaryEle>(mField);
84 fe->getOpPtrVector().push_back(op_ptr);
85
87 fe->getOpPtrVector(), {NOSPACE}, "GEOMETRY");
88 fe->getOpPtrVector().push_back(op_ptr_ho);
89 auto dm = simple->getDM();
91 DMoFEMLoopFiniteElements(dm, simple->getBoundaryFEName(), fe),
92 "calc metric");
93
95}
96
99 auto simple = mField.getInterface<Simple>();
100
101 CHKERR PetscOptionsGetReal(PETSC_NULLPTR, "", "-ref_geom_threshold",
102 &refGeomThreshold, PETSC_NULLPTR);
103
104 if (Tag tag_err = 0; mField.get_moab().tag_get_handle(
105 "GEOMETRY_ERROR", tag_err) == MB_SUCCESS) {
106
107 std::array<double, 2> mean_error_glob = {0.0, 0.0};
108 MPI_Allreduce(&meanError[0], &mean_error_glob[0], 2, MPI_DOUBLE, MPI_SUM,
109 mField.get_comm());
110 if (mean_error_glob[IndicInds::COUNT_ENTS] > 0) {
111 refGeomThreshold *= (mean_error_glob[IndicInds::ERROR_TOT] /
112 mean_error_glob[IndicInds::COUNT_ENTS]);
113 }
114
115 MOFEM_LOG("WORLD", Sev::inform)
116 << "Geometry refinement threshold = " << refGeomThreshold;
117
118 auto get_ents_to_refine = [&]() {
119 Range outer_ref_ents;
120
121 auto *op_ptr_ref = new BoundaryEleOp(NOSPACE, BoundaryEleOp::OPSPACE);
122 op_ptr_ref->doWorkRhsHook = [&](DataOperator *base_op_ptr, int side,
123 EntityType type,
124 EntitiesFieldData::EntData &data) {
126 auto op_ptr_ref = static_cast<BoundaryEleOp *>(base_op_ptr);
127 auto fe_ent = op_ptr_ref->getFEEntityHandle();
128 double err_measure = 0;
129 CHKERR mField.get_moab().tag_get_data(tag_err, &fe_ent, 1,
130 &err_measure);
131 if (err_measure > refGeomThreshold)
132 outer_ref_ents.insert(fe_ent);
133
135 };
136
137 auto fe = boost::make_shared<BoundaryEle>(mField);
138 fe->getOpPtrVector().push_back(op_ptr_ref);
139 auto dm = simple->getDM();
141 DMoFEMLoopFiniteElements(dm, simple->getBoundaryFEName(), fe),
142 "ref ents");
143 return outer_ref_ents;
144 };
145
146 auto ents_to_ref = get_ents_to_refine();
147
148 Range all_domain_ents;
149 CHKERR mField.get_moab().get_entities_by_handle(simple->getMeshset(),
150 all_domain_ents);
151 Range all_boundary_ents;
152 CHKERR mField.get_moab().get_entities_by_handle(
153 simple->getBoundaryMeshSet(), all_boundary_ents);
154
155 Range tets_to_refine[2];
156 CHKERR mField.get_moab().get_adjacencies(ents_to_ref, SPACE_DIM, false,
157 tets_to_refine[1],
158 moab::Interface::UNION);
159 Range ent_conn;
160 CHKERR mField.get_moab().get_adjacencies(tets_to_refine[1], SPACE_DIM - 1,
161 true, ent_conn,
162 moab::Interface::UNION);
163 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(ent_conn);
164
165 CHKERR mField.get_moab().get_adjacencies(
166 ent_conn, SPACE_DIM, true, tets_to_refine[0], moab::Interface::UNION);
167 tets_to_refine[0] = subtract(tets_to_refine[0], tets_to_refine[1]);
168
169#ifndef NDEBUG
170 CHKERR CutMeshInterface::SaveData(mField.get_moab())(
171 "ents_to_refine_ho_2.vtk", tets_to_refine[0]);
172 CHKERR CutMeshInterface::SaveData(mField.get_moab())(
173 "ents_to_refine_ho_3.vtk", tets_to_refine[1]);
174#endif
175
176 for (int i = 0; i < 2; ++i) {
177 Range ents_to_refine;
178 ents_to_refine.merge(tets_to_refine[i]);
179 for (int d = 1; d < SPACE_DIM; ++d) {
180 Range lower_dim_ents;
181 CHKERR mField.get_moab().get_adjacencies(
182 tets_to_refine[i], d, true, lower_dim_ents, moab::Interface::UNION);
183 ents_to_refine.merge(lower_dim_ents);
184 }
185 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
186 ents_to_refine);
187
188 CHKERR simple->setFieldOrder("U", oRder + i + 1, &ents_to_refine);
189 }
190
191 CHKERR mField.getInterface<CommInterface>()->synchroniseFieldEntities("U");
192 CHKERR simple->reSetUp();
193
194 // save order on tags (volumes and boundary)
195 int orders[] = {oRder, oRder + 1, oRder + 2};
196 Tag tag_order;
197
198 CHKERR getTagHandle(mField, "ORDER", MB_TYPE_INTEGER, tag_order);
199
200 for (int i = 0; i < 2; ++i) {
201 Range adj_faces;
202 CHKERR mField.get_moab().get_adjacencies(tets_to_refine[i], SPACE_DIM - 1,
203 true, adj_faces,
204 moab::Interface::UNION);
205 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
206 adj_faces);
207
208 adj_faces = intersect(adj_faces, all_boundary_ents);
209 CHKERR mField.get_moab().tag_clear_data(tag_order, tets_to_refine[i],
210 &orders[i + 1]);
211 CHKERR mField.get_moab().tag_clear_data(tag_order, adj_faces,
212 &orders[i + 1]);
213 }
214 }
216}
static MoFEMErrorCode getTagHandle(MoFEM::Interface &m_field, const char *name, DataType type, Tag &tag_handle)
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
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
@ NOSPACE
Definition definitions.h:83
#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.
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
MoFEMErrorCode calculateGeometryError()
Calculate geometry error and save on a tag.
std::array< double, 2 > meanError
MoFEM::Interface & mField
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.