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
54namespace 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.111.3 (Jul 15, 22:36, 2024)