libMesh
Public Types | Public Member Functions | Public Attributes | Protected Member Functions | List of all members
libMesh::UniformRefinementEstimator Class Reference

This class implements a `‘brute force’' error estimator which integrates differences between the current solution and the solution on a uniformly refined (in h and/or p, for an arbitrary number of levels) grid. More...

#include <uniform_refinement_estimator.h>

Inheritance diagram for libMesh::UniformRefinementEstimator:
[legend]

Public Types

typedef std::map< std::pair< const System *, unsigned int >, ErrorVector * > ErrorMap
 When calculating many error vectors at once, we need a data structure to hold them all. More...
 

Public Member Functions

 UniformRefinementEstimator ()
 Constructor. More...
 
 UniformRefinementEstimator (const UniformRefinementEstimator &)=default
 Copy/move ctor, copy/move assignment operator, and destructor are all explicitly defaulted for this simple class. More...
 
 UniformRefinementEstimator (UniformRefinementEstimator &&)=default
 
UniformRefinementEstimatoroperator= (const UniformRefinementEstimator &)=default
 
UniformRefinementEstimatoroperator= (UniformRefinementEstimator &&)=default
 
virtual ~UniformRefinementEstimator ()=default
 
virtual void estimate_error (const System &system, ErrorVector &error_per_cell, const NumericVector< Number > *solution_vector=nullptr, bool estimate_parent_error=false) override
 This function does uniform refinements and a solve to get an improved solution on each cell, then estimates the error by integrating differences between the coarse and fine solutions. More...
 
virtual void estimate_errors (const EquationSystems &equation_systems, ErrorVector &error_per_cell, const std::map< const System *, SystemNorm > &error_norms, const std::map< const System *, const NumericVector< Number > * > *solution_vectors=nullptr, bool estimate_parent_error=false) override
 Currently this function ignores the error_norm member variable, and uses the function argument error_norms instead. More...
 
virtual void estimate_errors (const EquationSystems &equation_systems, ErrorMap &errors_per_cell, const std::map< const System *, const NumericVector< Number > * > *solution_vectors=nullptr, bool estimate_parent_error=false) override
 Currently this function ignores the component_scale member variable, because it calculates each error individually, unscaled. More...
 
virtual ErrorEstimatorType type () const override
 

Public Attributes

unsigned char number_h_refinements
 How many h refinements to perform to get the fine grid. More...
 
unsigned char number_p_refinements
 How many p refinements to perform to get the fine grid. More...
 
SystemNorm error_norm
 When estimating the error in a single system, the error_norm is used to control the scaling and norm choice for each variable. More...
 

Protected Member Functions

virtual void _estimate_error (const EquationSystems *equation_systems, const System *system, ErrorVector *error_per_cell, std::map< std::pair< const System *, unsigned int >, ErrorVector * > *errors_per_cell, const std::map< const System *, SystemNorm > *error_norms, const std::map< const System *, const NumericVector< Number > * > *solution_vectors=nullptr, bool estimate_parent_error=false)
 The code for estimate_error and both estimate_errors versions is very similar, so we use the same function for all three. More...
 
void reduce_error (std::vector< ErrorVectorReal > &error_per_cell, const Parallel::Communicator &comm) const
 This method takes the local error contributions in error_per_cell from each processor and combines them to get the global error vector. More...
 

Detailed Description

This class implements a `‘brute force’' error estimator which integrates differences between the current solution and the solution on a uniformly refined (in h and/or p, for an arbitrary number of levels) grid.

Author
Roy H. Stogner
Date
2006

Definition at line 45 of file uniform_refinement_estimator.h.

Member Typedef Documentation

◆ ErrorMap

typedef std::map<std::pair<const System *, unsigned int>, ErrorVector *> libMesh::ErrorEstimator::ErrorMap
inherited

When calculating many error vectors at once, we need a data structure to hold them all.

Definition at line 127 of file error_estimator.h.

Constructor & Destructor Documentation

◆ UniformRefinementEstimator() [1/3]

libMesh::UniformRefinementEstimator::UniformRefinementEstimator ( )

Constructor.

Sets the most common default parameter values.

Definition at line 53 of file uniform_refinement_estimator.C.

53  :
57 {
58  error_norm = H1;
59 }

References libMesh::ErrorEstimator::error_norm, and libMesh::H1.

◆ UniformRefinementEstimator() [2/3]

libMesh::UniformRefinementEstimator::UniformRefinementEstimator ( const UniformRefinementEstimator )
default

Copy/move ctor, copy/move assignment operator, and destructor are all explicitly defaulted for this simple class.

◆ UniformRefinementEstimator() [3/3]

libMesh::UniformRefinementEstimator::UniformRefinementEstimator ( UniformRefinementEstimator &&  )
default

◆ ~UniformRefinementEstimator()

virtual libMesh::UniformRefinementEstimator::~UniformRefinementEstimator ( )
virtualdefault

Member Function Documentation

◆ _estimate_error()

void libMesh::UniformRefinementEstimator::_estimate_error ( const EquationSystems equation_systems,
const System system,
ErrorVector error_per_cell,
std::map< std::pair< const System *, unsigned int >, ErrorVector * > *  errors_per_cell,
const std::map< const System *, SystemNorm > *  error_norms,
const std::map< const System *, const NumericVector< Number > * > *  solution_vectors = nullptr,
bool  estimate_parent_error = false 
)
protectedvirtual

The code for estimate_error and both estimate_errors versions is very similar, so we use the same function for all three.

Definition at line 117 of file uniform_refinement_estimator.C.

124 {
125  // Get a vector of the Systems we're going to work on,
126  // and set up a error_norms map if necessary
127  std::vector<System *> system_list;
128  auto error_norms = libmesh_make_unique<std::map<const System *, SystemNorm>>();
129 
130  if (_es)
131  {
132  libmesh_assert(!_system);
133  libmesh_assert(_es->n_systems());
134  _system = &(_es->get_system(0));
135  libmesh_assert_equal_to (&(_system->get_equation_systems()), _es);
136 
137  libmesh_assert(_es->n_systems());
138  for (auto i : IntRange<unsigned int>(0, _es->n_systems()))
139  // We have to break the rules here, because we can't refine a const System
140  system_list.push_back(const_cast<System *>(&(_es->get_system(i))));
141 
142  // If we're computing one vector, we need to know how to scale
143  // each variable's contributions to it.
144  if (_error_norms)
145  {
146  libmesh_assert(!errors_per_cell);
147  }
148  else
149  // If we're computing many vectors, we just need to know which
150  // variables to skip
151  {
152  libmesh_assert (errors_per_cell);
153 
154  _error_norms = error_norms.get();
155 
156  for (auto i : IntRange<unsigned int>(0, _es->n_systems()))
157  {
158  const System & sys = _es->get_system(i);
159  unsigned int n_vars = sys.n_vars();
160 
161  std::vector<Real> weights(n_vars, 0.0);
162  for (unsigned int v = 0; v != n_vars; ++v)
163  {
164  if (errors_per_cell->find(std::make_pair(&sys, v)) ==
165  errors_per_cell->end())
166  continue;
167 
168  weights[v] = 1.0;
169  }
170  (*error_norms)[&sys] =
171  SystemNorm(std::vector<FEMNormType>(n_vars, error_norm.type(0)),
172  weights);
173  }
174  }
175  }
176  else
177  {
178  libmesh_assert(_system);
179  // We have to break the rules here, because we can't refine a const System
180  system_list.push_back(const_cast<System *>(_system));
181 
182  libmesh_assert(!_error_norms);
183  (*error_norms)[_system] = error_norm;
184  _error_norms = error_norms.get();
185  }
186 
187  // An EquationSystems reference will be convenient.
188  // We have to break the rules here, because we can't refine a const System
189  EquationSystems & es =
190  const_cast<EquationSystems &>(_system->get_equation_systems());
191 
192  // The current mesh
193  MeshBase & mesh = es.get_mesh();
194 
195  // The dimensionality of the mesh
196  const unsigned int dim = mesh.mesh_dimension();
197 
198  // Resize the error_per_cell vectors to be
199  // the number of elements, initialize them to 0.
200  if (error_per_cell)
201  {
202  error_per_cell->clear();
203  error_per_cell->resize (mesh.max_elem_id(), 0.);
204  }
205  else
206  {
207  libmesh_assert(errors_per_cell);
208  for (const auto & pr : *errors_per_cell)
209  {
210  ErrorVector * e = pr.second;
211  e->clear();
212  e->resize(mesh.max_elem_id(), 0.);
213  }
214  }
215 
216  // We'll want to back up all coarse grid vectors
217  std::vector<std::map<std::string, std::unique_ptr<NumericVector<Number>>>> coarse_vectors(system_list.size());
218  std::vector<std::unique_ptr<NumericVector<Number>>> coarse_solutions(system_list.size());
219  std::vector<std::unique_ptr<NumericVector<Number>>> coarse_local_solutions(system_list.size());
220  // And make copies of projected solutions
221  std::vector<std::unique_ptr<NumericVector<Number>>> projected_solutions(system_list.size());
222 
223  // And we'll need to temporarily change solution projection settings
224  std::vector<bool> old_projection_settings(system_list.size());
225 
226  // And it'll be best to avoid any repartitioning
227  std::unique_ptr<Partitioner> old_partitioner(mesh.partitioner().release());
228 
229  // And we can't allow any renumbering
230  const bool old_renumbering_setting = mesh.allow_renumbering();
231  mesh.allow_renumbering(false);
232 
233  for (auto i : index_range(system_list))
234  {
235  System & system = *system_list[i];
236 
237  // Check for valid error_norms
238  libmesh_assert (_error_norms->find(&system) !=
239  _error_norms->end());
240 
241  // Back up the solution vector
242  coarse_solutions[i] = system.solution->clone();
243  coarse_local_solutions[i] = system.current_local_solution->clone();
244 
245  // Back up all other coarse grid vectors
246  for (System::vectors_iterator vec = system.vectors_begin(); vec !=
247  system.vectors_end(); ++vec)
248  {
249  // The (string) name of this vector
250  const std::string & var_name = vec->first;
251 
252  coarse_vectors[i][var_name] = vec->second->clone();
253  }
254 
255  // Use a non-standard solution vector if necessary
256  if (solution_vectors &&
257  solution_vectors->find(&system) != solution_vectors->end() &&
258  solution_vectors->find(&system)->second &&
259  solution_vectors->find(&system)->second != system.solution.get())
260  {
261  NumericVector<Number> * newsol =
262  const_cast<NumericVector<Number> *>
263  (solution_vectors->find(&system)->second);
264  newsol->swap(*system.solution);
265  system.update();
266  }
267 
268  // Make sure the solution is projected when we refine the mesh
269  old_projection_settings[i] = system.project_solution_on_reinit();
270  system.project_solution_on_reinit() = true;
271  }
272 
273  // Find the number of coarse mesh elements, to make it possible
274  // to find correct coarse elem ids later
275  const dof_id_type max_coarse_elem_id = mesh.max_elem_id();
276 #ifndef NDEBUG
277  // n_coarse_elem is only used in an assertion later so
278  // avoid declaring it unless asserts are active.
279  const dof_id_type n_coarse_elem = mesh.n_elem();
280 #endif
281 
282  // Uniformly refine the mesh
283  MeshRefinement mesh_refinement(mesh);
284 
286 
287  // FIXME: this may break if there is more than one System
288  // on this mesh but estimate_error was still called instead of
289  // estimate_errors
290  for (unsigned int i = 0; i != number_h_refinements; ++i)
291  {
292  mesh_refinement.uniformly_refine(1);
293  es.reinit();
294  }
295 
296  for (unsigned int i = 0; i != number_p_refinements; ++i)
297  {
298  mesh_refinement.uniformly_p_refine(1);
299  es.reinit();
300  }
301 
302  for (auto i : index_range(system_list))
303  {
304  System & system = *system_list[i];
305 
306  // Copy the projected coarse grid solutions, which will be
307  // overwritten by solve()
308  projected_solutions[i] = NumericVector<Number>::build(system.comm());
309  projected_solutions[i]->init(system.solution->size(), true, SERIAL);
310  system.solution->localize(*projected_solutions[i],
311  system.get_dof_map().get_send_list());
312  }
313 
314  // Are we doing a forward or an adjoint solve?
315  bool solve_adjoint = false;
316  if (solution_vectors)
317  {
318  System * sys = system_list[0];
319  libmesh_assert (solution_vectors->find(sys) !=
320  solution_vectors->end());
321  const NumericVector<Number> * vec = solution_vectors->find(sys)->second;
322  for (auto j : IntRange<unsigned int>(0, sys->n_qois()))
323  {
324  std::ostringstream adjoint_name;
325  adjoint_name << "adjoint_solution" << j;
326 
327  if (vec == sys->request_vector(adjoint_name.str()))
328  {
329  solve_adjoint = true;
330  break;
331  }
332  }
333  }
334 
335  // Get the uniformly refined solution.
336 
337  if (_es)
338  {
339  // Even if we had a decent preconditioner, valid matrix etc. before
340  // refinement, we don't any more.
341  for (auto i : IntRange<unsigned int>(0, _es->n_systems()))
342  es.get_system(i).disable_cache();
343 
344  // No specified vectors == forward solve
345  if (!solution_vectors)
346  es.solve();
347  else
348  {
349  libmesh_assert_equal_to (solution_vectors->size(), es.n_systems());
350  libmesh_assert (solution_vectors->find(system_list[0]) !=
351  solution_vectors->end());
352  libmesh_assert(solve_adjoint ||
353  (solution_vectors->find(system_list[0])->second ==
354  system_list[0]->solution.get()) ||
355  !solution_vectors->find(system_list[0])->second);
356 
357 #ifdef DEBUG
358  for (const auto & sys : system_list)
359  {
360  libmesh_assert (solution_vectors->find(sys) !=
361  solution_vectors->end());
362  const NumericVector<Number> * vec = solution_vectors->find(sys)->second;
363  if (solve_adjoint)
364  {
365  bool found_vec = false;
366  for (auto j : IntRange<unsigned int>(0, sys->n_qois()))
367  {
368  std::ostringstream adjoint_name;
369  adjoint_name << "adjoint_solution" << j;
370 
371  if (vec == sys->request_vector(adjoint_name.str()))
372  {
373  found_vec = true;
374  break;
375  }
376  }
377  libmesh_assert(found_vec);
378  }
379  else
380  libmesh_assert(vec == sys->solution.get() || !vec);
381  }
382 #endif
383 
384  if (solve_adjoint)
385  {
386  std::vector<unsigned int> adjs(system_list.size(),
388  // Set up proper initial guesses
389  for (auto i : index_range(system_list))
390  {
391  System * sys = system_list[i];
392  libmesh_assert (solution_vectors->find(sys) !=
393  solution_vectors->end());
394  const NumericVector<Number> * vec = solution_vectors->find(sys)->second;
395  for (auto j : IntRange<unsigned int>(0, sys->n_qois()))
396  {
397  std::ostringstream adjoint_name;
398  adjoint_name << "adjoint_solution" << j;
399 
400  if (vec == sys->request_vector(adjoint_name.str()))
401  {
402  adjs[i] = j;
403  break;
404  }
405  }
406  libmesh_assert_not_equal_to (adjs[i], libMesh::invalid_uint);
407  sys->get_adjoint_solution(adjs[i]) = *sys->solution;
408  }
409 
410  es.adjoint_solve();
411 
412  // Put the adjoint_solution into solution for
413  // comparisons
414  for (auto i : index_range(system_list))
415  {
416  system_list[i]->get_adjoint_solution(adjs[i]).swap(*system_list[i]->solution);
417  system_list[i]->update();
418  }
419  }
420  else
421  es.solve();
422  }
423  }
424  else
425  {
426  System * sys = system_list[0];
427 
428  // Even if we had a decent preconditioner, valid matrix etc. before
429  // refinement, we don't any more.
430  sys->disable_cache();
431 
432  // No specified vectors == forward solve
433  if (!solution_vectors)
434  sys->solve();
435  else
436  {
437  libmesh_assert (solution_vectors->find(sys) !=
438  solution_vectors->end());
439 
440  const NumericVector<Number> * vec = solution_vectors->find(sys)->second;
441 
442  libmesh_assert(solve_adjoint ||
443  (solution_vectors->find(sys)->second ==
444  sys->solution.get()) ||
445  !solution_vectors->find(sys)->second);
446 
447  if (solve_adjoint)
448  {
449  unsigned int adj = libMesh::invalid_uint;
450  for (unsigned int j=0, n_qois = sys->n_qois();
451  j != n_qois; ++j)
452  {
453  std::ostringstream adjoint_name;
454  adjoint_name << "adjoint_solution" << j;
455 
456  if (vec == sys->request_vector(adjoint_name.str()))
457  {
458  adj = j;
459  break;
460  }
461  }
462  libmesh_assert_not_equal_to (adj, libMesh::invalid_uint);
463 
464  // Set up proper initial guess
465  sys->get_adjoint_solution(adj) = *sys->solution;
466  sys->adjoint_solve();
467  // Put the adjoint_solution into solution for
468  // comparisons
469  sys->get_adjoint_solution(adj).swap(*sys->solution);
470  sys->update();
471  }
472  else
473  sys->solve();
474  }
475  }
476 
477  // Get the error in the uniformly refined solution(s).
478  for (auto sysnum : index_range(system_list))
479  {
480  System & system = *system_list[sysnum];
481 
482  unsigned int n_vars = system.n_vars();
483 
484  DofMap & dof_map = system.get_dof_map();
485 
486  const SystemNorm & system_i_norm =
487  _error_norms->find(&system)->second;
488 
489  NumericVector<Number> * projected_solution = projected_solutions[sysnum].get();
490 
491  // Loop over all the variables in the system
492  for (unsigned int var=0; var<n_vars; var++)
493  {
494  // Get the error vector to fill for this system and variable
495  ErrorVector * err_vec = error_per_cell;
496  if (!err_vec)
497  {
498  libmesh_assert(errors_per_cell);
499  err_vec =
500  (*errors_per_cell)[std::make_pair(&system,var)];
501  }
502 
503  // The type of finite element to use for this variable
504  const FEType & fe_type = dof_map.variable_type (var);
505 
506  // Finite element object for each fine element
507  std::unique_ptr<FEBase> fe (FEBase::build (dim, fe_type));
508 
509  // Build and attach an appropriate quadrature rule
510  std::unique_ptr<QBase> qrule = fe_type.default_quadrature_rule(dim);
511  fe->attach_quadrature_rule (qrule.get());
512 
513  const std::vector<Real> & JxW = fe->get_JxW();
514  const std::vector<std::vector<Real>> & phi = fe->get_phi();
515  const std::vector<std::vector<RealGradient>> & dphi =
516  fe->get_dphi();
517 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
518  const std::vector<std::vector<RealTensor>> & d2phi =
519  fe->get_d2phi();
520 #endif
521 
522  // The global DOF indices for the fine element
523  std::vector<dof_id_type> dof_indices;
524 
525  // Iterate over all the active elements in the fine mesh
526  // that live on this processor.
527  for (const auto & elem : mesh.active_local_element_ptr_range())
528  {
529  // Find the element id for the corresponding coarse grid element
530  const Elem * coarse = elem;
531  dof_id_type e_id = coarse->id();
532  while (e_id >= max_coarse_elem_id)
533  {
534  libmesh_assert (coarse->parent());
535  coarse = coarse->parent();
536  e_id = coarse->id();
537  }
538 
539  Real L2normsq = 0., H1seminormsq = 0.;
540 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
541  Real H2seminormsq = 0.;
542 #endif
543 
544  // reinitialize the element-specific data
545  // for the current element
546  fe->reinit (elem);
547 
548  // Get the local to global degree of freedom maps
549  dof_map.dof_indices (elem, dof_indices, var);
550 
551  // The number of quadrature points
552  const unsigned int n_qp = qrule->n_points();
553 
554  // The number of shape functions
555  const unsigned int n_sf =
556  cast_int<unsigned int>(dof_indices.size());
557 
558  //
559  // Begin the loop over the Quadrature points.
560  //
561  for (unsigned int qp=0; qp<n_qp; qp++)
562  {
563  Number u_fine = 0., u_coarse = 0.;
564 
565  Gradient grad_u_fine, grad_u_coarse;
566 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
567  Tensor grad2_u_fine, grad2_u_coarse;
568 #endif
569 
570  // Compute solution values at the current
571  // quadrature point. This requires a sum
572  // over all the shape functions evaluated
573  // at the quadrature point.
574  for (unsigned int i=0; i<n_sf; i++)
575  {
576  u_fine += phi[i][qp]*system.current_solution (dof_indices[i]);
577  u_coarse += phi[i][qp]*(*projected_solution) (dof_indices[i]);
578  grad_u_fine += dphi[i][qp]*system.current_solution (dof_indices[i]);
579  grad_u_coarse += dphi[i][qp]*(*projected_solution) (dof_indices[i]);
580 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
581  grad2_u_fine += d2phi[i][qp]*system.current_solution (dof_indices[i]);
582  grad2_u_coarse += d2phi[i][qp]*(*projected_solution) (dof_indices[i]);
583 #endif
584  }
585 
586  // Compute the value of the error at this quadrature point
587  const Number val_error = u_fine - u_coarse;
588 
589  // Add the squares of the error to each contribution
590  if (system_i_norm.type(var) == L2 ||
591  system_i_norm.type(var) == H1 ||
592  system_i_norm.type(var) == H2)
593  {
594  L2normsq += JxW[qp] * system_i_norm.weight_sq(var) *
595  TensorTools::norm_sq(val_error);
596  libmesh_assert_greater_equal (L2normsq, 0.);
597  }
598 
599 
600  // Compute the value of the error in the gradient at this
601  // quadrature point
602  if (system_i_norm.type(var) == H1 ||
603  system_i_norm.type(var) == H2 ||
604  system_i_norm.type(var) == H1_SEMINORM)
605  {
606  Gradient grad_error = grad_u_fine - grad_u_coarse;
607 
608  H1seminormsq += JxW[qp] * system_i_norm.weight_sq(var) *
609  grad_error.norm_sq();
610  libmesh_assert_greater_equal (H1seminormsq, 0.);
611  }
612 
613  // Compute the value of the error in the hessian at this
614  // quadrature point
615  if (system_i_norm.type(var) == H2 ||
616  system_i_norm.type(var) == H2_SEMINORM)
617  {
618 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
619  Tensor grad2_error = grad2_u_fine - grad2_u_coarse;
620 
621  H2seminormsq += JxW[qp] * system_i_norm.weight_sq(var) *
622  grad2_error.norm_sq();
623  libmesh_assert_greater_equal (H2seminormsq, 0.);
624 #else
625  libmesh_error_msg
626  ("libMesh was not configured with --enable-second");
627 #endif
628  }
629  } // end qp loop
630 
631  if (system_i_norm.type(var) == L2 ||
632  system_i_norm.type(var) == H1 ||
633  system_i_norm.type(var) == H2)
634  (*err_vec)[e_id] +=
635  static_cast<ErrorVectorReal>(L2normsq);
636  if (system_i_norm.type(var) == H1 ||
637  system_i_norm.type(var) == H2 ||
638  system_i_norm.type(var) == H1_SEMINORM)
639  (*err_vec)[e_id] +=
640  static_cast<ErrorVectorReal>(H1seminormsq);
641 
642 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
643  if (system_i_norm.type(var) == H2 ||
644  system_i_norm.type(var) == H2_SEMINORM)
645  (*err_vec)[e_id] +=
646  static_cast<ErrorVectorReal>(H2seminormsq);
647 #endif
648  } // End loop over active local elements
649  } // End loop over variables
650 
651  // Don't bother projecting the solution; we'll restore from backup
652  // after coarsening
653  system.project_solution_on_reinit() = false;
654  }
655 
656 
657  // Uniformly coarsen the mesh, without projecting the solution
659 
660  for (unsigned int i = 0; i != number_h_refinements; ++i)
661  {
662  mesh_refinement.uniformly_coarsen(1);
663  // FIXME - should the reinits here be necessary? - RHS
664  es.reinit();
665  }
666 
667  for (unsigned int i = 0; i != number_p_refinements; ++i)
668  {
669  mesh_refinement.uniformly_p_coarsen(1);
670  es.reinit();
671  }
672 
673  // We should be back where we started
674  libmesh_assert_equal_to (n_coarse_elem, mesh.n_elem());
675 
676  // Each processor has now computed the error contributions
677  // for its local elements. We need to sum the vector
678  // and then take the square-root of each component. Note
679  // that we only need to sum if we are running on multiple
680  // processors, and we only need to take the square-root
681  // if the value is nonzero. There will in general be many
682  // zeros for the inactive elements.
683 
684  if (error_per_cell)
685  {
686  // First sum the vector of estimated error values
687  this->reduce_error(*error_per_cell, es.comm());
688 
689  // Compute the square-root of each component.
690  LOG_SCOPE("std::sqrt()", "UniformRefinementEstimator");
691  for (auto & val : *error_per_cell)
692  if (val != 0.)
693  val = std::sqrt(val);
694  }
695  else
696  {
697  for (const auto & pr : *errors_per_cell)
698  {
699  ErrorVector & e = *(pr.second);
700  // First sum the vector of estimated error values
701  this->reduce_error(e, es.comm());
702 
703  // Compute the square-root of each component.
704  LOG_SCOPE("std::sqrt()", "UniformRefinementEstimator");
705  for (auto & val : e)
706  if (val != 0.)
707  val = std::sqrt(val);
708  }
709  }
710 
711  // Restore old solutions and clean up the heap
712  for (auto i : index_range(system_list))
713  {
714  System & system = *system_list[i];
715 
716  system.project_solution_on_reinit() = old_projection_settings[i];
717 
718  // Restore the coarse solution vectors and delete their copies
719  *system.solution = *coarse_solutions[i];
720  *system.current_local_solution = *coarse_local_solutions[i];
721 
722  for (System::vectors_iterator vec = system.vectors_begin(); vec !=
723  system.vectors_end(); ++vec)
724  {
725  // The (string) name of this vector
726  const std::string & var_name = vec->first;
727 
728  system.get_vector(var_name) = *coarse_vectors[i][var_name];
729 
730  coarse_vectors[i][var_name]->clear();
731  }
732  }
733 
734  // Restore old partitioner and renumbering settings
735  mesh.partitioner().reset(old_partitioner.release());
736  mesh.allow_renumbering(old_renumbering_setting);
737 }

References libMesh::EquationSystems::adjoint_solve(), libMesh::System::adjoint_solve(), libMesh::FEGenericBase< OutputType >::build(), libMesh::NumericVector< T >::build(), libMesh::NumericVector< T >::clear(), libMesh::ParallelObject::comm(), libMesh::System::current_local_solution, libMesh::System::current_solution(), libMesh::FEType::default_quadrature_rule(), dim, libMesh::System::disable_cache(), libMesh::DofMap::dof_indices(), libMesh::ErrorEstimator::error_norm, libMesh::NumericVector< T >::get(), libMesh::System::get_adjoint_solution(), libMesh::System::get_dof_map(), libMesh::System::get_equation_systems(), libMesh::EquationSystems::get_mesh(), libMesh::DofMap::get_send_list(), libMesh::EquationSystems::get_system(), libMesh::System::get_vector(), libMesh::H1, libMesh::H1_SEMINORM, libMesh::H2, libMesh::H2_SEMINORM, libMesh::DofObject::id(), libMesh::index_range(), libMesh::invalid_uint, libMesh::L2, libMesh::libmesh_assert(), mesh, libMesh::System::n_qois(), libMesh::EquationSystems::n_systems(), n_vars, libMesh::System::n_vars(), libMesh::TensorTools::norm_sq(), libMesh::TypeVector< T >::norm_sq(), libMesh::TypeTensor< T >::norm_sq(), number_h_refinements, number_p_refinements, libMesh::Elem::parent(), libMesh::System::project_solution_on_reinit(), libMesh::Real, libMesh::ErrorEstimator::reduce_error(), libMesh::EquationSystems::reinit(), libMesh::System::request_vector(), libMesh::SERIAL, libMesh::System::solution, libMesh::EquationSystems::solve(), libMesh::System::solve(), std::sqrt(), libMesh::NumericVector< T >::swap(), libMesh::SystemNorm::type(), libMesh::MeshRefinement::uniformly_coarsen(), libMesh::MeshRefinement::uniformly_p_coarsen(), libMesh::MeshRefinement::uniformly_p_refine(), libMesh::MeshRefinement::uniformly_refine(), libMesh::System::update(), libMesh::DofMap::variable_type(), libMesh::System::vectors_begin(), libMesh::System::vectors_end(), and libMesh::SystemNorm::weight_sq().

Referenced by estimate_error(), and estimate_errors().

◆ estimate_error()

void libMesh::UniformRefinementEstimator::estimate_error ( const System system,
ErrorVector error_per_cell,
const NumericVector< Number > *  solution_vector = nullptr,
bool  estimate_parent_error = false 
)
overridevirtual

This function does uniform refinements and a solve to get an improved solution on each cell, then estimates the error by integrating differences between the coarse and fine solutions.

system.solve() must be called, and so should have no side effects.

Only the provided system is solved on the refined mesh; for problems decoupled into multiple systems, use of estimate_errors() should be more reliable.

The estimated error is output in the vector error_per_cell

Implements libMesh::ErrorEstimator.

Definition at line 69 of file uniform_refinement_estimator.C.

73 {
74  LOG_SCOPE("estimate_error()", "UniformRefinementEstimator");
75  std::map<const System *, const NumericVector<Number> *> solution_vectors;
76  solution_vectors[&_system] = solution_vector;
77  this->_estimate_error (nullptr,
78  &_system,
79  &error_per_cell,
80  nullptr,
81  nullptr,
82  &solution_vectors,
83  estimate_parent_error);
84 }

References _estimate_error().

Referenced by main().

◆ estimate_errors() [1/2]

void libMesh::UniformRefinementEstimator::estimate_errors ( const EquationSystems equation_systems,
ErrorMap errors_per_cell,
const std::map< const System *, const NumericVector< Number > * > *  solution_vectors = nullptr,
bool  estimate_parent_error = false 
)
overridevirtual

Currently this function ignores the component_scale member variable, because it calculates each error individually, unscaled.

The user selects which errors get computed by filling a map with error vectors: If errors_per_cell[&system][v] exists, it will be filled with the error values in variable v of system

Reimplemented from libMesh::ErrorEstimator.

Definition at line 102 of file uniform_refinement_estimator.C.

106 {
107  LOG_SCOPE("estimate_errors()", "UniformRefinementEstimator");
108  this->_estimate_error (&_es,
109  nullptr,
110  nullptr,
111  &errors_per_cell,
112  nullptr,
113  solution_vectors,
114  estimate_parent_error);
115 }

References _estimate_error().

◆ estimate_errors() [2/2]

void libMesh::UniformRefinementEstimator::estimate_errors ( const EquationSystems equation_systems,
ErrorVector error_per_cell,
const std::map< const System *, SystemNorm > &  error_norms,
const std::map< const System *, const NumericVector< Number > * > *  solution_vectors = nullptr,
bool  estimate_parent_error = false 
)
overridevirtual

Currently this function ignores the error_norm member variable, and uses the function argument error_norms instead.

This function is named estimate_errors instead of estimate_error because otherwise C++ can get confused.

Reimplemented from libMesh::ErrorEstimator.

Definition at line 86 of file uniform_refinement_estimator.C.

91 {
92  LOG_SCOPE("estimate_errors()", "UniformRefinementEstimator");
93  this->_estimate_error (&_es,
94  nullptr,
95  &error_per_cell,
96  nullptr,
97  &error_norms,
98  solution_vectors,
99  estimate_parent_error);
100 }

References _estimate_error().

◆ operator=() [1/2]

UniformRefinementEstimator& libMesh::UniformRefinementEstimator::operator= ( const UniformRefinementEstimator )
default

◆ operator=() [2/2]

UniformRefinementEstimator& libMesh::UniformRefinementEstimator::operator= ( UniformRefinementEstimator &&  )
default

◆ reduce_error()

void libMesh::ErrorEstimator::reduce_error ( std::vector< ErrorVectorReal > &  error_per_cell,
const Parallel::Communicator &  comm 
) const
protectedinherited

This method takes the local error contributions in error_per_cell from each processor and combines them to get the global error vector.

Definition at line 32 of file error_estimator.C.

34 {
35  // This function must be run on all processors at once
36  // parallel_object_only();
37 
38  // Each processor has now computed the error contributions
39  // for its local elements. We may need to sum the vector to
40  // recover the error for each element.
41 
42  comm.sum(error_per_cell);
43 }

Referenced by _estimate_error(), libMesh::WeightedPatchRecoveryErrorEstimator::estimate_error(), libMesh::PatchRecoveryErrorEstimator::estimate_error(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::AdjointRefinementEstimator::estimate_error(), and libMesh::ExactErrorEstimator::estimate_error().

◆ type()

ErrorEstimatorType libMesh::UniformRefinementEstimator::type ( ) const
overridevirtual
Returns
The type for the ErrorEstimator subclass.

Implements libMesh::ErrorEstimator.

Definition at line 63 of file uniform_refinement_estimator.C.

64 {
65  return UNIFORM_REFINEMENT;
66 }

References libMesh::UNIFORM_REFINEMENT.

Member Data Documentation

◆ error_norm

SystemNorm libMesh::ErrorEstimator::error_norm
inherited

When estimating the error in a single system, the error_norm is used to control the scaling and norm choice for each variable.

Not all estimators will support all norm choices. The default scaling is for all variables to be weighted equally. The default norm choice depends on the error estimator.

Part of this functionality was supported via component_scale and sobolev_order in older libMesh versions, and a small part was supported via component_mask in even older versions. Hopefully the encapsulation here will allow us to avoid changing this API again.

Definition at line 164 of file error_estimator.h.

Referenced by _estimate_error(), libMesh::AdjointRefinementEstimator::AdjointRefinementEstimator(), libMesh::DiscontinuityMeasure::boundary_side_integration(), libMesh::KellyErrorEstimator::boundary_side_integration(), libMesh::DiscontinuityMeasure::DiscontinuityMeasure(), libMesh::JumpErrorEstimator::estimate_error(), libMesh::AdjointResidualErrorEstimator::estimate_error(), libMesh::ExactErrorEstimator::estimate_error(), libMesh::ErrorEstimator::estimate_errors(), libMesh::ExactErrorEstimator::ExactErrorEstimator(), libMesh::ExactErrorEstimator::find_squared_element_error(), libMesh::LaplacianErrorEstimator::init_context(), libMesh::DiscontinuityMeasure::init_context(), libMesh::KellyErrorEstimator::init_context(), libMesh::LaplacianErrorEstimator::internal_side_integration(), libMesh::DiscontinuityMeasure::internal_side_integration(), libMesh::KellyErrorEstimator::internal_side_integration(), libMesh::KellyErrorEstimator::KellyErrorEstimator(), libMesh::LaplacianErrorEstimator::LaplacianErrorEstimator(), main(), libMesh::WeightedPatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::PatchRecoveryErrorEstimator::EstimateError::operator()(), libMesh::PatchRecoveryErrorEstimator::PatchRecoveryErrorEstimator(), libMesh::JumpErrorEstimator::reinit_sides(), and UniformRefinementEstimator().

◆ number_h_refinements

unsigned char libMesh::UniformRefinementEstimator::number_h_refinements

How many h refinements to perform to get the fine grid.

Definition at line 116 of file uniform_refinement_estimator.h.

Referenced by _estimate_error().

◆ number_p_refinements

unsigned char libMesh::UniformRefinementEstimator::number_p_refinements

How many p refinements to perform to get the fine grid.

Definition at line 121 of file uniform_refinement_estimator.h.

Referenced by _estimate_error().


The documentation for this class was generated from the following files:
libMesh::Number
Real Number
Definition: libmesh_common.h:195
libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::invalid_uint
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value.
Definition: libmesh.h:249
libMesh::System::vectors_iterator
std::map< std::string, NumericVector< Number > * >::iterator vectors_iterator
Vector iterator typedefs.
Definition: system.h:756
libMesh::ErrorEstimator::error_norm
SystemNorm error_norm
When estimating the error in a single system, the error_norm is used to control the scaling and norm ...
Definition: error_estimator.h:164
n_vars
unsigned int n_vars
Definition: adaptivity_ex3.C:116
libMesh::UniformRefinementEstimator::number_p_refinements
unsigned char number_p_refinements
How many p refinements to perform to get the fine grid.
Definition: uniform_refinement_estimator.h:121
libMesh::SERIAL
Definition: enum_parallel_type.h:35
libMesh::index_range
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:106
libMesh::H1_SEMINORM
Definition: enum_norm_type.h:43
std::sqrt
MetaPhysicL::DualNumber< T, D > sqrt(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::UNIFORM_REFINEMENT
Definition: enum_error_estimator_type.h:43
libMesh::H2
Definition: enum_norm_type.h:38
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::NumericVector::build
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
Definition: numeric_vector.C:49
libMesh::SystemNorm::type
FEMNormType type(unsigned int var) const
Definition: system_norm.C:111
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::TypeVector::norm_sq
auto norm_sq() const -> decltype(std::norm(T()))
Definition: type_vector.h:986
libMesh::TypeTensor::norm_sq
auto norm_sq() const -> decltype(std::norm(T()))
Definition: type_tensor.h:1390
libMesh::UniformRefinementEstimator::number_h_refinements
unsigned char number_h_refinements
How many h refinements to perform to get the fine grid.
Definition: uniform_refinement_estimator.h:116
libMesh::FEGenericBase::build
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
libMesh::ErrorEstimator::ErrorEstimator
ErrorEstimator()=default
Constructor.
libMesh::H2_SEMINORM
Definition: enum_norm_type.h:44
libMesh::Gradient
NumberVectorValue Gradient
Definition: exact_solution.h:58
libMesh::TensorTools::norm_sq
T norm_sq(std::complex< T > a)
Definition: tensor_tools.h:85
libMesh::ErrorEstimator::reduce_error
void reduce_error(std::vector< ErrorVectorReal > &error_per_cell, const Parallel::Communicator &comm) const
This method takes the local error contributions in error_per_cell from each processor and combines th...
Definition: error_estimator.C:32
libMesh::UniformRefinementEstimator::_estimate_error
virtual void _estimate_error(const EquationSystems *equation_systems, const System *system, ErrorVector *error_per_cell, std::map< std::pair< const System *, unsigned int >, ErrorVector * > *errors_per_cell, const std::map< const System *, SystemNorm > *error_norms, const std::map< const System *, const NumericVector< Number > * > *solution_vectors=nullptr, bool estimate_parent_error=false)
The code for estimate_error and both estimate_errors versions is very similar, so we use the same fun...
Definition: uniform_refinement_estimator.C:117
libMesh::L2
Definition: enum_norm_type.h:36
libMesh::H1
Definition: enum_norm_type.h:37
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::Tensor
NumberTensorValue Tensor
Definition: exact_solution.h:56