MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
mesh_operators.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "mesh_operators.hpp"
13#include "pmesh.hpp"
14
15namespace mfem
16{
17
19{
20 // delete in reverse order
21 for (int i = sequence.Size()-1; i >= 0; i--)
22 {
23 delete sequence[i];
24 }
25}
26
28{
29 if (sequence.Size() == 0) { return NONE; }
30next_step:
31 step = (step + 1) % sequence.Size();
32 bool last = (step == sequence.Size() - 1);
33 int mod = sequence[step]->ApplyImpl(mesh);
34 switch (mod & MASK_ACTION)
35 {
36 case NONE: if (last) { return NONE; } goto next_step;
37 case CONTINUE: return last ? mod : (REPEAT | (mod & MASK_INFO));
38 case STOP: return STOP;
39 case REPEAT: --step; return mod;
40 }
41 return NONE;
42}
43
45{
46 for (int i = 0; i < sequence.Size(); i++)
47 {
48 sequence[i]->Reset();
49 }
50 step = 0;
51}
52
53
55 : estimator(est)
56{
59 total_err_goal = 0.0;
60 total_fraction = 0.5;
61 local_err_goal = 0.0;
62 max_elements = std::numeric_limits<long long>::max();
63
64 threshold = 0.0;
66
67 non_conforming = -1;
68 nc_limit = 0;
69}
70
71real_t ThresholdRefiner::GetNorm(const Vector &local_err, Mesh &mesh) const
72{
73#ifdef MFEM_USE_MPI
74 ParMesh *pmesh = dynamic_cast<ParMesh*>(&mesh);
75 if (pmesh)
76 {
77 return ParNormlp(local_err, total_norm_p, pmesh->GetComm());
78 }
79#endif
80 return local_err.Normlp(total_norm_p);
81}
82
84 Array<Refinement> & refinements)
85{
86 threshold = 0.0;
88 refinements.SetSize(0);
89
90 const long long num_elements = mesh.GetGlobalNE();
91 if (num_elements >= max_elements) { return STOP; }
92
93 const int NE = mesh.GetNE();
94 const Vector &local_err = estimator.GetLocalErrors();
95 MFEM_ASSERT(local_err.Size() == NE, "invalid size of local_err");
96
97 const real_t total_err = GetNorm(local_err, mesh);
98 if (total_err <= total_err_goal) { return STOP; }
99
100 if (total_norm_p < infinity())
101 {
102 threshold = std::max((real_t) (total_err * total_fraction *
103 std::pow(num_elements, -1.0/total_norm_p)),
105 }
106 else
107 {
108 threshold = std::max(total_err * total_fraction, local_err_goal);
109 }
110
111 for (int el = 0; el < NE; el++)
112 {
113 if (local_err(el) > threshold)
114 {
115 refinements.Append(Refinement(el));
116 }
117 }
118
119 if (aniso_estimator)
120 {
121 const Array<int> &aniso_flags = aniso_estimator->GetAnisotropicFlags();
122 if (aniso_flags.Size() > 0)
123 {
124 for (int i = 0; i < refinements.Size(); i++)
125 {
126 Refinement &ref = refinements[i];
127 ref.SetType(aniso_flags[ref.index]);
128 }
129 }
130 }
131
132 return NONE;
133}
134
136{
137 const int action = MarkWithoutRefining(mesh, marked_elements);
138 if (action == STOP) { return STOP; }
139
141 if (num_marked_elements == 0LL) { return STOP; }
142
144 return static_cast<int>(CONTINUE) + static_cast<int>(REFINED);
145}
146
148{
151 // marked_elements.SetSize(0); // not necessary
152}
153
154
156{
157 if (mesh.Conforming()) { return NONE; }
158
159 const Vector &local_err = estimator.GetLocalErrors();
160 bool derefs = mesh.DerefineByError(local_err, threshold, nc_limit, op);
161
162 return derefs ? static_cast<int>(CONTINUE) + static_cast<int>(DEREFINED) : NONE;
163}
164
165
167{
168 int max_it = 1;
169 return PreprocessMesh(mesh, max_it);
170}
171
173{
174 int rank = 0;
175 MFEM_VERIFY(max_it > 0, "max_it must be strictly positive")
176
177 int dim = mesh.Dimension();
178 L2_FECollection l2fec(order, dim);
179 FiniteElementSpace* l2fes = NULL;
180
181 bool par = false;
182 GridFunction *gf = NULL;
183
184#ifdef MFEM_USE_MPI
185 ParMesh* pmesh = dynamic_cast<ParMesh*>(&mesh);
186 if (pmesh && pmesh->Nonconforming())
187 {
188 par = true;
189 l2fes = new ParFiniteElementSpace(pmesh, &l2fec);
190 gf = new ParGridFunction(static_cast<ParFiniteElementSpace*>(l2fes));
191 }
192#endif
193 if (!par)
194 {
195 l2fes = new FiniteElementSpace(&mesh, &l2fec);
196 gf = new GridFunction(l2fes);
197 }
198
199 // If custom integration rule has not been set,
200 // then use the default integration rule
201 if (!irs)
202 {
203 int order_quad = 2*order + 3;
204 for (int i=0; i < Geometry::NumGeom; ++i)
205 {
206 ir_default[i] = &(IntRules.Get(i, order_quad));
207 }
208 irs = ir_default;
209 }
210
211 for (int i = 0; i < max_it; i++)
212 {
213 // Compute number of elements and L2-norm of f.
214 int NE = mesh.GetNE();
215 int globalNE = 0;
216 real_t norm_of_coeff = 0.0;
217 if (par)
218 {
219#ifdef MFEM_USE_MPI
220 globalNE = pmesh->GetGlobalNE();
221 norm_of_coeff = ComputeGlobalLpNorm(2.0,*coeff,*pmesh,irs);
222#endif
223 }
224 else
225 {
226 globalNE = NE;
227 norm_of_coeff = ComputeLpNorm(2.0,*coeff,mesh,irs);
228 }
229
230 // Compute average L2-norm of f
231 real_t av_norm_of_coeff = norm_of_coeff / sqrt(globalNE);
232
233 // Compute element-wise L2-norms of (I - Π) f
234 Vector element_norms_of_fine_scale(NE);
235 gf->SetSpace(l2fes);
237 gf->ComputeElementL2Errors(*coeff,element_norms_of_fine_scale,irs);
238
239 // Define osc_K(f) := || h ⋅ (I - Π) f ||_K and select elements
240 // for refinement based on threshold. Also record relative osc(f).
241 global_osc = 0.0;
245 element_oscs = 0.0;
246 for (int j = 0; j < NE; j++)
247 {
248 real_t h = mesh.GetElementSize(j);
249 real_t element_osc = h * element_norms_of_fine_scale(j);
250 if ( element_osc > threshold * av_norm_of_coeff )
251 {
253 }
254 element_oscs(j) = element_osc/(norm_of_coeff + 1e-10);
255 global_osc += element_osc*element_osc;
256 }
257#ifdef MFEM_USE_MPI
258 if (par)
259 {
260 MPI_Comm comm = pmesh->GetComm();
261 MPI_Allreduce(MPI_IN_PLACE, &global_osc, 1, MPITypeMap<real_t>::mpi_type,
262 MPI_SUM, comm);
263 MPI_Comm_rank(comm, &rank);
264 }
265#endif
266 global_osc = sqrt(global_osc)/(norm_of_coeff + 1e-10);
267
268 // Exit if the global threshold or maximum number of elements is reached.
270 {
271 if (global_osc > threshold && globalNE > max_elements && rank == 0 &&
273 {
274 MFEM_WARNING("Reached maximum number of elements "
275 "before resolving data to tolerance.");
276 }
277 delete l2fes;
278 delete gf;
279 return STOP;
280 }
281
282 // Refine elements.
284 l2fes->Update(false);
285 gf->Update();
286
287 }
288 delete l2fes;
289 delete gf;
290 return static_cast<int>(CONTINUE) + static_cast<int>(REFINED);
291
292}
293
295{
297 global_osc = 0.0;
298 coeff = NULL;
299 irs = NULL;
300}
301
302
304{
305#ifdef MFEM_USE_MPI
306 ParMesh *pmesh = dynamic_cast<ParMesh*>(&mesh);
307 if (pmesh && pmesh->Nonconforming())
308 {
309 pmesh->Rebalance();
310 return static_cast<int>(CONTINUE) + static_cast<int>(REBALANCED);
311 }
312#endif
313 return NONE;
314}
315
316
317} // namespace mfem
The AnisotropicErrorEstimator class is the base class for all error estimators that compute one non-n...
virtual const Array< int > & GetAnisotropicFlags()=0
Get an Array<int> with anisotropic flags for all mesh elements.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:869
int Size() const
Return the logical size of the array.
Definition array.hpp:192
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:941
const IntegrationRule * ir_default[Geometry::NumGeom]
virtual int PreprocessMesh(Mesh &mesh, int max_it)
Apply the operator to the mesh max_it times or until tolerance achieved.
const IntegrationRule ** irs
void Reset() override
Reset.
int ApplyImpl(Mesh &mesh) override
Apply the operator to the mesh once.
Base class for all element based error estimators.
virtual void Reset()=0
Force recomputation of the estimates on the next call to GetLocalErrors.
virtual const Vector & GetLocalErrors()=0
Get a Vector with all element errors.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
virtual void Update(bool want_transform=true)
Reflect changes in the mesh: update number of DOFs, etc. Also, calculate GridFunction transformation ...
Definition fespace.cpp:4192
static const int NumGeom
Definition geom.hpp:46
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
virtual void ComputeElementL2Errors(Coefficient &exsol, Vector &error, const IntegrationRule *irs[]=NULL) const
Returns ||u_ex - u_h||_L2 elementwise for H1 or L2 elements.
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition gridfunc.cpp:169
virtual void ProjectCoefficient(Coefficient &coeff, ProjectType type=ProjectType::DEFAULT)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
virtual void SetSpace(FiniteElementSpace *f)
Associate a new FiniteElementSpace with the GridFunction.
Definition gridfunc.cpp:227
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:369
Array< MeshOperator * > sequence
MeshOperators sequence, owned by us.
int ApplyImpl(Mesh &mesh) override
Apply the MeshOperatorSequence.
virtual ~MeshOperatorSequence()
Delete all operators from the sequence.
void Reset() override
Reset all MeshOperators in the sequence.
@ MASK_ACTION
bit mask for all "action" bits
@ STOP
a stopping criterion was satisfied
@ MASK_INFO
bit mask for all "info" bits
@ REFINED
the mesh was refined
@ REBALANCED
the mesh was rebalanced
@ DEREFINED
the mesh was de-refined
Mesh data type.
Definition mesh.hpp:67
virtual long long ReduceInt(int value) const
Utility function: sum integers from all processors (Allreduce).
Definition mesh.hpp:2771
bool Conforming() const
Definition mesh.cpp:16102
void GeneralRefinement(const Array< Refinement > &refinements, int nonconforming=-1, int nc_limit=0)
Definition mesh.cpp:11713
bool Nonconforming() const
Definition mesh.hpp:2539
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1390
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
real_t GetElementSize(int i, int type=0)
Get the size of the i-th element relative to the perfect reference element.
Definition mesh.cpp:111
bool DerefineByError(Array< real_t > &elem_error, real_t threshold, int nc_limit=0, int op=1)
Definition mesh.cpp:11447
long long GetGlobalNE() const
Return the total (global) number of elements.
Definition mesh.hpp:1419
Abstract parallel finite element space.
Definition pfespace.hpp:31
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:35
MPI_Comm GetComm() const
Definition pmesh.hpp:403
void Rebalance()
Definition pmesh.cpp:4056
int ApplyImpl(Mesh &mesh) override
Rebalance a parallel mesh (only non-conforming parallel meshes are supported).
int ApplyImpl(Mesh &mesh) override
Apply the operator to the mesh.
Array< Refinement > marked_elements
ThresholdRefiner(ErrorEstimator &est)
Construct a ThresholdRefiner using the given ErrorEstimator.
AnisotropicErrorEstimator * aniso_estimator
void Reset() override
Reset the associated estimator.
int MarkWithoutRefining(Mesh &mesh, Array< Refinement > &refinements)
Set the array refinements of elements to refine, without refining.
real_t GetNorm(const Vector &local_err, Mesh &mesh) const
ErrorEstimator & estimator
int ApplyImpl(Mesh &mesh) override
Apply the operator to the mesh.
Vector data type.
Definition vector.hpp:82
void Destroy()
Destroy a vector.
Definition vector.hpp:722
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
real_t Normlp(real_t p) const
Returns the l_p norm of the vector.
Definition vector.cpp:1032
int dim
Definition ex24.cpp:53
real_t ParNormlp(const Vector &vec, real_t p, MPI_Comm comm)
Compute the l_p norm of the Vector which is split without overlap across the given communicator.
Definition hypre.cpp:482
real_t ComputeGlobalLpNorm(real_t p, Coefficient &coeff, ParMesh &pmesh, const IntegrationRule *irs[])
Compute the global Lp norm of a function f. .
real_t ComputeLpNorm(real_t p, Coefficient &coeff, Mesh &mesh, const IntegrationRule *irs[])
Compute the Lp norm of a function f. .
float real_t
Definition config.hpp:46
constexpr real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition vector.hpp:47
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:549
Helper struct to convert a C++ type to an MPI type.
int index
Mesh element number.
Definition ncmesh.hpp:42
void SetType(char type, real_t scale=0.5)
Set the type and scale, assuming the element is already set.
Definition ncmesh.cpp:596