www.mooseframework.org
Adaptivity.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "Adaptivity.h"
11 
12 #include "AuxiliarySystem.h"
13 #include "DisplacedProblem.h"
14 #include "FEProblem.h"
15 #include "FlagElementsThread.h"
16 #include "MooseMesh.h"
17 #include "NonlinearSystemBase.h"
19 
20 // libMesh
21 #include "libmesh/equation_systems.h"
22 #include "libmesh/kelly_error_estimator.h"
23 #include "libmesh/patch_recovery_error_estimator.h"
24 #include "libmesh/fourth_error_estimators.h"
25 #include "libmesh/parallel.h"
26 #include "libmesh/error_vector.h"
27 
28 #ifdef LIBMESH_ENABLE_AMR
29 
31  : ConsoleStreamInterface(subproblem.getMooseApp()),
32  PerfGraphInterface(subproblem.getMooseApp().perfGraph(), "Adaptivity"),
33  _subproblem(subproblem),
34  _mesh(_subproblem.mesh()),
35  _mesh_refinement_on(false),
36  _initialized(false),
37  _initial_steps(0),
38  _steps(0),
39  _print_mesh_changed(false),
40  _t(_subproblem.time()),
41  _step(_subproblem.timeStep()),
42  _interval(1),
43  _start_time(-std::numeric_limits<Real>::max()),
44  _stop_time(std::numeric_limits<Real>::max()),
45  _cycles_per_step(1),
46  _use_new_system(false),
47  _max_h_level(0),
48  _recompute_markers_during_cycles(false),
49  _adapt_mesh_timer(registerTimedSection("adaptMesh", 3)),
50  _uniform_refine_timer(registerTimedSection("uniformRefine", 2)),
51  _uniform_refine_with_projection(registerTimedSection("uniformRefineWithProjection", 2)),
52  _update_error_vectors(registerTimedSection("updateErrorVectors", 5))
53 {
54 }
55 
57 
58 void
59 Adaptivity::init(unsigned int steps, unsigned int initial_steps)
60 {
61  // Get the pointer to the DisplacedProblem, this cannot be done at construction because
62  // DisplacedProblem
63  // does not exist at that point.
65 
66  _mesh_refinement = libmesh_make_unique<MeshRefinement>(_mesh);
67  _error = libmesh_make_unique<ErrorVector>();
68 
69  EquationSystems & es = _subproblem.es();
70  es.parameters.set<bool>("adaptivity") = true;
71 
72  _initial_steps = initial_steps;
73  _steps = steps;
74  _mesh_refinement_on = true;
75 
76  _mesh_refinement->set_periodic_boundaries_ptr(
77  _subproblem.getNonlinearSystemBase().dofMap().get_periodic_boundaries());
78 
79  // displaced problem
80  if (_displaced_problem != nullptr)
81  {
82  EquationSystems & displaced_es = _displaced_problem->es();
83  displaced_es.parameters.set<bool>("adaptivity") = true;
84 
86  _displaced_mesh_refinement = libmesh_make_unique<MeshRefinement>(_displaced_problem->mesh());
87 
88  // The periodic boundaries pointer allows the MeshRefinement
89  // object to determine elements which are "topological" neighbors,
90  // i.e. neighbors across periodic boundaries, for the purposes of
91  // refinement.
92  _displaced_mesh_refinement->set_periodic_boundaries_ptr(
93  _subproblem.getNonlinearSystemBase().dofMap().get_periodic_boundaries());
94 
95  // TODO: This is currently an empty function on the DisplacedProblem... could it be removed?
96  _displaced_problem->initAdaptivity();
97  }
98 
99  // indicate the Adaptivity system has been initialized
100  _initialized = true;
101 }
102 
103 void
104 Adaptivity::setErrorEstimator(const MooseEnum & error_estimator_name)
105 {
106  if (error_estimator_name == "KellyErrorEstimator")
107  _error_estimator = libmesh_make_unique<KellyErrorEstimator>();
108  else if (error_estimator_name == "LaplacianErrorEstimator")
109  _error_estimator = libmesh_make_unique<LaplacianErrorEstimator>();
110  else if (error_estimator_name == "PatchRecoveryErrorEstimator")
111  _error_estimator = libmesh_make_unique<PatchRecoveryErrorEstimator>();
112  else
113  mooseError(std::string("Unknown error_estimator selection: ") +
114  std::string(error_estimator_name));
115 }
116 
117 void
118 Adaptivity::setErrorNorm(SystemNorm & sys_norm)
119 {
120  mooseAssert(_error_estimator, "error_estimator not initialized. Did you call init_adaptivity()?");
121  _error_estimator->error_norm = sys_norm;
122 }
123 
124 bool
125 Adaptivity::adaptMesh(std::string marker_name /*=std::string()*/)
126 {
127  TIME_SECTION(_adapt_mesh_timer);
128 
129  // If the marker name is supplied, use it. Otherwise, use the one in _marker_variable_name
130  if (marker_name.empty())
131  marker_name = _marker_variable_name;
132 
133  bool mesh_changed = false;
134 
135  if (_use_new_system)
136  {
137  if (!marker_name.empty()) // Only flag if a marker variable name has been set
138  {
139  _mesh_refinement->clean_refinement_flags();
140 
141  std::vector<Number> serialized_solution;
143  _subproblem.getAuxiliarySystem().solution().localize(serialized_solution);
144 
145  FlagElementsThread fet(_subproblem, serialized_solution, _max_h_level, marker_name);
146  ConstElemRange all_elems(_subproblem.mesh().getMesh().active_elements_begin(),
147  _subproblem.mesh().getMesh().active_elements_end(),
148  1);
149  Threads::parallel_reduce(all_elems, fet);
151  }
152  }
153  else
154  {
155  // Compute the error for each active element
157 
158  // Flag elements to be refined and coarsened
159  _mesh_refinement->flag_elements_by_error_fraction(*_error);
160 
161  if (_displaced_problem)
162  // Reuse the error vector and refine the displaced mesh
163  _displaced_mesh_refinement->flag_elements_by_error_fraction(*_error);
164  }
165 
166  // If the DisplacedProblem is active, undisplace the DisplacedMesh
167  // in preparation for refinement. We can't safely refine the
168  // DisplacedMesh directly, since the Hilbert keys computed on the
169  // inconsistenly-displaced Mesh are different on different
170  // processors, leading to inconsistent Hilbert keys. We must do
171  // this before the undisplaced Mesh is refined, so that the
172  // element and node numbering is still consistent.
173  if (_displaced_problem)
174  _displaced_problem->undisplaceMesh();
175 
176  // Perform refinement and coarsening
177  mesh_changed = _mesh_refinement->refine_and_coarsen_elements();
178 
179  if (_displaced_problem && mesh_changed)
180  {
181 #ifndef NDEBUG
182  bool displaced_mesh_changed =
183 #endif
184  _displaced_mesh_refinement->refine_and_coarsen_elements();
185 
186  // Since the undisplaced mesh changed, the displaced mesh better have changed!
187  mooseAssert(displaced_mesh_changed, "Undisplaced mesh changed, but displaced mesh did not!");
188  }
189 
190  if (mesh_changed && _print_mesh_changed)
191  {
192  _console << "\nMesh Changed:\n";
193  _mesh.printInfo();
194  }
195 
196  return mesh_changed;
197 }
198 
199 bool
201 {
203 }
204 
205 void
207 {
208  mooseAssert(mesh, "Mesh pointer must not be NULL");
209 
210  // NOTE: we are using a separate object here, since adaptivity may not be on, but we need to be
211  // able to do refinements
212  MeshRefinement mesh_refinement(*mesh);
213  unsigned int level = mesh->uniformRefineLevel();
214  mesh_refinement.uniformly_refine(level);
215 }
216 
217 void
219 {
220  TIME_SECTION(_uniform_refine_with_projection);
221 
222  // NOTE: we are using a separate object here, since adaptivity may not be on, but we need to be
223  // able to do refinements
224  MeshRefinement mesh_refinement(_mesh);
225  unsigned int level = _mesh.uniformRefineLevel();
226  MeshRefinement displaced_mesh_refinement(_displaced_problem ? _displaced_problem->mesh() : _mesh);
227 
228  // we have to go step by step so EquationSystems::reinit() won't freak out
229  for (unsigned int i = 0; i < level; i++)
230  {
231  // See comment above about why refining the displaced mesh is potentially unsafe.
232  if (_displaced_problem)
233  _displaced_problem->undisplaceMesh();
234 
235  mesh_refinement.uniformly_refine(1);
236 
237  if (_displaced_problem)
238  displaced_mesh_refinement.uniformly_refine(1);
240  }
241 }
242 
243 void
245 {
246  // check if Adaptivity has been initialized before turning on
247  if (state == true && !_initialized)
248  mooseError("Mesh adaptivity system not available");
249 
250  _mesh_refinement_on = state;
251 }
252 
253 void
254 Adaptivity::setTimeActive(Real start_time, Real stop_time)
255 {
256  _start_time = start_time;
257  _stop_time = stop_time;
258 }
259 
260 void
262 {
263  _use_new_system = true;
264 }
265 
266 void
267 Adaptivity::setMarkerVariableName(std::string marker_field)
268 {
269  _marker_variable_name = marker_field;
270 }
271 
272 void
274 {
275  _initial_marker_variable_name = marker_field;
276 }
277 
278 ErrorVector &
279 Adaptivity::getErrorVector(const std::string & indicator_field)
280 {
281  // Insert or retrieve error vector
282  auto insert_pair = moose_try_emplace(
283  _indicator_field_to_error_vector, indicator_field, libmesh_make_unique<ErrorVector>());
284  return *insert_pair.first->second;
285 }
286 
287 void
289 {
290  TIME_SECTION(_update_error_vectors);
291 
292  // Resize all of the ErrorVectors in case the mesh has changed
293  for (const auto & it : _indicator_field_to_error_vector)
294  {
295  ErrorVector & vec = *(it.second);
296  vec.assign(_mesh.getMesh().max_elem_id(), 0);
297  }
298 
299  // Fill the vectors with the local contributions
301  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), uevt);
302 
303  // Now sum across all processors
304  for (const auto & it : _indicator_field_to_error_vector)
305  _subproblem.comm().sum((std::vector<float> &)*(it.second));
306 }
307 
308 bool
310 {
311  return _mesh_refinement_on && (_start_time <= _t && _t < _stop_time) && _step % _interval == 0;
312 }
313 
314 #endif // LIBMESH_ENABLE_AMR
bool adaptMesh(std::string marker_name=std::string())
Adapts the mesh based on the error estimator used.
Definition: Adaptivity.C:125
bool initialAdaptMesh()
Used during initial adaptivity.
Definition: Adaptivity.C:200
ConstElemRange * getActiveLocalElementRange()
Return pointers to range objects for various types of ranges (local nodes, boundary elems...
Definition: MooseMesh.C:737
std::shared_ptr< DisplacedProblem > _displaced_problem
Definition: Adaptivity.h:258
Real _stop_time
When adaptivity stops.
Definition: Adaptivity.h:280
Adaptivity(FEProblemBase &subproblem)
Definition: Adaptivity.C:30
std::string _marker_variable_name
Name of the marker variable if using the new adaptivity system.
Definition: Adaptivity.h:288
std::unique_ptr< MeshRefinement > _displaced_mesh_refinement
A mesh refinement object for displaced mesh.
Definition: Adaptivity.h:261
std::unique_ptr< ErrorEstimator > _error_estimator
Error estimator to be used by the apps.
Definition: Adaptivity.h:254
NonlinearSystemBase & getNonlinearSystemBase()
bool _initialized
on/off flag reporting if the adaptivity system has been initialized
Definition: Adaptivity.h:250
PerfID _uniform_refine_with_projection
Definition: Adaptivity.h:305
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:207
virtual ~Adaptivity()
Definition: Adaptivity.C:56
void updateErrorVectors()
Update the ErrorVectors that have been requested through calls to getErrorVector().
Definition: Adaptivity.C:288
void init(unsigned int steps, unsigned int initial_steps)
Initialize and turn on adaptivity for the simulation.
Definition: Adaptivity.C:59
void setTimeActive(Real start_time, Real stop_time)
Sets the time when the adaptivity is active.
Definition: Adaptivity.C:254
std::unique_ptr< ErrorVector > _error
Error vector for use with the error estimator.
Definition: Adaptivity.h:256
void setUseNewSystem()
Tells this object we&#39;re using the "new" adaptivity system.
Definition: Adaptivity.C:261
std::pair< typename M::iterator, bool > moose_try_emplace(M &m, const typename M::key_type &k, Args &&... args)
Function to mirror the behavior of the C++17 std::map::try_emplace() method (no hint).
Definition: Moose.h:75
PerfID _adapt_mesh_timer
Timers.
Definition: Adaptivity.h:303
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
std::string _initial_marker_variable_name
Name of the initial marker variable if using the new adaptivity system.
Definition: Adaptivity.h:291
static void uniformRefine(MooseMesh *mesh)
Performs uniform refinement of the passed Mesh object.
Definition: Adaptivity.C:206
MooseMesh & _mesh
Definition: Adaptivity.h:245
std::map< std::string, std::unique_ptr< ErrorVector > > _indicator_field_to_error_vector
Stores pointers to ErrorVectors associated with indicator field names.
Definition: Adaptivity.h:300
Real & _t
Time.
Definition: Adaptivity.h:272
virtual EquationSystems & es() override
FEProblemBase & _subproblem
Definition: Adaptivity.h:244
bool _print_mesh_changed
True if we want to print out info when mesh has changed.
Definition: Adaptivity.h:269
virtual DofMap & dofMap()
Gets writeable reference to the dof map.
Definition: SystemBase.C:932
std::unique_ptr< MeshRefinement > _mesh_refinement
A mesh refinement object to be used either with initial refinement or with Adaptivity.
Definition: Adaptivity.h:252
virtual std::shared_ptr< DisplacedProblem > getDisplacedProblem()
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2567
bool _mesh_refinement_on
on/off flag reporting if the adaptivity is being used
Definition: Adaptivity.h:248
An inteface for the _console for outputting to the Console object.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:74
virtual void meshChanged() override
Update data after a mesh change.
void setAdaptivityOn(bool state)
Allow adaptivity to be toggled programatically.
Definition: Adaptivity.C:244
NumericVector< Number > & solution() override
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
void printInfo(std::ostream &os=libMesh::out) const
Calls print_info() on the underlying Mesh.
Definition: MooseMesh.C:2588
unsigned int uniformRefineLevel() const
Returns the level of uniform refinement requested (zero if AMR is disabled).
Definition: MooseMesh.C:2361
void setErrorEstimator(const MooseEnum &error_estimator_name)
Set the error estimator.
Definition: Adaptivity.C:104
AuxiliarySystem & getAuxiliarySystem()
unsigned int _steps
steps of adaptivity to perform
Definition: Adaptivity.h:266
Interface for objects that needs transient capabilities.
void uniformRefineWithProjection()
Performs uniform refinement on the meshes in the current object.
Definition: Adaptivity.C:218
unsigned int _initial_steps
the number of adaptivity steps to do at the beginning of simulation
Definition: Adaptivity.h:264
bool _use_new_system
Whether or not to use the "new" adaptivity system.
Definition: Adaptivity.h:285
PerfID _update_error_vectors
Definition: Adaptivity.h:306
unsigned int _interval
intreval between adaptivity runs
Definition: Adaptivity.h:276
ErrorVector & getErrorVector(const std::string &indicator_field)
Get an ErrorVector that will be filled up with values corresponding to the indicator field name passe...
Definition: Adaptivity.C:279
virtual System & system() override
Get the reference to the libMesh system.
virtual MooseMesh & mesh() override
Real _start_time
When adaptivity start.
Definition: Adaptivity.h:278
void setErrorNorm(SystemNorm &sys_norm)
Set the error norm (FIXME: improve description)
Definition: Adaptivity.C:118
int & _step
Time Step.
Definition: Adaptivity.h:274
bool isAdaptivityDue()
Query if an adaptivity step should be performed at the current time / time step.
Definition: Adaptivity.C:309
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
void setMarkerVariableName(std::string marker_field)
Sets the name of the field variable to actually use to flag elements for refinement / coarsening...
Definition: Adaptivity.C:267
unsigned int _max_h_level
The maximum number of refinement levels.
Definition: Adaptivity.h:294
void setInitialMarkerVariableName(std::string marker_field)
Sets the name of the field variable to actually use to flag elements for initial refinement / coarsen...
Definition: Adaptivity.C:273