Hermes2D  2.0
kelly_type_adapt.h
1 // This file is part of Hermes2D.
2 //
3 // Hermes2D is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
15 #ifndef KELLY_TYPE_ADAPT_H
16 #define KELLY_TYPE_ADAPT_H
17 
18 #include "adapt.h"
19 #include "../neighbor.h"
20 #include "../discrete_problem.h"
21 
22 namespace Hermes
23 {
24  namespace Hermes2D
25  {
28  {
29  private:
30  virtual double value(double e_diam, const std::string& e_marker) const = 0;
31  template<typename Scalar> friend class KellyTypeAdapt;
32  };
33 
36  {
37  private:
38  virtual double value(double e_diam, const std::string& e_marker) const {
39  return e_diam;
40  }
41  template<typename Scalar> friend class KellyTypeAdapt;
42  };
43 
64  template<typename Scalar>
65  class HERMES_API KellyTypeAdapt : public Adapt<Scalar>
66  {
67  public:
89  class HERMES_API ErrorEstimatorForm : public Form<Scalar>
90  {
91  public:
92  int i;
94  Hermes::vector<MeshFunction<Scalar>*> ext;
95 
96  void setAsInterface();
98  ErrorEstimatorForm(int i, std::string area = HERMES_ANY,
99  Hermes::vector<MeshFunction<Scalar>*> ext = Hermes::vector<MeshFunction<Scalar>*>())
100  : i(i), area(area), ext(ext) {}
101 
103  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[],
104  Func<Scalar> *u, Geom<double> *e,
105  Func<Scalar> **ext) const
106  {
107  throw Exceptions::MethodNotOverridenException("KellyTypeAdapt::ErrorEstimatorForm::value()");
108  return 0.0;
109  }
110 
112  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[],
114  Func<Ord> **ext) const
115  {
116  throw Exceptions::MethodNotOverridenException("KellyTypeAdapt::ErrorEstimatorForm::ord().");
117  return Hermes::Ord();
118  }
119 
122  };
123 
124  protected:
125  DiscreteProblem<Scalar> dp; // Only needed for gaining access to NeighborSearch methods.
126 
130  double eval_volumetric_estimator(typename KellyTypeAdapt::ErrorEstimatorForm* err_est_form,
131  RefMap* rm);
132  double eval_boundary_estimator(typename KellyTypeAdapt::ErrorEstimatorForm* err_est_form,
133  RefMap* rm,
134  SurfPos* surf_pos);
135  double eval_interface_estimator(typename KellyTypeAdapt::ErrorEstimatorForm* err_est_form,
136  RefMap *rm,
137  SurfPos* surf_pos,
138  LightArray<NeighborSearch<Scalar>*>& neighbor_searches,
139  int neighbor_index);
140  double eval_solution_norm(typename Adapt<Scalar>::MatrixFormVolError* form,
141  RefMap* rm,
142  MeshFunction<Scalar>* sln);
143 
147  Hermes::vector<typename KellyTypeAdapt::ErrorEstimatorForm *> error_estimators_vol;
148  Hermes::vector<typename KellyTypeAdapt::ErrorEstimatorForm *> error_estimators_surf;
149 
150  Mesh::ElementMarkersConversion element_markers_conversion;
151  Mesh::BoundaryMarkersConversion boundary_markers_conversion;
152 
155  Hermes::vector<const InterfaceEstimatorScalingFunction*> interface_scaling_fns;
156  bool use_aposteriori_interface_scaling;
157 
158 
159 
166 
171 
176  virtual double calc_err_internal(Hermes::vector<Solution<Scalar>*> slns,
177  Hermes::vector<double>* component_errors,
178  unsigned int error_flags);
179 
180  public:
181 
211  KellyTypeAdapt(Hermes::vector<Space<Scalar>*> spaces,
212  bool ignore_visited_segments = true,
213  Hermes::vector<const InterfaceEstimatorScalingFunction*>
214  interface_scaling_fns_ = Hermes::vector<const InterfaceEstimatorScalingFunction*>(),
215  Hermes::vector<ProjNormType> norms_ = Hermes::vector<ProjNormType>());
216 
218  bool ignore_visited_segments = true,
219  const InterfaceEstimatorScalingFunction* interface_scaling_fn_ = NULL,
220  ProjNormType norm_ = HERMES_UNSET_NORM);
221 
223  virtual ~KellyTypeAdapt()
224  {
225  for (unsigned int i = 0; i < error_estimators_surf.size(); i++)
226  delete error_estimators_surf[i];
227  error_estimators_surf.clear();
228 
229  for (unsigned int i = 0; i < error_estimators_vol.size(); i++)
230  delete error_estimators_vol[i];
231  error_estimators_vol.clear();
232 
233  for (unsigned int i = 0; i < interface_scaling_fns.size(); i++)
234  delete interface_scaling_fns[i];
235  interface_scaling_fns.clear();
236  }
237 
238  Mesh::ElementMarkersConversion* get_element_markers_conversion()
239  {
240  return &this->element_markers_conversion;
241  }
242  Mesh::BoundaryMarkersConversion* get_boundary_markers_conversion()
243  {
244  return &this->boundary_markers_conversion;
245  }
246 
254  void add_error_estimator_vol(ErrorEstimatorForm* form);
255 
262  void add_error_estimator_surf(ErrorEstimatorForm* form);
263 
267 
268  double calc_err_est(Solution<Scalar>*sln,
269  unsigned int error_flags = HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL)
270  {
271  if(this->num != 1)
272  throw Exceptions::Exception("Wrong number of solutions.");
273  Hermes::vector<Solution<Scalar>*> slns;
274  slns.push_back(sln);
275  return calc_err_est(slns, NULL, error_flags);
276  }
277 
278  double calc_err_est(Hermes::vector<Solution<Scalar>*> slns,
279  Hermes::vector<double>* component_errors = NULL,
280  unsigned int error_flags = HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL)
281  {
282  return calc_err_internal(slns, component_errors, error_flags);
283  }
284 
288  bool adapt(double thr, int strat = 0, int regularize = -1, double to_be_processed = 0.0);
289 
290  void disable_aposteriori_interface_scaling() { use_aposteriori_interface_scaling = false; }
291 
292  void set_volumetric_scaling_const(double C) { volumetric_scaling_const = C; }
293  void set_boundary_scaling_const(double C) { boundary_scaling_const = C; }
294  };
295 
310  template<typename Scalar>
311  class HERMES_API BasicKellyAdapt : public KellyTypeAdapt<Scalar>
312  {
313  public:
315  {
316  public:
318  ErrorEstimatorFormKelly(int i = 0, double const_by_laplacian = 1.0);
319 
320  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[],
321  Func<Scalar> *u, Geom<double> *e,
322  Func<Scalar> **ext) const
323  {
324  Scalar result = 0.;
325  for (int i = 0; i < n; i++)
326  result += wt[i] * Hermes::sqr( const_by_laplacian * ( e->nx[i] * (u->get_dx_central(i) - u->get_dx_neighbor(i)) +
327  e->ny[i] * (u->get_dy_central(i) - u->get_dy_neighbor(i)) ) );
328  return result;
329  }
330 
331  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[],
333  Func<Ord> **ext) const
334  {
335  return Hermes::sqr( (u->get_dx_central(0) - u->get_dx_neighbor(0)) +
336  (u->get_dy_central(0) - u->get_dy_neighbor(0)) );
337  }
338 
339  private:
340  double const_by_laplacian;
341  };
342 
347  BasicKellyAdapt(Hermes::vector<Space<Scalar>*> spaces_,
348  double const_by_laplacian = 1.0,
349  Hermes::vector<ProjNormType> norms_ = Hermes::vector<ProjNormType>())
350  : KellyTypeAdapt<Scalar>(spaces_, true, Hermes::vector<const InterfaceEstimatorScalingFunction*>(), norms_)
351  {
352  set_scaling_consts(const_by_laplacian);
353  for (int i = 0; i < this->num; i++)
354  this->error_estimators_surf.push_back(new ErrorEstimatorFormKelly(i, const_by_laplacian));
355  }
356 
357  BasicKellyAdapt(Space<Scalar>* space_, double const_by_laplacian = 1.0, ProjNormType norm_ = HERMES_UNSET_NORM)
358  : KellyTypeAdapt<Scalar>(space_, true, NULL, norm_)
359  {
360  set_scaling_consts(const_by_laplacian);
361  this->error_estimators_surf.push_back(new ErrorEstimatorFormKelly(0, const_by_laplacian));
362  }
363 
364  private:
365  void set_scaling_consts(double C)
366  {
367  this->interface_scaling_const = 1./(24.*C);
368  this->volumetric_scaling_const = this->interface_scaling_const;
369  this->boundary_scaling_const = this->interface_scaling_const;
370  }
371  };
372  }
373 }
374 #endif