www.mooseframework.org
Adaptivity.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* DO NOT MODIFY THIS HEADER */
3 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
4 /* */
5 /* (c) 2010 Battelle Energy Alliance, LLC */
6 /* ALL RIGHTS RESERVED */
7 /* */
8 /* Prepared by Battelle Energy Alliance, LLC */
9 /* Under Contract No. DE-AC07-05ID14517 */
10 /* With the U. S. Department of Energy */
11 /* */
12 /* See COPYRIGHT for full restrictions */
13 /****************************************************************/
14 
15 #include "Adaptivity.h"
16 
17 #include "AuxiliarySystem.h"
18 #include "DisplacedProblem.h"
19 #include "FEProblem.h"
20 #include "FlagElementsThread.h"
21 #include "MooseMesh.h"
22 #include "NonlinearSystemBase.h"
24 
25 // libMesh
26 #include "libmesh/equation_systems.h"
27 #include "libmesh/kelly_error_estimator.h"
28 #include "libmesh/patch_recovery_error_estimator.h"
29 #include "libmesh/fourth_error_estimators.h"
30 #include "libmesh/parallel.h"
31 #include "libmesh/error_vector.h"
32 
33 #ifdef LIBMESH_ENABLE_AMR
34 
36  : ConsoleStreamInterface(subproblem.getMooseApp()),
37  _subproblem(subproblem),
38  _mesh(_subproblem.mesh()),
39  _mesh_refinement_on(false),
40  _initialized(false),
41  _initial_steps(0),
42  _steps(0),
43  _print_mesh_changed(false),
44  _t(_subproblem.time()),
45  _step(_subproblem.timeStep()),
46  _interval(1),
47  _start_time(-std::numeric_limits<Real>::max()),
48  _stop_time(std::numeric_limits<Real>::max()),
49  _cycles_per_step(1),
50  _use_new_system(false),
51  _max_h_level(0),
52  _recompute_markers_during_cycles(false)
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  // If the marker name is supplied, use it. Otherwise, use the one in _marker_variable_name
128  if (marker_name.empty())
129  marker_name = _marker_variable_name;
130 
131  bool mesh_changed = false;
132 
133  if (_use_new_system)
134  {
135  if (!marker_name.empty()) // Only flag if a marker variable name has been set
136  {
137  _mesh_refinement->clean_refinement_flags();
138 
139  std::vector<Number> serialized_solution;
141  _subproblem.getAuxiliarySystem().solution().localize(serialized_solution);
142 
143  FlagElementsThread fet(_subproblem, serialized_solution, _max_h_level, marker_name);
144  ConstElemRange all_elems(_subproblem.mesh().getMesh().active_elements_begin(),
145  _subproblem.mesh().getMesh().active_elements_end(),
146  1);
147  Threads::parallel_reduce(all_elems, fet);
149  }
150  }
151  else
152  {
153  // Compute the error for each active element
155 
156  // Flag elements to be refined and coarsened
157  _mesh_refinement->flag_elements_by_error_fraction(*_error);
158 
159  if (_displaced_problem)
160  // Reuse the error vector and refine the displaced mesh
161  _displaced_mesh_refinement->flag_elements_by_error_fraction(*_error);
162  }
163 
164  // If the DisplacedProblem is active, undisplace the DisplacedMesh
165  // in preparation for refinement. We can't safely refine the
166  // DisplacedMesh directly, since the Hilbert keys computed on the
167  // inconsistenly-displaced Mesh are different on different
168  // processors, leading to inconsistent Hilbert keys. We must do
169  // this before the undisplaced Mesh is refined, so that the
170  // element and node numbering is still consistent.
171  if (_displaced_problem)
172  _displaced_problem->undisplaceMesh();
173 
174  // Perform refinement and coarsening
175  mesh_changed = _mesh_refinement->refine_and_coarsen_elements();
176 
177  if (_displaced_problem && mesh_changed)
178  {
179 // Now do refinement/coarsening
180 #ifndef NDEBUG
181  bool displaced_mesh_changed =
182 #endif
183  _displaced_mesh_refinement->refine_and_coarsen_elements();
184 
185  // Since the undisplaced mesh changed, the displaced mesh better have changed!
186  mooseAssert(displaced_mesh_changed, "Undisplaced mesh changed, but displaced mesh did not!");
187  }
188 
189  if (mesh_changed && _print_mesh_changed)
190  {
191  _console << "\nMesh Changed:\n";
192  _mesh.printInfo();
193  }
194 
195  return mesh_changed;
196 }
197 
198 bool
200 {
202 }
203 
204 void
206 {
207  mooseAssert(mesh, "Mesh pointer must not be NULL");
208 
209  // NOTE: we are using a separate object here, since adaptivity may not be on, but we need to be
210  // able to do refinements
211  MeshRefinement mesh_refinement(*mesh);
212  unsigned int level = mesh->uniformRefineLevel();
213  mesh_refinement.uniformly_refine(level);
214 }
215 
216 void
218 {
219  // NOTE: we are using a separate object here, since adaptivity may not be on, but we need to be
220  // able to do refinements
221  MeshRefinement mesh_refinement(_mesh);
222  unsigned int level = _mesh.uniformRefineLevel();
223  MeshRefinement displaced_mesh_refinement(_displaced_problem ? _displaced_problem->mesh() : _mesh);
224 
225  // we have to go step by step so EquationSystems::reinit() won't freak out
226  for (unsigned int i = 0; i < level; i++)
227  {
228  // See comment above about why refining the displaced mesh is potentially unsafe.
229  if (_displaced_problem)
230  _displaced_problem->undisplaceMesh();
231 
232  mesh_refinement.uniformly_refine(1);
233 
234  if (_displaced_problem)
235  displaced_mesh_refinement.uniformly_refine(1);
237  }
238 }
239 
240 void
242 {
243  // check if Adaptivity has been initialized before turning on
244  if (state == true && !_initialized)
245  mooseError("Mesh adaptivity system not available");
246 
247  _mesh_refinement_on = state;
248 }
249 
250 void
251 Adaptivity::setTimeActive(Real start_time, Real stop_time)
252 {
253  _start_time = start_time;
254  _stop_time = stop_time;
255 }
256 
257 void
259 {
260  _use_new_system = true;
261 }
262 
263 void
264 Adaptivity::setMarkerVariableName(std::string marker_field)
265 {
266  _marker_variable_name = marker_field;
267 }
268 
269 void
271 {
272  _initial_marker_variable_name = marker_field;
273 }
274 
275 ErrorVector &
276 Adaptivity::getErrorVector(const std::string & indicator_field)
277 {
278  // Insert or retrieve error vector
279  auto insert_pair = moose_try_emplace(
280  _indicator_field_to_error_vector, indicator_field, libmesh_make_unique<ErrorVector>());
281  return *insert_pair.first->second;
282 }
283 
284 void
286 {
287  // Resize all of the ErrorVectors in case the mesh has changed
288  for (const auto & it : _indicator_field_to_error_vector)
289  {
290  ErrorVector & vec = *(it.second);
291  vec.assign(_mesh.getMesh().max_elem_id(), 0);
292  }
293 
294  // Fill the vectors with the local contributions
295  UpdateErrorVectorsThread uevt(_subproblem, _indicator_field_to_error_vector);
296  Threads::parallel_reduce(*_mesh.getActiveLocalElementRange(), uevt);
297 
298  // Now sum across all processors
299  for (const auto & it : _indicator_field_to_error_vector)
300  _subproblem.comm().sum((std::vector<float> &)*(it.second));
301 }
302 
303 bool
305 {
306  return _mesh_refinement_on && (_start_time <= _t && _t < _stop_time) && _step % _interval == 0;
307 }
308 
309 #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:199
ConstElemRange * getActiveLocalElementRange()
Return pointers to range objects for various types of ranges (local nodes, boundary elems...
Definition: MooseMesh.C:724
std::shared_ptr< DisplacedProblem > _displaced_problem
Definition: Adaptivity.h:260
Real _stop_time
When adaptivity stops.
Definition: Adaptivity.h:282
Adaptivity(FEProblemBase &subproblem)
Definition: Adaptivity.C:35
std::string _marker_variable_name
Name of the marker variable if using the new adaptivity system.
Definition: Adaptivity.h:290
std::unique_ptr< MeshRefinement > _displaced_mesh_refinement
A mesh refinement object for displaced mesh.
Definition: Adaptivity.h:263
std::unique_ptr< ErrorEstimator > _error_estimator
Error estimator to be used by the apps.
Definition: Adaptivity.h:256
NonlinearSystemBase & getNonlinearSystemBase()
bool _initialized
on/off flag reporting if the adaptivity system has been initialized
Definition: Adaptivity.h:252
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:66
virtual ~Adaptivity()
Definition: Adaptivity.C:56
void updateErrorVectors()
Update the ErrorVectors that have been requested through calls to getErrorVector().
Definition: Adaptivity.C:285
void mooseError(Args &&...args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:182
void init(unsigned int steps, unsigned int initial_steps)
Initialize the initial adaptivity ;-)
Definition: Adaptivity.C:59
void setTimeActive(Real start_time, Real stop_time)
Sets the time when the adaptivity is active.
Definition: Adaptivity.C:251
void printInfo(std::ostream &os=libMesh::out) const
Calls print_info() on the underlying Mesh.
Definition: MooseMesh.C:2429
std::unique_ptr< ErrorVector > _error
Error vector for use with the error estimator.
Definition: Adaptivity.h:258
void setUseNewSystem()
Tells this object we&#39;re using the "new" adaptivity system.
Definition: Adaptivity.C:258
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:293
static void uniformRefine(MooseMesh *mesh)
Performs uniform refinement of the passed Mesh object.
Definition: Adaptivity.C:205
MooseMesh & _mesh
Definition: Adaptivity.h:247
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:302
Real & _t
Time.
Definition: Adaptivity.h:274
virtual EquationSystems & es() override
FEProblemBase & _subproblem
Definition: Adaptivity.h:246
bool _print_mesh_changed
True if we want to print out info when mesh has changed.
Definition: Adaptivity.h:271
virtual DofMap & dofMap()
Gets the dof map.
Definition: SystemBase.C:610
std::unique_ptr< MeshRefinement > _mesh_refinement
A mesh refinement object to be used either with initial refinement or with Adaptivity.
Definition: Adaptivity.h:254
virtual std::shared_ptr< DisplacedProblem > getDisplacedProblem()
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2408
bool _mesh_refinement_on
on/off flag reporting if the adaptivity is being used
Definition: Adaptivity.h:250
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
void setAdaptivityOn(bool state)
Allow adaptivity to be toggled programatically.
Definition: Adaptivity.C:241
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:37
unsigned int uniformRefineLevel() const
Returns the level of uniform refinement requested (zero if AMR is disabled).
Definition: MooseMesh.C:2202
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:268
void uniformRefineWithProjection()
Performs uniform refinement on the meshes in the current object.
Definition: Adaptivity.C:217
unsigned int _initial_steps
the number of adaptivity steps to do at the beginning of simulation
Definition: Adaptivity.h:266
virtual NumericVector< Number > & solution() override
bool _use_new_system
Whether or not to use the "new" adaptivity system.
Definition: Adaptivity.h:287
unsigned int _interval
intreval between adaptivity runs
Definition: Adaptivity.h:278
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:276
virtual System & system() override
Get the reference to the libMesh system.
virtual MooseMesh & mesh() override
Real _start_time
When adaptivity start.
Definition: Adaptivity.h:280
void setErrorNorm(SystemNorm &sys_norm)
Set the error norm (FIXME: improve description)
Definition: Adaptivity.C:118
int & _step
Time Step.
Definition: Adaptivity.h:276
bool isAdaptivityDue()
Query if an adaptivity step should be performed at the current time / time step.
Definition: Adaptivity.C:304
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:264
unsigned int _max_h_level
The maximum number of refinement levels.
Definition: Adaptivity.h:296
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:270