v0.16.3
Loading...
Searching...
No Matches
MeshSmoothingOpFactory.hpp
Go to the documentation of this file.
1#ifndef __MESH_SMOOTHING_OP_FACTORY_HPP__
2#define __MESH_SMOOTHING_OP_FACTORY_HPP__
3
4#ifndef WITH_ADOL_C
5 #error "MoFEM need to be compiled with ADOL-C"
6#endif
7
8#include <MoFEM.hpp>
9
11#include <MatOps.hpp>
12#include <MatElastic.hpp>
13
14#include <algorithm>
15#include <limits>
16#include <vector>
17
19
20struct Tags {
21 int smoothingTag = 1;
22 int surfaceTag = 2;
23 int edgeTag = 3;
24};
25
26struct MinQualityOp;
27
28struct Config {
29 std::string geometryField = "MESH_NODE_POSITIONS";
30 std::string meshReferenceField = "NONE";
31 std::string lambdaSurfaceField = "LAMBDA_SURFACE";
32 std::string lambdaEdgeField = "LAMBDA_EDGE";
34 bool enableEdgeSliding = false;
35 bool fixEdgeBlocks = true;
37 double gamma = 0.0;
39};
40
41struct Handles {
43 boost::shared_ptr<MatOps::PhysicalEquations> volQualityPhysicalPtr;
44 boost::shared_ptr<ForcesAndSourcesCore> feSmootherRhs;
45 boost::shared_ptr<ForcesAndSourcesCore> feSmootherLhs;
46 boost::shared_ptr<SurfaceSlidingConstrains> surfaceConstraint;
47 boost::shared_ptr<SurfaceSlidingConstrains::DriverElementOrientation>
49 boost::shared_ptr<EdgeSlidingConstrains> edgeConstraint;
50 boost::shared_ptr<MoFEM::VolumeElementForcesAndSourcesCore> minQualityFe;
51 boost::shared_ptr<double> minQualityValue;
52};
53
55
57
58 MinQualityOp(const std::string &field_name, double *min_quality_ptr)
61 minQualityPtr(min_quality_ptr) {}
62
63 MoFEMErrorCode doWork(int, EntityType type,
64 EntitiesFieldData::EntData &data) {
66 if (type != MBVERTEX)
68 const double q =
69 MoFEM::Tools::volumeLengthQuality(&*data.getFieldData().begin());
70 *minQualityPtr = std::min(*minQualityPtr, q);
72 }
73};
74
75inline MoFEMErrorCode createOperators(MoFEM::Interface &m_field,
76 const Config &cfg,
77 const Range &fixed_vertices,
78 const Range &edge_entities,
79 Handles &handles) {
81
82 handles.m_field_ptr = &m_field;
83
85 using DomainEleOp = DomainEle::UserDataOperator;
86 handles.feSmootherRhs = boost::make_shared<DomainEle>(m_field);
87 handles.feSmootherLhs = boost::make_shared<DomainEle>(m_field);
88
93 cfg.tags.smoothingTag));
94 CHKERR handles.volQualityPhysicalPtr->getOptions(&m_field);
95 CHKERR handles.volQualityPhysicalPtr->recordTape();
96
97 using DomainEleOp =
99 auto &rhs_ops = handles.feSmootherRhs->getOpPtrVector();
100 rhs_ops.clear();
102 template opRhsFactory<PETSC, GAUSS, DomainEleOp>(
103 m_field, rhs_ops, cfg.geometryField, handles.volQualityPhysicalPtr);
104
105 auto &lhs_ops = handles.feSmootherLhs->getOpPtrVector();
106 lhs_ops.clear();
108 template opLhsFactory<PETSC, GAUSS, DomainEleOp>(
109 m_field, lhs_ops, cfg.geometryField, handles.volQualityPhysicalPtr);
110
111 handles.minQualityFe =
112 boost::make_shared<MoFEM::VolumeElementForcesAndSourcesCore>(m_field);
113 handles.minQualityValue =
114 boost::make_shared<double>(std::numeric_limits<double>::max());
115
116 handles.minQualityFe->getOpPtrVector().push_back(
117 new MinQualityOp(cfg.geometryField, handles.minQualityValue.get()));
118
119 if (!fixed_vertices.empty()) {
120 auto *prb_mng = m_field.getInterface<ProblemsManager>();
121 auto *simple = m_field.getInterface<Simple>();
122
123 CHKERR prb_mng->removeDofsOnEntities(
124 simple->getProblemName(), cfg.geometryField, fixed_vertices, 0, 3);
125
126 if (cfg.enableSurfaceSliding &&
127 m_field.check_field(cfg.lambdaSurfaceField)) {
128 CHKERR prb_mng->removeDofsOnEntities(simple->getProblemName(),
130 fixed_vertices, 0, 1);
131 }
132
133 if (cfg.enableEdgeSliding && !cfg.fixEdgeBlocks &&
134 m_field.check_field(cfg.lambdaEdgeField)) {
135 CHKERR prb_mng->removeDofsOnEntities(
136 simple->getProblemName(), cfg.lambdaEdgeField, fixed_vertices, 0, 1);
137 }
138 }
139
140 if (cfg.enableSurfaceSliding) {
141 handles.surfaceOrientation = boost::make_shared<
143 handles.surfaceConstraint = boost::shared_ptr<SurfaceSlidingConstrains>(
144 handles.surfaceOrientation,
145 new SurfaceSlidingConstrains(m_field, *handles.surfaceOrientation));
146 CHKERR handles.surfaceConstraint->setOperators(
148 }
149
150 if (cfg.enableEdgeSliding && !edge_entities.empty() && !cfg.fixEdgeBlocks) {
151 Range tets;
152 CHKERR m_field.get_moab().get_entities_by_type(0, MBTET, tets);
153 Range skin_faces;
154 Skinner skin(&m_field.get_moab());
155 CHKERR skin.find_skin(0, tets, false, skin_faces);
156 if (skin_faces.empty()) {
157 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
158 "No skin faces found for edge constrains");
159 }
160 handles.edgeConstraint = boost::make_shared<EdgeSlidingConstrains>(m_field);
161 CHKERR handles.edgeConstraint->setOperators(cfg.tags.edgeTag, edge_entities,
162 skin_faces, cfg.lambdaEdgeField,
163 cfg.geometryField);
164 }
165
167}
168
169inline MoFEMErrorCode addToSnesDM(DM dm, const Config &cfg,
170 const Handles &handles) {
172 boost::shared_ptr<ForcesAndSourcesCore> null;
173
174 CHKERR DMMoFEMSNESSetFunction(dm, "SMOOTHING", handles.feSmootherRhs, null,
175 null);
176 CHKERR DMMoFEMSNESSetJacobian(dm, "SMOOTHING", handles.feSmootherLhs, null,
177 null);
178
179 if (cfg.enableSurfaceSliding && handles.surfaceConstraint) {
180 CHKERR DMMoFEMSNESSetFunction(
181 dm, "SURFACE_SLIDING", handles.surfaceConstraint->feRhsPtr, null, null);
182 CHKERR DMMoFEMSNESSetJacobian(
183 dm, "SURFACE_SLIDING", handles.surfaceConstraint->feLhsPtr, null, null);
184 }
185
186 if (cfg.enableEdgeSliding && !cfg.fixEdgeBlocks && handles.edgeConstraint) {
187 CHKERR DMMoFEMSNESSetFunction(dm, "EDGE_SLIDING",
188 handles.edgeConstraint->feRhsPtr, null, null);
189 CHKERR DMMoFEMSNESSetJacobian(dm, "EDGE_SLIDING",
190 handles.edgeConstraint->feLhsPtr, null, null);
191 }
192
194}
195
196inline MoFEMErrorCode evaluateMinQuality(DM dm,
197 const std::string &domain_fe_name,
198 const Handles &handles,
199 double &min_quality) {
201
202 if (!handles.minQualityFe || !handles.minQualityValue) {
203 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
204 "Min quality operators are not initialised");
205 }
206
207 *handles.minQualityValue = std::numeric_limits<double>::max();
208 CHKERR DMoFEMLoopFiniteElements(dm, domain_fe_name.c_str(),
209 handles.minQualityFe);
210
211 MoFEM::Interface *m_field_ptr = nullptr;
212 CHKERR DMoFEMGetInterfacePtr(dm, &m_field_ptr);
213 double local_min = *handles.minQualityValue;
214 CHKERR MPI_Allreduce(&local_min, &min_quality, 1, MPI_DOUBLE, MPI_MIN,
215 m_field_ptr->get_comm());
216
218}
219
220inline MoFEMErrorCode updateBarrierGamma(Handles &handles, double gamma) {
222 char gamma_value[64];
223 CHKERR PetscSNPrintf(gamma_value, sizeof(gamma_value), "%.17g", gamma);
224 CHKERR PetscOptionsSetValue(NULL, "-volume_length_gamma", gamma_value);
225 CHKERR handles.volQualityPhysicalPtr->getOptions(handles.m_field_ptr);
226 CHKERR handles.volQualityPhysicalPtr->recordTape();
228}
229
230inline MoFEMErrorCode createSnes(DM dm, SmartPetscObj<SNES> &snes) {
232 MoFEM::Interface *m_field_ptr = nullptr;
233 CHKERR DMoFEMGetInterfacePtr(dm, &m_field_ptr);
234 snes = createSNES(m_field_ptr->get_comm());
235 CHKERR SNESSetFromOptions(snes);
236 CHKERR SNESSetDM(snes, dm);
237 CHKERR SNESSetUp(snes);
239}
240
241inline MoFEMErrorCode
242solveSnes(DM dm, SNES snes,
243 const std::vector<std::string> &zero_vertex_fields = {}) {
245 if (!zero_vertex_fields.empty()) {
246 MoFEM::Interface *m_field_ptr = nullptr;
247 CHKERR DMoFEMGetInterfacePtr(dm, &m_field_ptr);
248 auto field_blas = m_field_ptr->getInterface<FieldBlas>();
249 for (const auto &field_name : zero_vertex_fields) {
250 CHKERR field_blas->setField(0, MBVERTEX, field_name);
251 }
252 }
253
254 auto f = createDMVector(dm);
255 auto d = vectorDuplicate(f);
256 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_FORWARD);
257 CHKERR SNESSolve(snes, f, d);
258 CHKERR DMoFEMMeshToGlobalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
260}
261
262} // namespace MeshSmoothingOps
263
264#endif // __MESH_SMOOTHING_OP_FACTORY_HPP__
ForcesAndSourcesCore::UserDataOperator UserDataOperator
std::string type
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
#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_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 ...
PetscErrorCode DMoFEMMeshToGlobalVector(DM dm, Vec g, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set ghosted vector values on all existing mesh entities
Definition DMMoFEM.cpp:554
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:543
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1250
virtual bool check_field(const std::string &name) const =0
check if field is in database
@ MODEL_3D
Definition MatOps.hpp:209
boost::shared_ptr< PhysicalEquations > createMatOpsPhysicalEquationsPtr(boost::shared_ptr< MatOpsData > mat_ops_data_ptr, int tag)
VolumeLengthQualityType
@ BARRIER_AND_QUALITY
boost::shared_ptr< MatOpsData > createMatOpsDataPtr()
Definition MatOps.cpp:709
MoFEMErrorCode updateBarrierGamma(Handles &handles, double gamma)
MoFEMErrorCode evaluateMinQuality(DM dm, const std::string &domain_fe_name, const Handles &handles, double &min_quality)
MoFEMErrorCode createSnes(DM dm, SmartPetscObj< SNES > &snes)
MoFEMErrorCode solveSnes(DM dm, SNES snes, const std::vector< std::string > &zero_vertex_fields={})
MoFEMErrorCode createOperators(MoFEM::Interface &m_field, const Config &cfg, const Range &fixed_vertices, const Range &edge_entities, Handles &handles)
MoFEMErrorCode addToSnesDM(DM dm, const Config &cfg, const Handles &handles)
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
constexpr auto field_name
double q
static int setTagName(std::string name, int tag=-1)
Definition MatOps.cpp:29
MatOps::VolumeLengthQualityType qualityType
boost::shared_ptr< double > minQualityValue
boost::shared_ptr< MatOps::PhysicalEquations > volQualityPhysicalPtr
boost::shared_ptr< ForcesAndSourcesCore > feSmootherLhs
boost::shared_ptr< EdgeSlidingConstrains > edgeConstraint
boost::shared_ptr< MoFEM::VolumeElementForcesAndSourcesCore > minQualityFe
boost::shared_ptr< SurfaceSlidingConstrains > surfaceConstraint
boost::shared_ptr< ForcesAndSourcesCore > feSmootherRhs
boost::shared_ptr< SurfaceSlidingConstrains::DriverElementOrientation > surfaceOrientation
MinQualityOp(const std::string &field_name, double *min_quality_ptr)
MoFEMErrorCode doWork(int, EntityType type, EntitiesFieldData::EntData &data)
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
Deprecated interface functions.
@ OPROW
operator doWork function is executed on FE rows
static double volumeLengthQuality(const double *coords)
Calculate tetrahedron volume length quality.
Definition Tools.cpp:15
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Class implemented by user to detect face orientation.
Shape preserving constrains, i.e. nodes sliding on body surface.
Implementing surface sliding constrains.