error_estimator.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2022 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 #ifndef OOMPH_ERROR_ESTIMATOR_NAMESPACE_HEADER
27 #define OOMPH_ERROR_ESTIMATOR_NAMESPACE_HEADER
28 
29 #include "mesh.h"
30 #include "quadtree.h"
31 #include "nodes.h"
32 #include "algebraic_elements.h"
33 
34 namespace oomph
35 {
36  //========================================================================
38  //========================================================================
40  {
41  public:
44 
46  ErrorEstimator(const ErrorEstimator&) = delete;
47 
49  void operator=(const ErrorEstimator&) = delete;
50 
52  virtual ~ErrorEstimator() {}
53 
56  void get_element_errors(Mesh*& mesh_pt, Vector<double>& elemental_error)
57  {
58  // Create dummy doc info object and switch off output
59  DocInfo doc_info;
60  doc_info.disable_doc();
61  // Forward call to version with doc.
62  get_element_errors(mesh_pt, elemental_error, doc_info);
63  }
64 
65 
68  virtual void get_element_errors(Mesh*& mesh_pt,
69  Vector<double>& elemental_error,
70  DocInfo& doc_info) = 0;
71  };
72 
73 
74  //========================================================================
77  //========================================================================
79  {
80  public:
83 
86 
88  void operator=(const ElementWithZ2ErrorEstimator&) = delete;
89 
91  virtual unsigned num_Z2_flux_terms() = 0;
92 
100  virtual unsigned ncompound_fluxes()
101  {
102  return 1;
103  }
104 
106  virtual void get_Z2_flux(const Vector<double>& s, Vector<double>& flux) = 0;
107 
111  std::ostream& outfile,
113  double& error,
114  double& norm)
115  {
116  std::string error_message =
117  "compute_exact_Z2_error undefined for this element \n";
118  outfile << error_message;
119 
120  throw OomphLibError(
122  }
123 
127  virtual void get_Z2_compound_flux_indices(Vector<unsigned>& flux_index) {}
128 
130  virtual unsigned nvertex_node() const = 0;
131 
134  virtual Node* vertex_node_pt(const unsigned& j) const = 0;
135 
137  virtual unsigned nrecovery_order() = 0;
138 
142  virtual double geometric_jacobian(const Vector<double>& x)
143  {
144  return 1.0;
145  }
146  };
147 
148 
149  //========================================================================
264  //========================================================================
265  class Z2ErrorEstimator : public virtual ErrorEstimator
266  {
267  public:
270 
275  Reference_flux_norm(0.0),
277  {
278  }
279 
280 
285  : Recovery_order(0),
287  Reference_flux_norm(0.0),
289  {
290  }
291 
294 
296  void operator=(const Z2ErrorEstimator&) = delete;
297 
299  virtual ~Z2ErrorEstimator() {}
300 
303  void get_element_errors(Mesh*& mesh_pt, Vector<double>& elemental_error)
304  {
305  // Create dummy doc info object and switch off output
306  DocInfo doc_info;
307  doc_info.disable_doc();
308  // Forward call to version with doc.
309  get_element_errors(mesh_pt, elemental_error, doc_info);
310  }
311 
317  void get_element_errors(Mesh*& mesh_pt,
318  Vector<double>& elemental_error,
319  DocInfo& doc_info);
320 
322  unsigned& recovery_order()
323  {
324  return Recovery_order;
325  }
326 
328  unsigned recovery_order() const
329  {
330  return Recovery_order;
331  }
332 
335  {
336  return Combined_error_fct_pt;
337  }
338 
342  {
343  return Combined_error_fct_pt;
344  }
345 
349  void setup_patches(Mesh*& mesh_pt,
351  adjacent_elements_pt,
352  Vector<Node*>& vertex_node_pt);
353 
356  {
357  return Reference_flux_norm;
358  }
359 
361  double reference_flux_norm() const
362  {
363  return Reference_flux_norm;
364  }
365 
367  double get_combined_error_estimate(const Vector<double>& compound_error);
368 
369  private:
376  const Vector<ElementWithZ2ErrorEstimator*>& patch_el_pt,
377  const unsigned& num_recovery_terms,
378  const unsigned& num_flux_terms,
379  const unsigned& dim,
380  DenseMatrix<double>*& recovered_flux_coefficient_pt);
381 
382 
386  unsigned nrecovery_terms(const unsigned& dim);
387 
388 
393  void shape_rec(const Vector<double>& x,
394  const unsigned& dim,
395  Vector<double>& psi_r);
396 
400  Integral* integral_rec(const unsigned& dim, const bool& is_q_mesh);
401 
403  unsigned Recovery_order;
404 
408 
410  void doc_flux(Mesh* mesh_pt,
411  const unsigned& num_flux_terms,
413  const Vector<double>& elemental_error,
414  DocInfo& doc_info);
415 
418 
421  };
422 
423 
427 
428 
429  //========================================================================
433  //========================================================================
434  class DummyErrorEstimator : public virtual ErrorEstimator
435  {
436  public:
446  const Vector<unsigned>& elements_to_refine,
447  const unsigned& central_node_number,
448  const bool& use_lagrangian_coordinates = false)
449  : Use_lagrangian_coordinates(use_lagrangian_coordinates),
450  Central_node_number(central_node_number)
451  {
452 #ifdef PARANOID
453 #ifdef OOMPH_HAS_MPI
454  if (mesh_pt->is_mesh_distributed())
455  {
456  throw OomphLibError(
457  "Can't use this error estimator on distributed meshes!",
460  }
461 #endif
462 #endif
463 
464 #ifdef PARANOID
465  if (mesh_pt->nelement() == 0)
466  {
467  throw OomphLibError(
468  "Can't build error estimator if there are no elements in mesh\n",
471  }
472 #endif
473 
474  unsigned dim = mesh_pt->finite_element_pt(0)->node_pt(0)->ndim();
475  if (use_lagrangian_coordinates)
476  {
477  SolidNode* solid_nod_pt =
478  dynamic_cast<SolidNode*>(mesh_pt->finite_element_pt(0)->node_pt(0));
479  if (solid_nod_pt != 0)
480  {
481  dim = solid_nod_pt->nlagrangian();
482  }
483  }
484  unsigned nregion = elements_to_refine.size();
485  Region_low_bound.resize(nregion);
486  Region_upp_bound.resize(nregion);
487  for (unsigned e = 0; e < nregion; e++)
488  {
489  Region_low_bound[e].resize(dim, 1.0e20);
490  Region_upp_bound[e].resize(dim, -1.0e20);
491  FiniteElement* el_pt =
492  mesh_pt->finite_element_pt(elements_to_refine[e]);
493  unsigned nnod = el_pt->nnode();
494  for (unsigned j = 0; j < nnod; j++)
495  {
496  Node* nod_pt = el_pt->node_pt(j);
497  for (unsigned i = 0; i < dim; i++)
498  {
499  double x = nod_pt->x(i);
500  if (use_lagrangian_coordinates)
501  {
502  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(nod_pt);
503  if (solid_nod_pt != 0)
504  {
505  x = solid_nod_pt->xi(i);
506  }
507  }
508  if (x < Region_low_bound[e][i])
509  {
510  Region_low_bound[e][i] = x;
511  }
512  if (x > Region_upp_bound[e][i])
513  {
514  Region_upp_bound[e][i] = x;
515  }
516  }
517  }
518  }
519  }
520 
521 
531  const Vector<double>& lower_left,
532  const Vector<double>& upper_right,
533  const unsigned& central_node_number,
534  const bool& use_lagrangian_coordinates = false)
535  : Use_lagrangian_coordinates(use_lagrangian_coordinates),
536  Central_node_number(central_node_number)
537  {
538 #ifdef PARANOID
539  if (mesh_pt->nelement() == 0)
540  {
541  throw OomphLibError(
542  "Can't build error estimator if there are no elements in mesh\n",
545  }
546 #endif
547 
548  unsigned nregion = 1;
549  Region_low_bound.resize(nregion);
550  Region_upp_bound.resize(nregion);
551  Region_low_bound[0] = lower_left;
552  Region_upp_bound[0] = upper_right;
553  }
554 
557 
559  void operator=(const DummyErrorEstimator&) = delete;
560 
562  virtual ~DummyErrorEstimator() {}
563 
564 
567  virtual void get_element_errors(Mesh*& mesh_pt,
568  Vector<double>& elemental_error,
569  DocInfo& doc_info)
570  {
571 #ifdef PARANOID
572  if (doc_info.is_doc_enabled())
573  {
574  std::ostringstream warning_stream;
575  warning_stream
576  << "No output defined in DummyErrorEstimator::get_element_errors()\n"
577  << "Ignoring doc_info flag.\n";
578  OomphLibWarning(warning_stream.str(),
579  "DummyErrorEstimator::get_element_errors()",
581  }
582 #endif
583  unsigned nregion = Region_low_bound.size();
584  unsigned nelem = mesh_pt->nelement();
585  for (unsigned e = 0; e < nelem; e++)
586  {
587  elemental_error[e] = 0.0;
588 
589  // Check if element is in the regions to be refined
590  // (based on coords of its central node)
591  Node* nod_pt =
593  for (unsigned r = 0; r < nregion; r++)
594  {
595  bool is_inside = true;
596  unsigned dim = Region_low_bound[r].size();
597  for (unsigned i = 0; i < dim; i++)
598  {
599  double x = nod_pt->x(i);
601  {
602  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(nod_pt);
603  if (solid_nod_pt != 0)
604  {
605  x = solid_nod_pt->xi(i);
606  }
607  }
608  if (x < Region_low_bound[r][i])
609  {
610  is_inside = false;
611  break;
612  }
613  if (x > Region_upp_bound[r][i])
614  {
615  is_inside = false;
616  break;
617  }
618  }
619  if (is_inside)
620  {
621  elemental_error[e] = 1.0;
622  break;
623  }
624  }
625  }
626  }
627 
628  private:
632 
636 
639 
642  };
643 
644 
645 } // namespace oomph
646 
647 #endif
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Definition: oomph_utilities.h:499
bool is_doc_enabled() const
Are we documenting?
Definition: oomph_utilities.h:548
void disable_doc()
Disable documentation.
Definition: oomph_utilities.h:542
Definition: error_estimator.h:435
bool Use_lagrangian_coordinates
Definition: error_estimator.h:631
Vector< Vector< double > > Region_low_bound
Lower bounds for the coordinates of the refinement regions.
Definition: error_estimator.h:641
DummyErrorEstimator(Mesh *mesh_pt, const Vector< unsigned > &elements_to_refine, const unsigned &central_node_number, const bool &use_lagrangian_coordinates=false)
Definition: error_estimator.h:445
DummyErrorEstimator(const DummyErrorEstimator &)=delete
Broken copy constructor.
virtual void get_element_errors(Mesh *&mesh_pt, Vector< double > &elemental_error, DocInfo &doc_info)
Definition: error_estimator.h:567
Vector< Vector< double > > Region_upp_bound
Upper bounds for the coordinates of the refinement regions.
Definition: error_estimator.h:638
unsigned Central_node_number
Definition: error_estimator.h:635
DummyErrorEstimator(Mesh *mesh_pt, const Vector< double > &lower_left, const Vector< double > &upper_right, const unsigned &central_node_number, const bool &use_lagrangian_coordinates=false)
Definition: error_estimator.h:530
virtual ~DummyErrorEstimator()
Empty virtual destructor.
Definition: error_estimator.h:562
void operator=(const DummyErrorEstimator &)=delete
Broken assignment operator.
Definition: error_estimator.h:79
ElementWithZ2ErrorEstimator(const ElementWithZ2ErrorEstimator &)=delete
Broken copy constructor.
void operator=(const ElementWithZ2ErrorEstimator &)=delete
Broken assignment operator.
virtual Node * vertex_node_pt(const unsigned &j) const =0
virtual unsigned nvertex_node() const =0
Number of vertex nodes in the element.
virtual unsigned ncompound_fluxes()
Definition: error_estimator.h:100
virtual void get_Z2_compound_flux_indices(Vector< unsigned > &flux_index)
Definition: error_estimator.h:127
ElementWithZ2ErrorEstimator()
Default empty constructor.
Definition: error_estimator.h:82
virtual void get_Z2_flux(const Vector< double > &s, Vector< double > &flux)=0
Z2 'flux' terms for Z2 error estimation.
virtual void compute_exact_Z2_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_flux_pt, double &error, double &norm)
Definition: error_estimator.h:110
virtual double geometric_jacobian(const Vector< double > &x)
Definition: error_estimator.h:142
virtual unsigned num_Z2_flux_terms()=0
Number of 'flux' terms for Z2 error estimation.
virtual unsigned nrecovery_order()=0
Order of recovery shape functions.
Base class for spatial error estimators.
Definition: error_estimator.h:40
void get_element_errors(Mesh *&mesh_pt, Vector< double > &elemental_error)
Definition: error_estimator.h:56
ErrorEstimator()
Default empty constructor.
Definition: error_estimator.h:43
virtual ~ErrorEstimator()
Empty virtual destructor.
Definition: error_estimator.h:52
ErrorEstimator(const ErrorEstimator &)=delete
Broken copy constructor.
virtual void get_element_errors(Mesh *&mesh_pt, Vector< double > &elemental_error, DocInfo &doc_info)=0
void operator=(const ErrorEstimator &)=delete
Broken assignment operator.
Definition: elements.h:1313
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2210
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Definition: elements.h:1759
Definition: integral.h:49
Definition: map_matrix.h:109
Definition: mesh.h:67
bool is_mesh_distributed() const
Boolean to indicate if Mesh has been distributed.
Definition: mesh.h:1588
FiniteElement * finite_element_pt(const unsigned &e) const
Definition: mesh.h:473
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:590
Definition: nodes.h:906
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
Definition: oomph_definitions.h:222
Definition: oomph_definitions.h:267
Definition: nodes.h:1686
double & xi(const unsigned &i)
Reference to i-th Lagrangian position.
Definition: nodes.h:1883
unsigned nlagrangian() const
Return number of lagrangian coordinates.
Definition: nodes.h:1870
Definition: error_estimator.h:266
void get_recovered_flux_in_patch(const Vector< ElementWithZ2ErrorEstimator * > &patch_el_pt, const unsigned &num_recovery_terms, const unsigned &num_flux_terms, const unsigned &dim, DenseMatrix< double > *&recovered_flux_coefficient_pt)
Definition: error_estimator.cc:666
CombinedErrorEstimateFctPt & combined_error_fct_pt()
Access function: Pointer to combined error estimate function.
Definition: error_estimator.h:334
unsigned nrecovery_terms(const unsigned &dim)
Definition: error_estimator.cc:812
Z2ErrorEstimator(const unsigned &recovery_order)
Constructor: Set order of recovery shape functions.
Definition: error_estimator.h:272
CombinedErrorEstimateFctPt Combined_error_fct_pt
Function pointer to combined error estimator function.
Definition: error_estimator.h:420
Z2ErrorEstimator()
Definition: error_estimator.h:284
virtual ~Z2ErrorEstimator()
Empty virtual destructor.
Definition: error_estimator.h:299
double reference_flux_norm() const
Access function for prescribed reference flux norm (const. version)
Definition: error_estimator.h:361
double get_combined_error_estimate(const Vector< double > &compound_error)
Return a combined error estimate from all compound errors.
Definition: error_estimator.cc:460
void setup_patches(Mesh *&mesh_pt, std::map< Node *, Vector< ElementWithZ2ErrorEstimator * > * > &adjacent_elements_pt, Vector< Node * > &vertex_node_pt)
Definition: error_estimator.cc:505
void operator=(const Z2ErrorEstimator &)=delete
Broken assignment operator.
double(* CombinedErrorEstimateFctPt)(const Vector< double > &errors)
Function pointer to combined error estimator function.
Definition: error_estimator.h:269
double & reference_flux_norm()
Access function for prescribed reference flux norm.
Definition: error_estimator.h:355
unsigned Recovery_order
Order of recovery polynomials.
Definition: error_estimator.h:403
double Reference_flux_norm
Prescribed reference flux norm.
Definition: error_estimator.h:417
void get_element_errors(Mesh *&mesh_pt, Vector< double > &elemental_error)
Definition: error_estimator.h:303
CombinedErrorEstimateFctPt combined_error_fct_pt() const
Definition: error_estimator.h:341
Z2ErrorEstimator(const Z2ErrorEstimator &)=delete
Broken copy constructor.
void shape_rec(const Vector< double > &x, const unsigned &dim, Vector< double > &psi_r)
Definition: error_estimator.cc:44
Integral * integral_rec(const unsigned &dim, const bool &is_q_mesh)
Definition: error_estimator.cc:245
unsigned recovery_order() const
Access function for order of recovery polynomials (const version)
Definition: error_estimator.h:328
void doc_flux(Mesh *mesh_pt, const unsigned &num_flux_terms, MapMatrixMixed< Node *, int, double > &rec_flux_map, const Vector< double > &elemental_error, DocInfo &doc_info)
Doc flux and recovered flux.
Definition: error_estimator.cc:1802
unsigned & recovery_order()
Access function for order of recovery polynomials.
Definition: error_estimator.h:322
bool Recovery_order_from_first_element
Definition: error_estimator.h:407
RealScalar s
Definition: level1_cplx_impl.h:130
void flux(const double &time, const Vector< double > &x, double &flux)
Get flux applied along boundary x=0.
Definition: pretend_melt.cc:59
r
Definition: UniformPSDSelfTest.py:20
int error
Definition: calibrate.py:297
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2