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