v0.15.5
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
10#include <Smoother.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 alpha = 1.0;
38 double gamma = 0.0;
40};
41
42struct Handles {
43 boost::shared_ptr<Smoother> smoother;
44 boost::shared_ptr<Smoother::MyVolumeFE> feSmootherRhs;
45 boost::shared_ptr<Smoother::MyVolumeFE> feSmootherLhs;
46 boost::shared_ptr<VolumeLengthQuality<double>> qualityDouble;
47 boost::shared_ptr<VolumeLengthQuality<adouble>> qualityAdouble;
48 boost::shared_ptr<SurfaceSlidingConstrains> surfaceConstraint;
49 boost::shared_ptr<SurfaceSlidingConstrains::DriverElementOrientation>
51 boost::shared_ptr<EdgeSlidingConstrains> edgeConstraint;
52 boost::shared_ptr<MoFEM::VolumeElementForcesAndSourcesCore> minQualityFe;
53 boost::shared_ptr<double> minQualityValue;
54};
55
57
59
60 MinQualityOp(const std::string &field_name,
61 double *min_quality_ptr)
64 minQualityPtr(min_quality_ptr) {}
65
66 MoFEMErrorCode doWork(int, EntityType type, EntitiesFieldData::EntData &data) {
68 if (type != MBVERTEX)
70 const double q = MoFEM::Tools::volumeLengthQuality(&*data.getFieldData().begin());
71 *minQualityPtr = std::min(*minQualityPtr, q);
73 }
74};
75
76inline MoFEMErrorCode createOperators(MoFEM::Interface &m_field,
77 const Config &cfg,
78 const Range &fixed_vertices,
79 const Range &edge_entities,
80 Handles &handles) {
82
83 handles.smoother = boost::make_shared<Smoother>(m_field);
84 handles.qualityAdouble = boost::make_shared<VolumeLengthQuality<adouble>>(
85 cfg.qualityType, cfg.alpha, cfg.gamma, cfg.geometryField);
86 handles.qualityDouble = boost::make_shared<VolumeLengthQuality<double>>(
87 cfg.qualityType, cfg.alpha, cfg.gamma, cfg.geometryField);
88
89 Range tets;
90 CHKERR m_field.get_moab().get_entities_by_type(0, MBTET, tets);
91 handles.smoother->setOfBlocks[0].tEts.merge(tets);
92 handles.smoother->setOfBlocks[0].materialDoublePtr = handles.qualityDouble;
93 handles.smoother->setOfBlocks[0].materialAdoublePtr = handles.qualityAdouble;
94
95 handles.smoother->commonData.spatialPositions = cfg.geometryField;
96 handles.smoother->commonData.meshPositions = cfg.meshReferenceField;
97
98 handles.feSmootherRhs = handles.smoother->feRhsPtr;
99 handles.feSmootherLhs = handles.smoother->feLhsPtr;
100
101 auto &rhs_ops = handles.feSmootherRhs->getOpPtrVector();
102 rhs_ops.clear();
103 rhs_ops.push_back(new OpCalculateVectorFieldGradient<3, 3>(
104 cfg.geometryField, handles.smoother->commonData.matGradPtr));
105 rhs_ops.push_back(new Smoother::OpJacobianSmoother(
106 cfg.geometryField, handles.smoother->setOfBlocks.at(0),
107 handles.smoother->commonData, cfg.tags.smoothingTag, false));
108 rhs_ops.push_back(new Smoother::OpInternalForcePiola(
109 cfg.geometryField, handles.smoother->commonData.matFirstPiolaStressPtr));
110
111 auto &lhs_ops = handles.feSmootherLhs->getOpPtrVector();
112 lhs_ops.clear();
113 lhs_ops.push_back(new OpCalculateVectorFieldGradient<3, 3>(
114 cfg.geometryField, handles.smoother->commonData.matGradPtr));
115 lhs_ops.push_back(new Smoother::OpJacobianSmoother(
116 cfg.geometryField, handles.smoother->setOfBlocks.at(0),
117 handles.smoother->commonData, cfg.tags.smoothingTag, true));
118 lhs_ops.push_back(new Smoother::OpKPiola(
119 cfg.geometryField, cfg.geometryField, handles.smoother->commonData.matTangentPtr));
120
121 handles.minQualityFe =
122 boost::make_shared<MoFEM::VolumeElementForcesAndSourcesCore>(m_field);
123 handles.minQualityValue =
124 boost::make_shared<double>(std::numeric_limits<double>::max());
125
126 handles.minQualityFe->getOpPtrVector().push_back(
127 new MinQualityOp(cfg.geometryField, handles.minQualityValue.get()));
128
129 if (!fixed_vertices.empty()) {
130 auto *prb_mng = m_field.getInterface<ProblemsManager>();
131 auto *simple = m_field.getInterface<Simple>();
132
133 CHKERR prb_mng->removeDofsOnEntities(simple->getProblemName(),
134 cfg.geometryField, fixed_vertices, 0,
135 3);
136
137 if (cfg.enableSurfaceSliding && m_field.check_field(cfg.lambdaSurfaceField)) {
138 CHKERR prb_mng->removeDofsOnEntities(simple->getProblemName(),
139 cfg.lambdaSurfaceField, fixed_vertices,
140 0, 1);
141 }
142
143 if (cfg.enableEdgeSliding && !cfg.fixEdgeBlocks &&
144 m_field.check_field(cfg.lambdaEdgeField)) {
145 CHKERR prb_mng->removeDofsOnEntities(simple->getProblemName(),
146 cfg.lambdaEdgeField, fixed_vertices,
147 0, 1);
148 }
149 }
150
151 if (cfg.enableSurfaceSliding) {
152 handles.surfaceOrientation = boost::make_shared<
154 handles.surfaceConstraint = boost::shared_ptr<SurfaceSlidingConstrains>(
155 handles.surfaceOrientation,
156 new SurfaceSlidingConstrains(m_field, *handles.surfaceOrientation));
157 CHKERR handles.surfaceConstraint->setOperators(cfg.tags.surfaceTag,
159 cfg.geometryField);
160 }
161
162 if (cfg.enableEdgeSliding && !edge_entities.empty() && !cfg.fixEdgeBlocks) {
163 Range skin_faces;
164 Skinner skin(&m_field.get_moab());
165 CHKERR skin.find_skin(0, tets, false, skin_faces);
166 if (skin_faces.empty()) {
167 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
168 "No skin faces found for edge constrains");
169 }
170 handles.edgeConstraint = boost::make_shared<EdgeSlidingConstrains>(m_field);
171 CHKERR handles.edgeConstraint->setOperators(
172 cfg.tags.edgeTag, edge_entities, skin_faces, cfg.lambdaEdgeField,
173 cfg.geometryField);
174 }
175
177}
178
179inline MoFEMErrorCode addToSnesDM(DM dm, const Config &cfg,
180 const Handles &handles) {
182 boost::shared_ptr<ForcesAndSourcesCore> null;
183
184 CHKERR DMMoFEMSNESSetFunction(dm, "SMOOTHING", handles.feSmootherRhs, null,
185 null);
186 CHKERR DMMoFEMSNESSetJacobian(dm, "SMOOTHING", handles.feSmootherLhs, null,
187 null);
188
189 if (cfg.enableSurfaceSliding && handles.surfaceConstraint) {
190 CHKERR DMMoFEMSNESSetFunction(dm, "SURFACE_SLIDING",
191 handles.surfaceConstraint->feRhsPtr, null,
192 null);
193 CHKERR DMMoFEMSNESSetJacobian(dm, "SURFACE_SLIDING",
194 handles.surfaceConstraint->feLhsPtr, null,
195 null);
196 }
197
198 if (cfg.enableEdgeSliding && !cfg.fixEdgeBlocks && handles.edgeConstraint) {
199 CHKERR DMMoFEMSNESSetFunction(dm, "EDGE_SLIDING",
200 handles.edgeConstraint->feRhsPtr, null, null);
201 CHKERR DMMoFEMSNESSetJacobian(dm, "EDGE_SLIDING",
202 handles.edgeConstraint->feLhsPtr, null, null);
203 }
204
206}
207
208inline MoFEMErrorCode evaluateMinQuality(DM dm,
209 const std::string &domain_fe_name,
210 const Handles &handles,
211 double &min_quality) {
213
214 if (!handles.minQualityFe || !handles.minQualityValue) {
215 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
216 "Min quality operators are not initialised");
217 }
218
219 *handles.minQualityValue = std::numeric_limits<double>::max();
220 CHKERR DMoFEMLoopFiniteElements(dm, domain_fe_name.c_str(),
221 handles.minQualityFe);
222
223 MoFEM::Interface *m_field_ptr = nullptr;
224 CHKERR DMoFEMGetInterfacePtr(dm, &m_field_ptr);
225 double local_min = *handles.minQualityValue;
226 CHKERR MPI_Allreduce(&local_min, &min_quality, 1, MPI_DOUBLE, MPI_MIN,
227 m_field_ptr->get_comm());
228
230}
231
232inline MoFEMErrorCode updateBarrierGamma(Handles &handles, double gamma) {
234 if (handles.qualityDouble)
235 handles.qualityDouble->gAmma = gamma;
236 if (handles.qualityAdouble)
237 handles.qualityAdouble->gAmma = gamma;
239}
240
241inline MoFEMErrorCode createSnes(DM dm, SmartPetscObj<SNES> &snes) {
243 MoFEM::Interface *m_field_ptr = nullptr;
244 CHKERR DMoFEMGetInterfacePtr(dm, &m_field_ptr);
245 snes = createSNES(m_field_ptr->get_comm());
246 CHKERR SNESSetFromOptions(snes);
247 CHKERR SNESSetDM(snes, dm);
248 CHKERR SNESSetUp(snes);
250}
251
252inline MoFEMErrorCode solveSnes(
253 DM dm, SNES snes,
254 const std::vector<std::string> &zero_vertex_fields = {}) {
256 if (!zero_vertex_fields.empty()) {
257 MoFEM::Interface *m_field_ptr = nullptr;
258 CHKERR DMoFEMGetInterfacePtr(dm, &m_field_ptr);
259 auto field_blas = m_field_ptr->getInterface<FieldBlas>();
260 for (const auto &field_name : zero_vertex_fields) {
261 CHKERR field_blas->setField(0, MBVERTEX, field_name);
262 }
263 }
264
265 auto f = createDMVector(dm);
266 auto d = vectorDuplicate(f);
267 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_FORWARD);
268 CHKERR SNESSolve(snes, f, d);
269 CHKERR DMoFEMMeshToGlobalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
271}
272
273} // namespace MeshSmoothingOps
274
275#endif // __MESH_SMOOTHING_OP_FACTORY_HPP__
ForcesAndSourcesCore::UserDataOperator UserDataOperator
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
#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 DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1234
PetscErrorCode DMoFEMMeshToGlobalVector(DM dm, Vec g, InsertMode mode, ScatterMode scatter_mode)
set ghosted vector values on all existing mesh entities
Definition DMMoFEM.cpp:525
virtual bool check_field(const std::string &name) const =0
check if field is in database
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
VolumeLengthQualityType qualityType
boost::shared_ptr< double > minQualityValue
boost::shared_ptr< Smoother > smoother
boost::shared_ptr< VolumeLengthQuality< double > > qualityDouble
boost::shared_ptr< EdgeSlidingConstrains > edgeConstraint
boost::shared_ptr< MoFEM::VolumeElementForcesAndSourcesCore > minQualityFe
boost::shared_ptr< SurfaceSlidingConstrains > surfaceConstraint
boost::shared_ptr< Smoother::MyVolumeFE > feSmootherLhs
boost::shared_ptr< Smoother::MyVolumeFE > feSmootherRhs
boost::shared_ptr< SurfaceSlidingConstrains::DriverElementOrientation > surfaceOrientation
boost::shared_ptr< VolumeLengthQuality< adouble > > qualityAdouble
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.
BiLinearForm::OpGradTensorGrad< 1, 3, 3, 1 > OpKPiola
Definition Smoother.hpp:203
LinearForm::OpGradTimesTensor< 1, 3, 3 > OpInternalForcePiola
Definition Smoother.hpp:202
Class implemented by user to detect face orientation.
Shape preserving constrains, i.e. nodes sliding on body surface.
VolumeLengthQualityType
@ BARRIER_AND_QUALITY
Implementing surface sliding constrains.
Implementation of Volume-Length-Quality measure with barrier.