DUNE-ACFEM (unstable)

ellipticfemscheme.hh
1 #ifndef __ELLIPTIC_FEMSCHEME_HH__
2 #define __ELLIPTIC_FEMSCHEME_HH__
3 
4 // iostream includes
5 #include <iostream>
6 
7 // include grid part
8 #include <dune/fem/gridpart/adaptiveleafgridpart.hh>
9 
10 // include discrete function space
11 #include <dune/fem/space/lagrange.hh>
12 
13 // adaptation ...
14 #include <dune/fem/function/adaptivefunction.hh>
15 #include <dune/fem/space/common/adaptationmanager.hh>
16 
17 // include discrete function
18 #include <dune/fem/function/blockvectorfunction.hh>
19 
20 // Newton's iteration
21 #include <dune/fem/solver/newtoninverseoperator.hh>
22 
23 // lagrange interpolation
24 #include <dune/fem/space/common/interpolate.hh>
25 
26 // include norms
27 #include <dune/fem/misc/l2norm.hh>
28 #include <dune/fem/misc/h1norm.hh>
29 
30 // include parameter handling
31 #include <dune/fem/io/parameter.hh>
32 #include <dune/fem/solver/parameter.hh>
33 
34 // include output
35 #include <dune/fem/io/file/dataoutput.hh>
36 
37 // local includes
38 #include "../common/matrixhelper.hh"
39 #include "../algorithms/femschemeinterface.hh"
40 #include "../algorithms/operatorselector.hh"
41 #include "../models/modeltraits.hh"
42 #include "../operators/ellipticoperator.hh"
43 #include "../operators/functionals/functionals.hh"
44 #include "../operators/constraints/dirichletconstraints.hh"
45 #include "../functions/functions.hh"
46 
47 #include "../estimators/ellipticestimator.hh"
48 #include "../algorithms/marking.hh"
49 #include "../common/dataoutput.hh"
50 
51 // Select an appropriate solver, depending on ModelType and solver-family (ISTL, PESC ...)
52 #include "../common/solverselector.hh"
53 
54 namespace Dune {
55 
56  namespace ACFem {
57 
90  template<class DiscreteFunction, class Model, class InitialGuess, class RHSFunctional>
92  : public AdaptiveFemScheme
93  {
94  public:
96  typedef DiscreteFunction DiscreteFunctionType;
97 
98  typedef RHSFunctional RHSFunctionalType;
99 
101  typedef typename DiscreteFunctionType::GridType GridType;
102 
104  typedef typename DiscreteFunctionType::GridPartType GridPartType;
105 
107  typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
108 
110  using ModelType = Model;
111 
121  using DiscreteModelType = DiscreteModel<Model, DiscreteFunctionSpaceType>;
122 
124  using TraitsType = ModelTraits<DiscreteModelType>;
125 
129  typedef typename DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;
130 
133  typedef typename SolverSelectorType::LinearOperatorType LinearOperatorType;
134  typedef typename SolverSelectorType::LinearInverseOperatorType LinearInverseOperatorType;
135  typedef typename LinearInverseOperatorType::SolverParameterType LinearSolverParameterType;
136 
138  typedef
139  Fem::NewtonInverseOperator<LinearOperatorType, LinearInverseOperatorType>
141 
144  typedef Fem::RestrictProlongDefault<DiscreteFunctionType> RestrictionProlongationType;
145 
147  typedef Fem::AdaptationManager<GridType, RestrictionProlongationType> AdaptationManagerType;
148 
150  typedef DirichletConstraints<DiscreteFunctionSpaceType, DiscreteModelType> ConstraintsOperatorType;
151 
154  typedef DifferentiableEllipticOperator<LinearOperatorType, DiscreteModelType, const ConstraintsOperatorType&> OperatorType;
155 
157 
159  typedef MarkingStrategy<GridPartType> MarkingStrategyType;
160 
162  typedef InitialGuess InitialGuessType;
163 
165  typedef std::tuple<DiscreteFunctionType *, InitialGuessType *> IOTupleType;
166 
168  typedef DataOutput<GridType, IOTupleType> DataOutputType;
169 
170  public:
187  const ModelType& model,
188  const InitialGuessType& initialGuess,
189  const RHSFunctionalType& rhsFunctional,
190  const std::string& name)
191  : grid_(solution.space().gridPart().grid()),
192  model_(asExpression(discreteModel(model, solution.space()))),
193  name_(name),
194  gridPart_(solution.space().gridPart()),
195  discreteSpace_(solution.space()),
196  solution_(solution),
197  // estimator
198  estimator_(model_, discreteSpace_),
199  markingStrategy_(gridPart_, estimator_, name_ + ".adaptation"),
200  // restriction/prolongation operator
201  restrictProlong_(0),
202  // adaptation manager
203  adaptationManager_(0),
204  // create Dirichlet contraints
205  constraints_(discreteSpace_, model_),
206  // the elliptic operator (implicit)
207  operator_(model_, constraints_),
208  // create linear operator (domainSpace,rangeSpace)
209  linearOperator_("assembled elliptic operator", discreteSpace_, discreteSpace_),
210  solverParams_(TraitsType::isAffineLinear ? name_ + ".solver." : name_ + ".linear."),
211  sequence_(-1),
212  // initial guess or "exact" solution
213  initialGuess_(initialGuess),
214  // cast back to implementation
215  rhsFunctional_(rhsFunctional),
216  // io tuple
217  ioTuple_(&solution_, &initialGuess_),
218  // DataOutputType
219  dataOutput_(0)
220  {
221  chooseDefaultSolverMethod<SolverSelectorType>(solverParams_);
222  }
223 
230  : grid_(other.grid_),
231  model_(other.model_),
232  name_(other.name_),
233  gridPart_(other.gridPart_),
234  discreteSpace_(other.discreteSpace_),
235  solution_(other.solution_),
236  // estimator
237  estimator_(model_, discreteSpace_),
238  markingStrategy_(other.markingStrategy_),
239  // restriction/prolongation operator
240  restrictProlong_(0),
241  // adaptation manager
242  adaptationManager_(0),
243  // create Dirichlet contraints
244  constraints_(discreteSpace_, model_),
245  // the elliptic operator (implicit)
246  operator_(model_, constraints_),
247  // create linear operator (domainSpace,rangeSpace)
248  linearOperator_("assembled elliptic operator", discreteSpace_, discreteSpace_),
249  solverParams_(other.solverParams_),
250  sequence_(-1),
251  // initial guess or "exact" solution
252  initialGuess_(other.initialGuess_),
253  // optional additional rhs-functional
254  rhsFunctional_(other.rhsFunctional_),
255  // io tuple
256  ioTuple_(&solution_, &initialGuess_),
257  // DataOutputType
258  dataOutput_(0)
259  {
260  chooseDefaultSolverMethod<SolverSelectorType>(solverParams_);
261  }
262 
263  public:
264  virtual ~EllipticFemScheme() {
265  if (dataOutput_) {
266  delete dataOutput_;
267  }
268  if (adaptationManager_) {
269  delete adaptationManager_;
270  }
271  if (restrictProlong_) {
272  delete restrictProlong_;
273  }
274  }
275 
276  virtual std::string name () const
277  {
278  return name_;
279  }
280 
282  virtual void initialize()
283  {
285  solution_.clear();
286  } else {
287  // apply natural interpolation
288  interpolate(initialGuess_, solution_);
289  }
290  }
291 
292  virtual void assemble() {
293  operator_.jacobian(solution_, linearOperator_);
294  }
295 
297  virtual void solve(bool forceMatrixAssembling = true)
298  {
299  // set Dirichlet constraints in solution
300  constraints_.constrain(solution_);
301 
302  // right hand side, if present
303  DiscreteFunctionType rhs("rhs", discreteSpace_);
304 
305  //The Expression Template eliminate functional
306  // whose type evaluates to the ZeroFunctional
307  rhs.clear();
308  rhs += rhsFunctional_;
309  constraints_.zeroConstrain(rhs);
310 
311  if (TraitsType::isAffineLinear) {
312  linearSolve(rhs, forceMatrixAssembling);
313  } else {
314  nonLinearSolve(rhs);
315  }
316  }
317 
318  protected:
319 
322  {
323  assert(!TraitsType::isAffineLinear);
324 
325  Dune::Fem::NewtonParameter newtonParam(solverParams_, name_ + ".newton.");
326  NonLinearInverseOperatorType newton(newtonParam);
327  newton.bind(operator_);
328 
329  newton(rhs, solution_);
330 
331  converged_ = newton.converged();
332  assert(newton.converged());
333  }
334 
339  virtual void linearSolve(DiscreteFunctionType& rhs, bool forceMatrixAssembling)
340  {
341  assert(TraitsType::isAffineLinear);
342 
343  // if sequence number is outdated update linear operator
344  if (sequence_ != discreteSpace_.sequence() || forceMatrixAssembling) {
345  // assemble linear operator (i.e. setup matrix) The jacobian
346  // incorporates the constraints defined by the constraint class.
347  assemble();
348 
349  // update sequence number
350  sequence_ = discreteSpace_.sequence();
351  }
352 
353  // inverse operator using linear operator
354  LinearInverseOperatorType solver(solverParams_);
355  solver.bind(linearOperator_);
356 
357  // Apply the affine linear operator to the start value. This
358  // computes the initial residual. In the linear case, Lagrange space,
359  // Dirichlet data g, this computes
360  //
361  // update_ = A u - g
362  //
363  // where it is allowed that A is affine-linear, without having
364  // to apply a non-linear solver for this trivial non-linearity
365  DiscreteFunctionType update("update", discreteSpace_);
366  operator_(solution_, update);
367  rhs -= update; // rhs = rhs - A u ...
368 
369  // Zero initial values for the update_ vector are ok, because
370  // the information about the previous solution is already is
371  // contained in residual_.
372  update.clear();
373 
374  solver(rhs, update);
375  converged_ = (static_cast<int>(solver.iterations()) < solverParams_.maxIterations());
376  solution_ += update; // ... so u = u + invA(rhs - Au)
377  }
378 
379  public:
380 
382  virtual bool mark (const double tolerance)
383  {
384  return markingStrategy_.mark(tolerance);
385  }
386 
388  virtual double estimate()
389  {
390  return estimator_.estimate(solution_);
391  }
392 
394  virtual void adapt()
395  {
396  // there can only one adaptation manager per grid, and the
397  // RestrictionProlongationType which determines which
398  // functions are restricted/prolongated is built into the
399  // AdaptationManagerType. In order to allow for override by
400  // derived classes, allocation that adaptationManager_
401  // dynamically (and thus not at all, if ThisType::adapt() is
402  // never called.
403 
404  if (!adaptationManager_) {
405  // restriction/prolongation operator
406  restrictProlong_ = new RestrictionProlongationType(solution_);
407 
408  // adaptation manager
409  adaptationManager_ = new AdaptationManagerType(grid_, *restrictProlong_);
410  }
411 
412  // apply adaptation and load balancing
413  adaptationManager_->adapt();
414  if (adaptationManager_->loadBalance()) {
415  // TODO: re-initialize stuff as needed.
416  }
417  }
418 
420  virtual int output()
421  {
422  if (!dataOutput_) {
423  // NOTE: this should allocated dynamically, otherwise a
424  // derived class has problems to define completely different
425  // IO-schemes Also DataOutputType likes to already generate
426  // some files during construction, so make sure this never happens
427  dataOutput_ = new DataOutputType(grid_, ioTuple_, DataOutputParameters());
428  }
429 
430  if (!dataOutput_->willWrite()) {
431  return -1;
432  }
433 
434  // write data
435  dataOutput_->write();
436 
437  return dataOutput_->writeStep() - 1;
438  }
439 
441  virtual bool converged() const
442  {
443  return converged_;
444  }
445 
447  virtual double residual() const
448  {
449  // right hand side, if present
450  DiscreteFunctionType rhs("rhs", discreteSpace_);
451 
452  rhs.clear();
453  rhs += rhsFunctional_;
454  constraints_.zeroConstrain(rhs);
455 
456  DiscreteFunctionType update("update", discreteSpace_);
457  operator_(solution_, update);
458  rhs -= update; // rhs = rhs - A u ...
459  return std::sqrt(rhs.scalarProductDofs(rhs));
460  }
461 
463  virtual double error() const
464  {
465  // can also use L2-norm
466  typedef Fem::H1Norm< GridPartType > NormType;
467 
468  // the DiscreteFunctionSpaceAdapter sets the order per default
469  // to 111 == \infty. We set therefore the order just high
470  // enough that we see the asymptotic error. If the polynomial
471  // order it D, then the error should decay with (h^D). In
472  // principle it should thus suffice to use a quadrature of
473  // degree D.
474  NormType norm(gridPart_, 2*discreteSpace_.order());
475  return norm.distance(initialGuess_, solution_);
476  }
477 
478  virtual size_t size() const
479  {
480  // NOTE: slaveDofs.size() is always one TOO LARGE.
481  size_t numberOfDofs = discreteSpace_.size() - discreteSpace_.slaveDofs().size() + 1;
482 
483  numberOfDofs = grid_.comm().sum(numberOfDofs);
484 
485  return numberOfDofs;
486  }
487 
488  // TODO: make this const, and assemble somewhere else
489  virtual void printSystemMatrix(bool sparse = false, std::ostream& out = std::clog) {
490  assemble();
491  MatrixHelper<LinearOperatorType> mh(linearOperator_);
492  if (sparse) {
493  mh.printSparse(out);
494  } else {
495  mh.printPretty(out);
496  }
497  }
498 
499  protected:
500  GridType& grid_; // hierarchical grid
501  DiscreteModelType model_; // always a copy
502 
503  const std::string name_;
504 
505  GridPartType& gridPart_; // grid part(view), here the leaf grid the discrete space is build with
506 
507  const DiscreteFunctionSpaceType& discreteSpace_; // discrete function space
508  DiscreteFunctionType& solution_; // the unknown
509 
510  EstimatorType estimator_; // residual error estimator
511  MarkingStrategyType markingStrategy_;
512 
513  RestrictionProlongationType *restrictProlong_ ; // local restriction/prolongation object
514  AdaptationManagerType *adaptationManager_ ; // adaptation manager handling adaptation
515 
516  ConstraintsOperatorType constraints_; // dirichlet boundary constraints
517 
518  OperatorType operator_; // the (potentially non-linear) operator
519 
520  LinearOperatorType linearOperator_; // the linear operator (i.e. jacobian of the operator)
521 
522  LinearSolverParameterType solverParams_; // the solver Parameters of Dune::Fem
523  bool converged_ = false; // check whether solver has converged
524  mutable int sequence_; // sequence number
525 
526  InitialGuessType initialGuess_;
527  RHSFunctionalType rhsFunctional_;
528  IOTupleType ioTuple_; // tuple with pointers
529  DataOutputType *dataOutput_; // data output class
530  };
531 
537  template<
538  class DiscreteFunction, class Model, class InitialGuess, class RHSFunctional,
539  std::enable_if_t<(IsWrappableByConstLocalFunction<InitialGuess>::value
540  && IsLinearFunctional<RHSFunctional>::value
541  ), int> = 0>
542  auto ellipticFemScheme(DiscreteFunction& solution,
543  const Model&model,
544  const InitialGuess& initialGuess,
545  const RHSFunctional& rhsFunctional,
546  const std::string name = "acfem.schemes.elliptic")
547  {
549 
550  return ReturnType(solution, model, initialGuess, rhsFunctional, name);
551  }
552 
554  template<class DiscreteFunction, class Model, class InitialGuess,
555  std::enable_if_t<IsWrappableByConstLocalFunction<InitialGuess>::value, int> = 0>
556  auto
557  ellipticFemScheme(DiscreteFunction& solution,
558  const Model& model,
559  const InitialGuess& initialGuess,
560  const std::string name = "acfem.schemes.elliptic")
561  {
562  typedef
563  EllipticFemScheme<DiscreteFunction,
564  Model,
565  InitialGuess,
567  ReturnType;
568 
569  return ReturnType(solution,
570  model,
571  initialGuess,
572  zeroFunctional(solution.space()),
573  name);
574  }
575 
577  template<class DiscreteFunction, class Model, class RHSFunctional,
578  std::enable_if_t<IsLinearFunctional<RHSFunctional>::value, int> = 0>
579  auto ellipticFemScheme(DiscreteFunction& solution,
580  const Model& model,
581  const RHSFunctional& rhsFunctional,
582  const std::string name = "acfem.schemes.elliptic")
583  {
584  typedef
585  EllipticFemScheme<DiscreteFunction,
586  Model,
587  ZeroGridFunction<typename DiscreteFunction::FunctionSpaceType,
588  typename DiscreteFunction::GridPartType>,
589  RHSFunctional>
590  ReturnType;
591 
592  return ReturnType(solution,
593  model,
594  GridFunction::zeros(solution.space()),
595  rhsFunctional,
596  name);
597  }
598 
600  template<class DiscreteFunction, class Model>
601  auto ellipticFemScheme(DiscreteFunction& solution,
602  const Model& model,
603  const std::string name = "acfem.schemes.elliptic")
604  {
605  typedef
606  EllipticFemScheme<DiscreteFunction,
607  Model,
608  ZeroGridFunction<typename DiscreteFunction::FunctionSpaceType,
609  typename DiscreteFunction::GridPartType>,
611  ReturnType;
612 
613  return ReturnType(solution,
614  model,
615  GridFunction::zeros(solution.space()),
616  zeroFunctional(solution.space()),
617  name);
618  }
619 
621 
623 
624  } // ACFem::
625 
626 } // Dune::
627 
628 #endif // __ELLIPTIC_FEMSCHEME_HH__
Abstract space adaptative FEM scheme.
Definition: femschemeinterface.hh:70
Potentially overwrite some parameters.
Definition: dataoutput.hh:37
RangeFieldType estimate(const DiscreteFunctionType &uh)
calculate estimator
Definition: ellipticestimator.hh:259
Adaptive fem-scheme for "elliptic" problems.
Definition: ellipticfemscheme.hh:93
virtual void linearSolve(DiscreteFunctionType &rhs, bool forceMatrixAssembling)
Perform only one step of the Newton scheme for the affine-linear case.
Definition: ellipticfemscheme.hh:339
SolverSelector< DiscreteFunctionType, DiscreteModelType > SolverSelectorType
choose type of discrete function, Matrix implementation and solver implementation
Definition: ellipticfemscheme.hh:132
Fem::RestrictProlongDefault< DiscreteFunctionType > RestrictionProlongationType
type of restriction/prolongation projection for adaptive simulations (use default here,...
Definition: ellipticfemscheme.hh:144
InitialGuess InitialGuessType
Initial guess/exact solution.
Definition: ellipticfemscheme.hh:162
virtual size_t size() const
return some measure about the number of DOFs in use
Definition: ellipticfemscheme.hh:478
virtual double error() const
calculate L2/H1 error
Definition: ellipticfemscheme.hh:463
virtual void solve(bool forceMatrixAssembling=true)
Solve the system.
Definition: ellipticfemscheme.hh:297
virtual bool converged() const
check whether solver has converged
Definition: ellipticfemscheme.hh:441
virtual double residual() const
calculate residual (in small l^2)
Definition: ellipticfemscheme.hh:447
virtual double estimate()
calculate error estimator
Definition: ellipticfemscheme.hh:388
virtual int output()
data I/O
Definition: ellipticfemscheme.hh:420
MarkingStrategy< GridPartType > MarkingStrategyType
type of marking strategy
Definition: ellipticfemscheme.hh:159
DirichletConstraints< DiscreteFunctionSpaceType, DiscreteModelType > ConstraintsOperatorType
type of constraints operator
Definition: ellipticfemscheme.hh:150
DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType
type of the discrete function space
Definition: ellipticfemscheme.hh:107
EllipticFemScheme(const EllipticFemScheme &other)
Copy-constructor.
Definition: ellipticfemscheme.hh:229
DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType
type of function space
Definition: ellipticfemscheme.hh:129
virtual void nonLinearSolve(DiscreteFunctionType &rhs)
Run the full Newton-scheme ...
Definition: ellipticfemscheme.hh:321
DiscreteFunctionType::GridType GridType
type of hierarchic grid
Definition: ellipticfemscheme.hh:101
virtual bool mark(const double tolerance)
mark elements for adaptation
Definition: ellipticfemscheme.hh:382
DiscreteFunctionType::GridPartType GridPartType
type of the grid view
Definition: ellipticfemscheme.hh:104
Fem::AdaptationManager< GridType, RestrictionProlongationType > AdaptationManagerType
type of adaptation manager handling adapation and DoF compression
Definition: ellipticfemscheme.hh:147
virtual void adapt()
do the adaptation for a given marking
Definition: ellipticfemscheme.hh:394
virtual std::string name() const
name of the Fem Scheme
Definition: ellipticfemscheme.hh:276
DiscreteFunction DiscreteFunctionType
Type of the discrete solution function.
Definition: ellipticfemscheme.hh:96
DifferentiableEllipticOperator< LinearOperatorType, DiscreteModelType, const ConstraintsOperatorType & > OperatorType
type of error estimator define differential operator
Definition: ellipticfemscheme.hh:154
virtual void initialize()
initialize solution
Definition: ellipticfemscheme.hh:282
Fem::NewtonInverseOperator< LinearOperatorType, LinearInverseOperatorType > NonLinearInverseOperatorType
Non-linear solver.
Definition: ellipticfemscheme.hh:140
DataOutput< GridType, IOTupleType > DataOutputType
type of data writer
Definition: ellipticfemscheme.hh:168
EllipticFemScheme(DiscreteFunctionType &solution, const ModelType &model, const InitialGuessType &initialGuess, const RHSFunctionalType &rhsFunctional, const std::string &name)
Constructor for the elliptic fem-scheme.
Definition: ellipticfemscheme.hh:186
Model ModelType
type of the provided model
Definition: ellipticfemscheme.hh:110
std::tuple< DiscreteFunctionType *, InitialGuessType * > IOTupleType
type of input/output tuple
Definition: ellipticfemscheme.hh:165
The zero functional.
Definition: zero.hh:24
DiscreteModel< Model, DiscreteFunctionSpaceType > DiscreteModelType
In the DG-case the resulting ModelType will a NitscheDirichletBoundaryModel.
Definition: ellipticfemscheme.hh:121
constexpr decltype(auto) asExpression(T &&t)
Return a non-closure expression as is.
Definition: interface.hh:122
auto ellipticFemScheme(DiscreteFunction &solution, const Model &model, const InitialGuess &initialGuess, const RHSFunctional &rhsFunctional, const std::string name="acfem.schemes.elliptic")
Adaptive fem-scheme for "elliptic" problems.
Definition: ellipticfemscheme.hh:542
ModelIntrospection::Traits< Model > ModelTraits
Traits class for models.
Definition: modeltraits.hh:898
Default expression traits definition is a recursion in order to ease disambiguation.
Definition: expressiontraits.hh:54
Select one appropriate (linear) solver depending on whether the model is symmetric and/or semidefinit...
Definition: solverselector.hh:91
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 4, 22:30, 2024)