A very useful compilation of template programming tricks with application to .... catch (...) {. 39 std::cout
The Distributed and Unified Numerics Environment (DUNE) Grid Interface HOWTO Peter Bastian∗ Markus Blatt∗ Andreas Dedner† Christian Engwer∗ Robert Kl¨ofkorn† Martin Nolte† Mario Ohlberger¶ Oliver Sander‡ Version 2.3-svn, June 9, 2013
∗ Abteilung
‘Simulation großer Systeme’, Universit¨at Stuttgart,
Universit¨ atsstr. 38, D-70569 Stuttgart, Germany † Abteilung
f¨ ur Angewandte Mathematik, Universit¨at Freiburg,
Hermann-Herder-Str. 10, D-79104 Freiburg, Germany ¶ Institut
f¨ ur Numerische und Angewandte Mathematik, Universit¨at M¨ unster, Einsteinstr. 62, D-48149 M¨ unster, Germany ‡ Institut
f¨ ur Mathematik II,
Freie Universit¨ at Berlin, Arnimallee 6, D-14195 Berlin, Germany http://www.dune-project.org/
2
This document gives an introduction to the Distributed and Unified Numerics Environment (DUNE). DUNE is a template library for the numerical solution of partial differential equations. It is based on the following principles: i) Separation of data structures and algorithms by abstract interfaces, ii) Efficient implementation of these interfaces using generic programming techniques (templates) in C++ and iii) Reuse of existing finite element packages with a large body of functionality. This introduction covers only the abstract grid interface of DUNE which is currently the most developed part. However, part of DUNE are also the Iterative Solver Template Library (ISTL, providing a large variety of solvers for sparse linear systems) and a flexible class hierarchy for finite element methods. These will be described in subsequent documents. Now have fun!
Thanks to Martin Drohmann for adapting this howto to version 1.2 of the DUNE grid interface.
Contents 1 Introduction 1.1 What is DUNE anyway? 1.2 Download . . . . . . . . 1.3 Installation . . . . . . . 1.4 Code documentation . . 1.5 Licence . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
6 6 7 7 8 8
2 Getting started 9 2.1 Creating your first grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2 Traversing a grid — A first look at the grid interface . . . . . . . . . . . . . . . . . . . . 11 3 The DUNE grid interface 3.1 Grid definition . . . . . . . . . . . 3.2 Concepts . . . . . . . . . . . . . . 3.2.1 Common types . . . . . . . 3.2.2 Concepts of the DUNE grid 3.3 Propagation of type information .
. . . . . . . . . . . . . . . . . . interface . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
16 16 18 18 19 20
4 Constructing grid objects 4.1 Creating Structured Grids . . . . . . . . 4.2 Reading Unstructured Grids from Files 4.3 The DUNE Grid Format (DGF) . . . . 4.4 The Grid Factory . . . . . . . . . . . . . 4.5 Attaching Data to a New Grid . . . . . 4.6 Example: The UnitCube class . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
21 21 22 23 23 25 26
5 Quadrature rules 5.1 Numerical integration . . . . . . . . . . 5.2 Functors . . . . . . . . . . . . . . . . . . 5.3 Integration over a single element . . . . 5.4 Integration with global error estimation
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
32 32 33 33 35
. . . . . .
38 38 39 44 45 46 54
6 Attaching user data to a grid 6.1 Mappers . . . . . . . . . . . . . . . . . . 6.2 Visualization of discrete functions . . . . 6.3 Cell centered finite volumes . . . . . . . 6.3.1 Numerical Scheme . . . . . . . . 6.3.2 Implementation . . . . . . . . . . 6.4 A FEM example: The Poisson equation
. . . . . .
4
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
Contents 6.4.1
Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7 Adaptivity 7.1 Adaptive integration . . . . . . . . . . . 7.1.1 Adaptive multigrid integration . 7.1.2 Implementation of the algorithm 7.2 Adaptive cell centered finite volumes . .
. . . .
65 65 65 66 69
8 Parallelism 8.1 DUNE Data Decomposition Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2 Communication Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3 Parallel finite volume scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
77 77 79 81
. . . .
5
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
1 Introduction 1.1 What is DUNE anyway? DUNE is a software framework for the numerical solution of partial differential equations with gridbased methods. It is based on the following main principles: • Separation of data structures and algorithms by abstract interfaces. This provides more functionality with less code and also ensures maintainability and extendability of the framework. • Efficient implementation of these interfaces using generic programming techniques. Static polymorphism allows the compiler to do more optimizations, in particular function inlining, which in turn allows the interface to have very small functions (implemented by one or few machine instructions) without a severe performance penalty. In essence the algorithms are parametrized with a particular data structure and the interface is removed at compile time. Thus the resulting code is as efficient as if it would have been written for the special case. • Reuse of existing finite element packages with a large body of functionality. In particular the finite element codes UG, [2], Alberta, [8], and ALU3d, [3], have been adapted to the DUNE framework. Thus, parallel and adaptive meshes with multiple element types and refinement rules are available. All these packages can be linked together in one executable. The framework consists of a number of modules which are downloadable as separate packages. The current core modules are: • dune-common contains the basic classes used by all DUNE-modules. It provides some infrastructural classes for debugging and exception handling as well as a library to handle dense matrices and vectors. • dune-grid is the most mature module and is covered in this document. It defines nonconforming, hierarchically nested, multi-element-type, parallel grids in arbitrary space dimensions. Graphical output with several packages is available, e. g. file output to IBM data explorer and VTK (parallel XML format for unstructured grids). The graphics package Grape, [5] has been integrated in interactive mode. • dune-istl – Iterative Solver Template Library. Provides generic sparse matrix/vector classes and a variety of solvers based on these classes. A special feature is the use of templates to exploit the recursive block structure of finite element matrices at compile time. Available solvers include Krylov methods, (block-) incomplete decompositions and aggregation-based algebraic multigrid. • dune-localfunctions – Library of local base functions. Provides classes for base functions on reference elements from which global discrete function spaces can be constructed.
6
1 Introduction Before starting to work with DUNE you might want to update your knowledge about C++ and templates in particular. For that you should have the bible, [9], at your desk. A good introduction, besides its age, is still the book by Barton and Nackman, [1]. The definitive guide to template programming is [10]. A very useful compilation of template programming tricks with application to scientific computing is given in [11] (if you can’t find it on the web, contact us).
1.2 Download The source code of the DUNE framework can be downloaded from the web page. To get started, it is easiest to download the latest stable version of the tarballs of dune-common, dune-grid and dune-grid-howto. These are available on the DUNE download page: http://www.dune-project.org/download.html Alternatively, you can download the latest development version via anonymous SVN. For further information, please see the web page.
1.3 Installation The official installation instructions are available on the web page http://www.dune-project.org/doc/installation-notes.html Obviously, we do not want to copy all this information because it might get outdated and inconsistent then. To make this document self-contained, we describe only how to install DUNE from the tarballs. If you prefer to use the version from SVN, see the web page for further information. Moreover, we assume that you use a UNIX system. If you have the Redmond system then ask them how to install it. In order to build the DUNE framework, you need a standards compliant C++ compiler. We tested compiling with GNU g++ in version ≥ 4.1. Recent versions of Intel icc and clang (≥ 3.0) should work, too. Now extract the tarballs of dune-common, dune-grid and dune-grid-howto into a common directory, say dune-home. Change to this directory and call > dune - common -1.0/ bin / dunecontrol all Replace “1.0” by the actual version number of the package you downloaded if necessary. This should configure and build all DUNE modules in dune-home with a basic configuration. For many of the examples in this howto you need adaptive grids or the parallel features of DUNE. To use adaptive grids, you need to install one of the external grid packages which DUNE provides interfaces for, for instance Alberta, UG and ALUGrid. • Alberta – http://www.alberta-fem.de/ • UG – http://sit.iwr.uni-heidelberg.de/~ug/ • ALUGrid – http://www.mathematik.uni-freiburg.de/IAM/Research/alugrid/
7
1 Introduction To use the parallel code of DUNE, you need an implementation of the Message Passing Interface (MPI), for example MPICH or LAM. For the DUNE build system to find these libraries, the configure scripts of the particular DUNE modules must be passed the locations of the respective installations. The dunecontrol script facilitates to pass options to the configure via a configuration file. Such a configuration file might look like this: CONFIGURE_FLAGS = " -- with - alugrid =/ path / to / alugrid / " \ " -- with - alberta =/ path / to / alberta " \ " -- with - ug =/ path / to / ug -- enable - parallel " MAKE_FLAGS = " -j 2 " If this is saved under the name dunecontrol.opts, you can tell dunecontrol to consider the file by calling > dune - common -1.0/ bin / dunecontrol -- opts = dunecontrol . opts all For information on how to build and configure the respective grids, please see the DUNE web page.
1.4 Code documentation Documentation of the files and classes in DUNE is provided in code and can be extracted using the doxygen1 software available elsewhere. The code documentation can either be built locally on your machine (in html and other formats, e. g. LATEX) or its latest version is available at http://www.dune-project.org/doc/
1.5 Licence The DUNE library and headers are licensed under version 2 of the GNU General Public License2 , with a special exception for linking and compiling against DUNE, the so-called “runtime exception.” The license is intended to be similar to the GNU Lesser General Public License, which by itself isn’t suitable for a C++ template library. The exact wording of the exception reads as follows: As a special exception, you may use the DUNE source files as part of a software library or application without restriction. Specifically, if other files instantiate templates or use macros or inline functions from one or more of the DUNE source files, or you compile one or more of the DUNE source files and link them with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License.
1 2
http://www.doxygen.org/ http://www.gnu.org/licenses/gpl-2.0.html
8
2 Getting started In this section we will take a quick tour through the abstract grid interface provided by DUNE. This should give you an overview of the different classes before we go into the details.
2.1 Creating your first grid Let us start with a replacement of the famous “hello world” program given below. Listing 1 (File dune-grid-howto/gettingstarted.cc) 1 2 3
// −∗− t a b −w i d t h : 4 ; i n d e n t −t a b s −mode : n i l ; c−b a s i c −o f f s e t : 2 −∗− // v i : s e t e t t s =4 sw=2 s t s =2: // $ I d $
4 5 6 7 8 9
// Dune i n c l u d e s # include " config . h " // f i l e c o n s t r u c t e d by . / c o n f i g u r e s c r i p t # include < dune / grid / sgrid . hh > // l o a d s g r i d d e f i n i t i o n # include < dune / grid / common / gridinfo . hh > // d e f i n i t i o n o f g r i d i n f o # include < dune / common / parallel / mpihelper . hh > // i n c l u d e mpi h e l p e r c l a s s
10 11 12 13 14 15
int main ( int argc , char ** argv ) { // i n i t i a l i z e MPI, f i n a l i z e i s done a u t o m a t i c a l l y on e x i t Dune :: MPIHelper :: instance ( argc , argv );
16 17 18 19 20 21 22 23 24 25
// s t a r t t r y / c a t c h b l o c k t o g e t e r r o r messages from dune try { // make a g r i d const int dim =3; typedef Dune :: SGrid < dim , dim > GridType ; Dune :: FieldVector < int , dim > N (3); Dune :: FieldVector < GridType :: ctype , dim > L ( -1.0); Dune :: FieldVector < GridType :: ctype , dim > H (1.0); GridType grid (N ,L , H );
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
// p r i n t some i n f o r m a t i o n a b o u t t h e g r i d Dune :: gridinfo ( grid ); } catch ( std :: exception & e ) { std :: cout
12 13 14 15 16 17 18
template < int dim > class UnitCube < Dune :: AlbertaGrid < dim , dim >, 1 > : public BasicUnitCube < dim > { public : typedef Dune :: AlbertaGrid < dim , dim > GridType ;
19 20 21
private : GridType * grid_ ;
22 23 24 25 26 27 28 29 30
public : UnitCube () { Dune :: GridFactory < GridType > factory ; BasicUnitCube < dim >:: insertVertices ( factory ); BasicUnitCube < dim >:: insertSimplices ( factory ); grid_ = factory . createGrid (); }
31
~ UnitCube () { Dune :: GridFactory < GridType >:: destroyGrid ( grid_ ); }
32 33 34 35 36
GridType & grid () { return * grid_ ; }
37 38 39 40 41
};
42 43
# endif // #i f HAVE ALBERTA
44 45
# endif
ALUGrid The next listing shows the instantiation of ALUSimplexGrid or ALUCubeGrid objects. The ALUGrid implementation supports either simplicial grids, i.e. tetrahedral or triangular grids, and hexahedral grids and the element type has to be chosen at compile-time. This is done by choosing either ALUSimplexGrid or ALUCubeGrid. The variant parameter must be 1. As in the default implementation, grid objects are set up with help of the StructuredGridFactory class. Listing 9 (File dune-grid-howto/unitcube alugrid.hh) 1 2 3
// −∗− t a b −w i d t h : 4 ; i n d e n t −t a b s −mode : n i l ; c−b a s i c −o f f s e t : 2 −∗− // v i : s e t e t t s =4 sw=2 s t s =2: # ifndef U N I T C U B E _ A L U G R I D _ H H
29
4 Constructing grid objects
4
# define U N I T C U B E _ A L U G R I D _ H H
5 6
# include " unitcube . hh "
7 8 9 10
# if HAVE_ALUGRID # include < dune / grid / alugrid . hh > # include < dune / grid / alugrid /3 d / a l u 3 d g r i d f a c t o r y . hh >
11 12 13 14 15 16 17 18
// ALU3dGrid and ALU2dGrid s i m p l e x s p e c i a l i z a t i o n . // Note : e l e m e n t t y p e d e t e r m i n e d by t y p e template < int dim > class UnitCube < Dune :: ALUGrid < dim , dim , Dune :: simplex , Dune :: nonconforming > ,1 > { public : typedef Dune :: ALUGrid < dim , dim , Dune :: simplex , Dune :: nonconforming > GridType ;
19 20 21
private : Dune :: shared_ptr < GridType > grid_ ;
22 23 24 25 26 27 28 29
public : UnitCube () { Dune :: FieldVector < typename GridType :: ctype , dim > lowerLeft (0) ; Dune :: FieldVector < typename GridType :: ctype , dim > upperRight (1) ; Dune :: array < unsigned int , dim > elements ; std :: fill ( elements . begin () , elements . end () , 1) ;
30
grid_ = Dune :: StructuredGridFactory < GridType >:: c r e a t e S i m p l e x G r i d ( lowerLeft , upperRight , elements ) ;
31
}
32 33
GridType & grid () { return * grid_ ; }
34 35 36 37 38
};
39 40 41 42 43 44 45
// ALU3dGrid h e x a h e d r a s p e c i a l i z a t i o n . Note : e l e m e n t t y p e d e t e r m i n e d by t y p e template < > class UnitCube < Dune :: ALUGrid ,1 > { public : typedef Dune :: ALUGrid GridType ;
46 47 48
private : Dune :: shared_ptr < GridType > grid_ ;
49 50 51 52 53 54 55
public : UnitCube () { Dune :: FieldVector < GridType :: ctype ,3 > lowerLeft (0) ; Dune :: FieldVector < GridType :: ctype ,3 > upperRight (1) ; Dune :: array < unsigned int ,3 > elements = {1 ,1 ,1};
56
grid_ = Dune :: StructuredGridFactory < GridType >:: createCubeGrid ( lowerLeft , upperRight , elements ) ;
57
}
58 59
GridType & grid () { return * grid_ ; }
60 61 62 63 64
};
30
4 Constructing grid objects
65
# endif
66 67
# endif
31
5 Quadrature rules In this chapter we explore how an integral Z
f (x) dx
Ω
over some function f : Ω → R can be computed numerically using a DUNE grid object.
5.1 Numerical integration Assume first the simpler task that ∆ is a reference element and that we want to compute the integral over some function fˆ : ∆ → R over the reference element: Z fˆ(ˆ x) dˆ x. ∆
A quadrature rule is a formula that approximates integrals of functions over a reference element ∆. In general it has the form Z n X fˆ(ξi )wi + error. fˆ(ˆ x) dˆ x= i=1
∆
The positions ξi and weight factors wi are dependent on the type of reference element and the number of quadrature points n is related to the error. Using the transformation formula for integrals we can now compute integrals over domains ω ⊆ Ω that are mapped from a reference element, i. e. ω = {x ∈ Ω | x = g(ˆ x), x ˆ ∈ ∆}, by some function g : ∆ → Ω: Z Z n X f (g(ξi ))µ(ξi )wi + error. (5.1) f (x) = f (g(ˆ x))µ(ˆ x) dˆ x= Ω
i=1
∆
p
Here µ(ˆ x) = | det J T (ˆ x)J(ˆ x)| is the integration element and S J(ˆ x) the Jacobian matrix of the map g. The integral over the whole domain Ω requires a grid Ω = k ω k . Using (5.1) on each element we obtain finally Z nk XX X errork . (5.2) f (x) dx = f (g k (ξik ))µk (ξik )wik + Ω
k
i=1
k
Note that each element ωk may in principle have its own reference element which means that quadrature points and weights as well as the transformation and integration element may depend on k. The total error is a sum of the errors on the individual elements. In the following we show how the formula (5.2) can be realised within DUNE.
32
5 Quadrature rules
5.2 Functors The function f is represented as a functor, i. e. a class having an operator() with appropriate arguments. A point x ∈ Ω is represented by an object of type FieldVector where ct is the type for each component of the vector and dim is its dimension. Listing 10 (dune-grid-howto/functors.hh) Here are some examples for functors. 1 2 3 4
// −∗− t a b −w i d t h : 4 ; i n d e n t −t a b s −mode : n i l ; c−b a s i c −o f f s e t : 2 −∗− // v i : s e t e t t s =4 sw=2 s t s =2: # ifndef _ _ D U N E _ G R I D _ H O W T O _ F U N C T O R S _ H H _ _ # define _ _ D U N E _ G R I D _ H O W T O _ F U N C T O R S _ H H _ _
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# include < dune / common / fvector . hh > // a smooth f u n c t i o n template < typename ct , int dim > class Exp { public : Exp () { midpoint = 0.5;} double operator () ( const Dune :: FieldVector < ct , dim >& x ) const { Dune :: FieldVector < ct , dim > y ( x ); y -= midpoint ; return exp ( -3.234*( y * y )); } private : Dune :: FieldVector < ct , dim > midpoint ; };
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
// a f u n c t i o n w i t h a l o c a l f e a t u r e template < typename ct , int dim > class Needle { public : Needle () { midpoint = 0.5; midpoint [ dim -1] = 1; } double operator () ( const Dune :: FieldVector < ct , dim >& x ) const { Dune :: FieldVector < ct , dim > y ( x ); y -= midpoint ; return 1.0/(1 E -4+ y * y ); } private : Dune :: FieldVector < ct , dim > midpoint ; };
40 41
# endif //
DUNE GRID HOWTO FUNCTORS HH
5.3 Integration over a single element The function integrateentity in the following listing computes the integral over a single element of the mesh with a quadrature rule of given order. This relates directly to formula (5.1) above. Listing 11 (dune-grid-howto/integrateentity.hh) 1
// −∗− t a b −w i d t h : 4 ; i n d e n t −t a b s −mode : n i l ; c−b a s i c −o f f s e t : 2 −∗−
33
5 Quadrature rules
2 3 4
// v i : s e t e t t s =4 sw=2 s t s =2: # ifndef D U N E _ I N T E G R A T E _ E N T I T Y _ H H # define D U N E _ I N T E G R A T E _ E N T I T Y _ H H
5 6 7
# include < dune / common / exceptions . hh > # include < dune / geometry / quadraturerules . hh >
8 9 10 11 12 13 14
// ! compute i n t e g r a l o f f u n c t i o n o v e r e n t i t y w i t h g i v e n o r d e r template < class Entity , class Function > double integrateEntity ( const Entity & entity , const Function &f , int p ) { // dimension o f t h e e n t i t y const int dim = Entity :: dimension ;
15
// t y p e used f o r c o o r d i n a t e s i n t h e g r i d typedef typename Entity :: ctype ctype ;
16 17 18
// g e t geometry const typename Entity :: Geometry geometry = entity . geometry ();
19 20 21
// g e t geometry t y p e const Dune :: GeometryType gt = geometry . type ();
22 23 24
// g e t q u a d r a t u r e r u l e o f o r d e r p const Dune :: QuadratureRule < ctype , dim >& rule = Dune :: QuadratureRules < ctype , dim >:: rule ( gt , p );
25 26 27 28
// e n s u r e t h a t r u l e has a t l e a s t t h e r e q u e s t e d o r d e r if ( rule . order () < p ) DUNE_THROW ( Dune :: Exception , " order not available " );
29 30 31 32
// compute a p p r o x i m a t e i n t e g r a l double result =0; for ( typename Dune :: QuadratureRule < ctype , dim >:: const_iterator i = rule . begin (); i != rule . end (); ++ i ) { double fval = f ( geometry . global (i - > position ())); double weight = i - > weight (); double detjac = geometry . i n t e g r a t i o n E l e m e n t (i - > position ()); result += fval * weight * detjac ; }
33 34 35 36 37 38 39 40 41 42 43
// r e t u r n r e s u l t return result ;
44 45 46
}
47 48
# endif
Line 27 extracts a reference to a Dune::QuadratureRule from the Dune::QuadratureRules singleton which is a container containing quadrature rules for all the different reference element types and different orders of approximation. Both classes are parametrized by dimension and the basic type used for the coordinate positions. Dune::QuadratureRule in turn is a container of Dune::QuadraturePoint supplying positions ξi and weights wi . Line 35 shows the loop over all quadrature points in the quadrature rules. For each quadrature point i the function value at the transformed position (line 38), the weight (line 39) and the integration element (line 40) are computed and summed (line 41).
34
5 Quadrature rules
5.4 Integration with global error estimation In the listing below function uniformintegration computes the integral over the whole domain via formula (5.2) and in addition provides an estimate of the error. This is done as follows. Let Ic be the value of the numerically computed integral on some grid and let If be the value of the numerically computed integral on a grid where each element has been refined. Then E ≈ |If − Ic |
(5.3)
is an estimate for the error. If the refinement is such that every element is bisected in every coordinate direction, the function to be integrated is sufficiently smooth and the order of the quadrature rule is p + 1, then the error should be reduced by a factor of (1/2)p after each mesh refinement. Listing 12 (dune-grid-howto/integration.cc) 1 2 3
// −∗− t a b −w i d t h : 4 ; i n d e n t −t a b s −mode : n i l ; c−b a s i c −o f f s e t : 2 −∗− // v i : s e t e t t s =4 sw=2 s t s =2: // $ I d $
4 5 6 7 8
// Dune i n c l u d e s # include " config . h " // f i l e c o n s t r u c t e d by . / c o n f i g u r e s c r i p t # include < dune / grid / sgrid . hh > // l o a d s g r i d d e f i n i t i o n # include < dune / common / parallel / mpihelper . hh > // i n c l u d e mpi h e l p e r c l a s s
9 10 11
# include " functors . hh " # include " integrateentity . hh "
12 13 14 15 16 17 18
// ! uniform r e f i n e m e n t t e s t template < class Grid > void u n i f o r m i n t e g r a t i o n ( Grid & grid ) { // f u n c t i o n t o i n t e g r a t e Exp < typename Grid :: ctype , Grid :: dimension > f ;
19 20 21
// g e t GridView on l e a f g r i d − t y p e typedef typename Grid :: LeafGridView GridView ;
22 23 24
// g e t GridView i n s t a n c e GridView gridView = grid . leafView ();
25 26 27
// g e t i t e r a t o r t y p e typedef typename GridView :: template Codim :: Iterator LeafIterator ;
28 29 30 31 32 33 34 35 36 37
// l o o p o v e r g r i d s e q u e n c e double oldvalue =1 E100 ; for ( int k =0; k < iomanip > < stdio .h > < dune / common / parallel / mpihelper . hh > // i n c l u d e mpi h e l p e r c l a s s < dune / grid / io / file / dgfparser / dgfparser . hh >
# include # include # include # include
" elementdata . hh " " vertexdata . hh " " functors . hh " " unitcube . hh "
11 12 13 14 15 16 17 18 19 20 21 22 23
# ifdef GRIDDIM const int dimGrid = GRIDDIM ; # else const int dimGrid = 2; # endif
24 25 26 27 28 29 30 31
// ! s u p p l y f u n c t o r template < class Grid > void dowork ( Grid & grid , int refSteps = 5 ) { // make f u n c t i o n o b j e c t Exp < typename Grid :: ctype , Grid :: dimension > f ;
32
// r e f i n e t h e g r i d grid . globalRefine ( refSteps );
33 34 35
// c a l l t h e v i s u a l i z a t i o n f u n c t i o n s elementdata ( grid , f ); vertexdata ( grid , f );
36 37 38 39
}
40 41 42 43 44
int main ( int argc , char ** argv ) { // i n i t i a l i z e MPI, f i n a l i z e i s done a u t o m a t i c a l l y on e x i t Dune :: MPIHelper :: instance ( argc , argv );
45 46 47 48 49 50 51 52 53 54 55
// s t a r t t r y / c a t c h b l o c k t o g e t e r r o r messages from dune try { if ( argc > 1 ) { typedef Dune :: GridSelector :: GridType DGFGridType ; // c r e a t e g r i d p o i n t e r Dune :: GridPtr < DGFGridType > gridPtr ( argv [ 1 ] ); dowork ( * gridPtr , 3 ); }
56 57 58 59
/∗ UnitCube uc0 ; UnitCube uc1 ;
60
43
6 Attaching user data to a grid #i f HAVE UG UnitCube< Dune : : UGGrid< dimGrid >, 2 > uc2 ; dowork ( uc2 . g r i d ( ) , 3 ) ; #e n d i f
61 62 63 64 65
#i f HAVE ALBERTA { UnitCube< Dune : : A l b e r t a G r i d < dimGrid , dimGrid >, 1 > u n i t c u b e ; // n o t e : The 3d cube cannot be b i s e c t e d r e c u r s i v e l y dowork ( u n i t c u b e . g r i d ( ) , ( dimGrid < 3 ? 6 : 0) ) ; } #e n d i f // #i f HAVE ALBERTA ∗/
66 67 68 69 70 71 72 73 74
UnitCube < Dune :: SGrid < dimGrid , dimGrid >, 1 > uc4 ; dowork ( uc4 . grid () , 3 );
75 76 77 78 79 80 81
# if HAVE_ALUGRID UnitCube < Dune :: ALUGrid < dimGrid , dimGrid , Dune :: simplex , Dune :: nonconforming > , 1 > uc5 ; dowork ( uc5 . grid () , 3 );
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
# if GRIDDIM == 2 || GRIDDIM == 3 UnitCube < Dune :: ALUGrid < dimGrid , dimGrid , Dune :: cube , Dune :: nonconforming > , 1 > uc6 ; dowork ( uc6 . grid () , 3 ); # endif // #i f GRIDDIM == 2 | | GRIDDIM == 3 # endif // #i f HAVE ALUGRID } catch ( std :: exception & e ) { std :: cout u ( const Dune :: FieldVector < ct , dimworld >& x , double t ) { Dune :: FieldVector < double , dimworld > r (0.5); r [0] = 1.0; return r ; } # endif // DUNE GRID HOWTO TRANSPORTPROBLEM2 HH
The initialization of the concentration vector with the initial condition should also be straightforward now. The function initialize works on a concentration vector c that can be stored in any container type with a vector interface (operator[], size() and copy constructor are needed). Moreover the grid and a mapper for element-wise data have to be passed as well. Listing 17 (File dune-grid-howto/initialize.hh) 1 2 3 4
// −∗− t a b −w i d t h : 4 ; i n d e n t −t a b s −mode : n i l ; c−b a s i c −o f f s e t : 2 −∗− // v i : s e t e t t s =4 sw=2 s t s =2: # ifndef _ _ D U N E _ G R I D _ H O W T O _ I N I T I A L I Z E _ H H _ _ # define _ _ D U N E _ G R I D _ H O W T O _ I N I T I A L I Z E _ H H _ _
5 6
# include < dune / common / fvector . hh >
7 8 9 10 11 12 13 14
// ! i n i t i a l i z e t h e v e c t o r o f unknowns w i t h i n i t i a l v a l u e template < class G , class M , class V > void initialize ( const G & grid , const M & mapper , V & c ) { // f i r s t we e x t r a c t t h e d i m e n s i o n s o f t h e g r i d // c o n s t i n t dim = G : : dimension ; const int dimworld = G :: dimensionworld ;
15
// t y p e used f o r c o o r d i n a t e s i n t h e g r i d typedef typename G :: ctype ct ;
16 17 18
// t y p e o f g r i d v i e w on l e a f p a r t typedef typename G :: LeafGridView GridView ;
19 20 21
// l e a f i t e r a t o r t y p e typedef typename GridView :: template Codim :: Iterator LeafIterator ;
22 23 24
// geometry t y p e typedef typename LeafIterator :: Entity :: Geometry Geometry ;
25 26 27
// g e t g r i d v i e w on l e a f p a r t GridView gridView = grid . leafView ();
28 29 30
// i t e r a t e t h r o u g h l e a f g r i d an e v a l u a t e c0 a t c e l l c e n t e r LeafIterator endit = gridView . template end (); for ( LeafIterator it = gridView . template begin (); it != endit ; ++ it ) { // g e t geometry const Geometry geo = it - > geometry ();
31 32 33 34 35 36 37
// g e t g l o b a l c o o r d i n a t e o f c e l l c e n t e r Dune :: FieldVector < ct , dimworld > global = geo . center ();
38 39 40
// i n i t i a l i z e c e l l c o n c e n t r a t i o n c [ mapper . map (* it )] = c0 ( global );
41 42
}
43 44
}
45 46
# endif //
DUNE GRID HOWTO INITIALIZE HH
47
6 Attaching user data to a grid The main work is now done in the function which implements the evolution (6.14) with optimal time step control via (6.13). In addition to grid, mapper and concentration vector the current time tn is passed and the optimum time step ∆tn selected by the algorithm is returned. Listing 18 (File dune-grid-howto/evolve.hh) 1 2 3 4
// −∗− t a b −w i d t h : 4 ; i n d e n t −t a b s −mode : n i l ; c−b a s i c −o f f s e t : 2 −∗− // v i : s e t e t t s =4 sw=2 s t s =2: # ifndef _ _ D U N E _ G R I D _ H O W T O _ E V O L V E _ H H _ _ # define _ _ D U N E _ G R I D _ H O W T O _ E V O L V E _ H H _ _
5 6
# include < dune / common / fvector . hh >
7 8 9 10 11 12
template < class G , class M , class V > void evolve ( const G & grid , const M & mapper , V & c , double t , double & dt ) { // f i r s t we e x t r a c t t h e d i m e n s i o n s o f t h e g r i d const int dimworld = G :: dimensionworld ;
13 14 15
// t y p e used f o r c o o r d i n a t e s i n t h e g r i d typedef typename G :: ctype ct ;
16 17 18
// t y p e o f g r i d v i e w on l e a f p a r t typedef typename G :: LeafGridView GridView ;
19 20 21
// e l e m e n t i t e r a t o r t y p e typedef typename GridView :: template Codim :: Iterator LeafIterator ;
22 23 24
// l e a f e n t i t y geometry typedef typename LeafIterator :: Entity :: Geometry LeafGeometry ;
25 26 27
// i n t e r s e c t i o n i t e r a t o r t y p e typedef typename GridView :: I n t e r s e c t i o n I t e r a t o r I n t e r s e c t i o n I t e r a t o r ;
28 29 30
// i n t e r s e c t i o n geometry typedef typename I n t e r s e c t i o n I t e r a t o r :: Intersection :: Geometry I n t e r s e c t i o n G e o m e t r y ;
31 32 33
// e n t i t y p o i n t e r t y p e typedef typename G :: template Codim :: EntityPointer EntityPointer ;
34 35 36
// g e t g r i d v i e w on l e a f p a r t GridView gridView = grid . leafView ();
37 38 39 40
// a l l o c a t e a temporary v e c t o r f o r t h e u p d a t e V update ( c . size ()); for ( typename V :: size_type i =0; i < c . size (); i ++) update [ i ] = 0;
41 42 43
// i n i t i a l i z e d t v e r y l a r g e dt = 1 E100 ;
44 45 46 47 48 49 50
// compute u p d a t e v e c t o r and optimum d t i n one g r i d t r a v e r s a l LeafIterator endit = gridView . template end (); for ( LeafIterator it = gridView . template begin (); it != endit ; ++ it ) { // c e l l geometry const LeafGeometry geo = it - > geometry ();
51 52 53 54
// c e l l volume , assume l i n e a r map h e r e double volume = geo . volume ();
55 56 57
// c e l l i n d e x int indexi = mapper . map (* it );
48
6 Attaching user data to a grid
58 59 60
// v a r i a b l e t o compute sum o f p o s i t i v e f a c t o r s double sumfactor = 0.0;
61 62 63 64 65 66 67
// run t h r o u g h a l l i n t e r s e c t i o n s w i t h n e i g h b o r s and boundary I n t e r s e c t i o n I t e r a t o r isend = gridView . iend (* it ); for ( I n t e r s e c t i o n I t e r a t o r is = gridView . ibegin (* it ); is != isend ; ++ is ) { // g e t geometry t y p e o f f a c e const I n t e r s e c t i o n G e o m e t r y igeo = is - > geometry ();
68 69 70 71 72
// g e t normal v e c t o r s c a l e d w i t h volume Dune :: FieldVector < ct , dimworld > i n t e g r a t i o n O u t e r N o r m a l = is - > c e n t e r U n i t O u t e r N o r m a l (); i n t e g r a t i o n O u t e r N o r m a l *= igeo . volume ();
73 74 75
// c e n t e r o f f a c e i n g l o b a l c o o r d i n a t e s Dune :: FieldVector < ct , dimworld > faceglobal = igeo . center ();
76 77 78
// e v a l u a t e v e l o c i t y a t f a c e c e n t e r Dune :: FieldVector < double , dimworld > velocity = u ( faceglobal , t );
79 80 81
// compute f a c t o r o c c u r i n g i n f l u x f o r m u l a double factor = velocity * i n t e g r a t i o n O u t e r N o r m a l / volume ;
82 83 84
// f o r time s t e p c a l c u l a t i o n if ( factor >=0) sumfactor += factor ;
85 86 87 88 89 90 91
// h a n d l e i n t e r i o r f a c e if ( is - > neighbor ()) // ” c o r r e c t ” v e r s i o n { // a c c e s s n e i g h b o r EntityPointer outside = is - > outside (); int indexj = mapper . map (* outside );
92
// compute f l u x from one s i d e o n l y // t h i s s h o u l d become e a s i e r w i t h t h e new I n t e r s e c t i o n I t e r a t o r f u n c t i o n a l i t y ! if ( it - > level () > outside - > level () || ( it - > level ()== outside - > level () && indexi < indexj ) ) { // compute f a c t o r i n n e i g h b o r const LeafGeometry nbgeo = outside - > geometry (); double nbvolume = nbgeo . volume (); double nbfactor = velocity * i n t e g r a t i o n O u t e r N o r m a l / nbvolume ;
93 94 95 96 97 98 99 100 101 102
if ( factor boundary ()) { if ( factor # include < stdio .h >
8 9 10 11 12 13 14 15 16 17 18
template < class G , class V > void vtkout ( const G & grid , const V & c , const char * name , int k , double time =0.0 , int rank =0) { Dune :: VTKWriter < typename G :: LeafGridView > vtkwriter ( grid . leafView ()); char fname [128]; char sername [128]; sprintf ( fname , " %s -%05 d " , name , k ); sprintf ( sername , " % s . series " , name ); vtkwriter . addCellData (c , " celldata " ); vtkwriter . write ( fname , Dune :: VTK :: ascii );
19 20 21 22
if ( rank == 0) { std :: ofstream serstream ( sername , ( k ==0 ? std :: ios_base :: out : std :: ios_base :: app ));
51
6 Attaching user data to a grid
serstream void timeloop ( const G & grid , double tend ) { // make a mapper f o r codim 0 e n t i t i e s i n t h e l e a f g r i d Dune :: L e a f M u l t i p l e C o d i m M u l t i p l e G e o m T y p e M a p p e r mapper ( grid );
25 26 27
// a l l o c a t e a v e c t o r f o r t h e c o n c e n t r a t i o n std :: vector < double > c ( mapper . size ());
28 29 30 31
// i n i t i a l i z e c o n c e n t r a t i o n w i t h i n i t i a l v a l u e s initialize ( grid , mapper , c ); vtkout ( grid ,c , " concentration " ,0 ,0.0);
32 33 34 35 36 37 38
// now do t h e time s t e p s double t =0 , dt ; int k =0; const double saveInterval = 0.1; double saveStep = 0.1; int counter = 1;
39 40 41 42 43
while (t < tend ) { // augment time s t e p c o u n t e r ++ k ;
44
52
6 Attaching user data to a grid // a p p l y f i n i t e volume scheme evolve ( grid , mapper ,c ,t , dt );
45 46 47
// augment time t += dt ;
48 49 50
// c h e c k i f d a t a s h o u l d be w r i t t e n if ( t >= saveStep ) { // w r i t e d a t a vtkout ( grid ,c , " concentration " , counter , t );
51 52 53 54 55 56
// i n c r e a s e c o u n t e r and s a v e S t e p f o r n e x t i n t e r v a l saveStep += saveInterval ; ++ counter ;
57 58 59
}
60 61
// p r i n t i n f o a b o u t time , t i m e s t e p s i z e and c o u n t e r std :: cout
12 13 14 15 16 17 18 19 20 21 22 23 24
# if HAVE_DUNE_ISTL # include < dune / istl / bvector . hh > # include < dune / istl / bcrsmatrix . hh > # include < dune / istl / ilu . hh > # include < dune / istl / operators . hh > # include < dune / istl / solvers . hh > # include < dune / istl / preconditioners . hh > # include < dune / istl / io . hh > # else # include < dune / common / dynvector . hh > # include < dune / common / dynmatrix . hh > # endif // HAVE DUNE ISTL
25 26
# include " shapefunctions . hh "
27 28 29 30 31 32 33 34 35
// P1Elements : // a P1 f i n i t e e l e m e n t d i s c r e t i z a t i o n f o r e l l i p t i c p r o b l e m s D i r i c h l e t // boundary c o n d i t i o n s on s i m p l i c i a l co nf o r mi ng g r i d s template < class GV , class F > class P1Elements { public : static const int dim = GV :: dimension ;
36 37 38 39 40 41 42 43 44
typedef typename GV :: ctype ctype ; # if HAVE_DUNE_ISTL typedef Dune :: BCRSMatrix < Dune :: FieldMatrix < ctype ,1 ,1 > > Matrix ; typedef Dune :: BlockVector < Dune :: FieldVector < ctype ,1 > > ScalarField ; # else typedef Dune :: DynamicMatrix < ctype > Matrix ; typedef Dune :: DynamicVector < ctype > ScalarField ; # endif // HAVE DUNE ISTL
45 46 47 48 49 50
private : typedef typename GV :: template Codim :: Iterator LeafIterator ; typedef typename GV :: template Codim :: Geometry :: J a c o b i a n I n v e r s e T r a n s p o s e d JacobianInverseTransposed ; typedef typename GV :: I n t e r s e c t i o n I t e r a t o r I n t e r s e c t i o n I t e r a t o r ; typedef typename GV :: IndexSet LeafIndexSet ;
51 52 53
const GV & gv ; const F & f ;
54 55 56 57 58 59
public : Matrix A ; ScalarField b ; ScalarField u ; std :: vector < std :: set < int > > a d j a c e n c y P a t t e r n ;
60 61
P1Elements ( const GV & gv_ , const F & f_ ) : gv ( gv_ ) , f ( f_ ) {}
62
58
6 Attaching user data to a grid // s t o r e a d j a c e n c y i n f o r m a t i o n i n a v e c t o r o f s e t s void d e t e r m i n e A d j a c e n c y P a t t e r n () ;
63 64 65
// a s s e m b l e s t i f f n e s s m a t r i x A and r i g h t s i d e b void assemble () ;
66 67 68
// f i n a l l y s o l v e Au = b f o r u void solve () ;
69 70 71
};
72 73 74 75 76 77
template < class GV , class F > void P1Elements < GV , F >:: d e t e r m i n e A d j a c e n c y P a t t e r n () { const int N = gv . size ( dim ) ; a d j a c e n c y P a t t e r n . resize ( N ) ;
78
const LeafIndexSet & set = gv . indexSet () ; const LeafIterator itend = gv . template end () ;
79 80 81
for ( LeafIterator it = gv . template begin () ; it != itend ; ++ it ) { Dune :: GeometryType gt = it - > type () ; const Dune :: template ReferenceElement < ctype , dim > & ref = Dune :: ReferenceElements < ctype , dim >:: general ( gt ) ;
82 83 84 85 86 87
// t r a v e r s e a l l codim−1− e n t i t i e s o f t h e c u r r e n t e l e m e n t and s t o r e a l l // p a i r s o f v e r t i c e s i n a d j a c e n c y P a t t e r n const I n t e r s e c t i o n I t e r a t o r isend = gv . iend (* it ) ; for ( I n t e r s e c t i o n I t e r a t o r is = gv . ibegin (* it ) ; is != isend ; ++ is ) { int vertexsize = ref . size ( is - > indexInInside () ,1 , dim ) ; for ( int i =0; i < vertexsize ; i ++) { int indexi = set . subIndex (* it , ref . subEntity ( is - > indexInInside () ,1 ,i , dim ) , dim ) ; for ( int j =0; j < vertexsize ; j ++) { int indexj = set . subIndex (* it , ref . subEntity ( is - > indexInInside () ,1 ,j , dim ) , dim ) ; a d j a c e n c y P a t t e r n [ indexi ]. insert ( indexj ) ; } } }
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
}
104 105
}
106 107 108 109 110
template < class GV , class F > void P1Elements < GV , F >:: assemble () { const int N = gv . size ( dim ) ;
111 112 113
const LeafIndexSet & set = gv . indexSet () ; const LeafIterator itend = gv . template end () ;
114 115 116 117 118 119
// s e t s i z e s o f A and b # if HAVE_DUNE_ISTL A . setSize (N , N , N + 2* gv . size ( dim -1) ) ; A . setBuildMode ( Matrix :: random ) ; b . resize (N , false ) ;
120 121 122 123
for ( int i = 0; i < N ; i ++) A . setrowsize (i , a d j a c e n c y P a t t e r n [ i ]. size () ) ; A . endrowsizes () ;
124 125
// s e t s p a r s i t y p a t t e r n o f A w i t h t h e i n f o r m a t i o n g a i n e d i n d e t e r m i n e A d j a c e n c y P a t t e r n
59
6 Attaching user data to a grid
126 127 128 129 130 131 132
for ( int i = 0; i < N ; i ++) { std :: template set < int >:: iterator setend = a d j a c e n c y P a t t e r n [ i ]. end () ; for ( std :: template set < int >:: iterator setit = a d j a c e n c y P a t t e r n [ i ]. begin () ; setit != setend ; ++ setit ) A . addindex (i ,* setit ) ; }
133 134 135 136 137 138
A . endindices () ; # else A . resize (N , N ) ; b . resize ( N ) ; # endif // HAVE DUNE ISTL
139 140 141 142
// i n i t i a l i z e A and b A = 0.0; b = 0.0;
143 144 145
// g e t a s e t o f P1 s h a p e f u n c t i o n s const P1ShapeFunctionSet < ctype , ctype , dim >& basis = P1ShapeFunctionSet < ctype , ctype , dim >:: instance () ;
146 147 148 149 150 151 152 153
for ( LeafIterator it = gv . template begin () ; it != itend ; ++ it ) { // d e t e r m i n e geometry t y p e o f t h e c u r r e n t e l e m e n t and g e t t h e matching r e f e r e n c e e l e m e n t Dune :: GeometryType gt = it - > type () ; const Dune :: template ReferenceElement < ctype , dim > & ref = Dune :: ReferenceElements < ctype , dim >:: general ( gt ) ; int vertexsize = ref . size ( dim ) ;
154 155 156 157 158 159 160 161 162
// g e t a q u a d r a t u r e r u l e o f o r d e r one f o r t h e g i v e n geometry t y p e const Dune :: QuadratureRule < ctype , dim >& rule = Dune :: QuadratureRules < ctype , dim >:: rule ( gt ,1) ; for ( typename Dune :: QuadratureRule < ctype , dim >:: const_iterator r = rule . begin () ; r != rule . end () ; ++ r ) { // compute t h e j a c o b i a n i n v e r s e t r a n s p o s e d t o t r a n s f o r m t h e g r a d i e n t s J a c o b i a n I n v e r s e T r a n s p o s e d jacInvTra = it - > geometry () . j a c o b i a n I n v e r s e T r a n s p o s e d (r - > position () ) ;
163
// g e t t h e w e i g h t a t t h e c u r r e n t q u a d r a t u r e p o i n t ctype weight = r - > weight () ;
164 165 166
// compute J a c o b i a n d e t e r m i n a n t f o r t h e t r a n s f o r m a t i o n f o r m u l a ctype detjac = it - > geometry () . i n t e g r a t i o n E l e m e n t (r - > position () ) ; for ( int i = 0; i < vertexsize ; i ++) { // compute t r a n s f o r m e d g r a d i e n t s Dune :: FieldVector < ctype , dim > grad1 ; jacInvTra . mv ( basis [ i ]. e v a l u a t e G r a d i e n t (r - > position () ) , grad1 ) ; for ( int j = 0; j < vertexsize ; j ++) { Dune :: FieldVector < ctype , dim > grad2 ; jacInvTra . mv ( basis [ j ]. e v a l u a t e G r a d i e n t (r - > position () ) , grad2 ) ;
167 168 169 170 171 172 173 174 175 176 177 178
// g a i n g l o b a l i n i d i c e s o f v e r t i c e s i and j and u p d a t e a s s o c i a t e d m a t r i x e n t r y A [ set . subIndex (* it ,i , dim ) ][ set . subIndex (* it ,j , dim ) ] += ( grad1 * grad2 ) * weight * detjac ;
179 180 181
}
182
}
183 184
}
185 186 187
// g e t a q u a d r a t u r e r u l e o f o r d e r two f o r t h e g i v e n geometry t y p e const Dune :: QuadratureRule < ctype , dim >& rule2 = Dune :: QuadratureRules < ctype , dim >:: rule ( gt ,2)
60
6 Attaching user data to a grid
; for ( typename Dune :: QuadratureRule < ctype , dim >:: const_iterator r = rule2 . begin () ; r != rule2 . end () ; ++ r ) { ctype weight = r - > weight () ; ctype detjac = it - > geometry () . i n t e g r a t i o n E l e m e n t (r - > position () ) ; for ( int i = 0 ; i < vertexsize ; i ++) { // e v a l u a t e t h e i n t e g r a n d o f t h e r i g h t s i d e ctype fval = basis [ i ]. e v a l u a t e F u n c t i o n (r - > position () ) * f ( it - > geometry () . global (r - > position () ) ) ; b [ set . subIndex (* it ,i , dim ) ] += fval * weight * detjac ; } }
188 189 190 191 192 193 194 195 196 197 198 199 200
}
201 202
// D i r i c h l e t boundary c o n d i t i o n s : // r e p l a c e l i n e s i n A r e l a t e d t o D i r i c h l e t v e r t i c e s by t r i v i a l l i n e s for ( LeafIterator it = gv . template begin () ; it != itend ; ++ it ) { const I n t e r s e c t i o n I t e r a t o r isend = gv . iend (* it ) ; for ( I n t e r s e c t i o n I t e r a t o r is = gv . ibegin (* it ) ; is != isend ; ++ is ) { // d e t e r m i n e geometry t y p e o f t h e c u r r e n t e l e m e n t and g e t t h e matching r e f e r e n c e e l e m e n t Dune :: GeometryType gt = it - > type () ; const Dune :: template ReferenceElement < ctype , dim > & ref = Dune :: ReferenceElements < ctype , dim >:: general ( gt ) ;
203 204 205 206 207 208 209 210 211 212 213 214
// c h e c k w h e t h e r c u r r e n t i n t e r s e c t i o n i s on t h e boundary if ( is - > boundary () ) { // t r a v e r s e a l l v e r t i c e s t h e i n t e r s e c t i o n c o n s i s t s o f for ( int i =0; i < ref . size ( is - > indexInInside () ,1 , dim ) ; i ++) { // and r e p l a c e t h e a s s o c i a t e d l i n e o f A and b w i t h a t r i v i a l one int indexi = set . subIndex (* it , ref . subEntity ( is - > indexInInside () ,1 ,i , dim ) , dim ) ;
215 216 217 218 219 220 221 222 223
A [ indexi ] = 0.0; A [ indexi ][ indexi ] = 1.0; b [ indexi ] = 0.0;
224 225 226
}
227
}
228
}
229
}
230 231
}
232 233 234 235 236 237 238
# if HAVE_DUNE_ISTL template < class GV , class E > void P1Elements < GV , E >:: solve () { // make l i n e a r o p e r a t o r from A Dune :: MatrixAdapter < Matrix , ScalarField , ScalarField > op ( A ) ;
239 240 241
// i n i t i a l i z e p r e c o n d i t i o n e r Dune :: SeqILUn < Matrix , ScalarField , ScalarField > ilu1 (A , 1 , 0.92) ;
242 243 244 245
// t h e i n v e r s e o p e r a t o r Dune :: BiCGSTABSolver < ScalarField > bcgs ( op , ilu1 , 1e -15 , 5000 , 0) ; Dune :: I n v e r s e O p e r a t o r R e s u l t r ;
246 247 248 249
// i n i t i a l i z e u t o some a r b i t r a r y v a l u e t o a v o i d u b e i n g t h e e x a c t // s o l u t i o n u . resize ( b . N () , false ) ;
61
6 Attaching user data to a grid
250
u = 2.0;
251 252 253 254 255
// f i n a l l y s o l v e t h e s y s t em bcgs . apply (u , b , r ) ; } # endif // HAVE DUNE ISTL
256 257 258 259 260 261 262 263 264 265 266 267 268
// an example r i g h t hand s i d e f u n c t i o n template < class ctype , int dim > class Bump { public : ctype operator () ( Dune :: FieldVector < ctype , dim > x ) const { ctype result = 0; for ( int i =0 ; i < dim ; i ++) result += 2.0 * x [ i ]* (1 - x [ i ]) ; return result ; } };
269 270 271 272 273 274
int main ( int argc , char ** argv ) { # if HAVE_ALBERTA && ALBERTA_DIM ==2 static const int dim = 2; const char * gridfile = " grids /2 dgrid . al " ;
275 276 277
typedef Dune :: AlbertaGrid < dim , dim > GridType ; typedef GridType :: LeafGridView GV ;
278 279 280
typedef GridType :: ctype ctype ; typedef Bump < ctype , dim > Func ;
281 282 283
GridType grid ( gridfile ) ; const GV & gv = grid . leafView () ;
284 285 286
Func f ; P1Elements < GV , Func > p1 ( gv , f ) ;
287 288 289 290 291 292
# if HAVE_DUNE_ISTL grid . globalRefine (16) ; # else grid . globalRefine (10) ; # endif // HAVE DUNE ISTL
293 294 295
std :: cout // f o r i n p u t / o u t p u t t o f i l e s # include < vector > // STL v e c t o r c l a s s # include < dune / grid / common / mcmgmapper . hh > // mapper c l a s s # include < dune / common / parallel / mpihelper . hh > // i n c l u d e mpi h e l p e r c l a s s
9 10 11 12 13 14 15 16 17
// c h e c k s f o r d e f i n e d g r i d t y p e and i n l c u d e s a p p r o p r i a t e d g f p a r s e r i m p l e m e n t a t i o n # include " vtkout . hh " # include " unitcube . hh " # include " t r a n s p o r t p r o b l e m 2 . hh " # include " initialize . hh " # include " parfvdatahandle . hh " # include " parevolve . hh "
18 19 20 21 22
//=============================================================== // t h e time l o o p f u n c t i o n w o r k i n g f o r a l l t y p e s o f g r i d s //===============================================================
23 24 25 26 27 28 29
template < class G > void partimeloop ( const G & grid , double tend ) { // make a mapper f o r codim 0 e n t i t i e s i n t h e l e a f g r i d Dune :: L e a f M u l t i p l e C o d i m M u l t i p l e G e o m T y p e M a p p e r mapper ( grid );
30 31 32
// a l l o c a t e a v e c t o r f o r t h e c o n c e n t r a t i o n std :: vector < double > c ( mapper . size ());
33 34 35 36
// i n i t i a l i z e c o n c e n t r a t i o n w i t h i n i t i a l v a l u e s initialize ( grid , mapper , c ); vtkout ( grid ,c , " pconc " ,0 ,0.0 , grid . comm (). rank ());
37 38 39 40 41 42
// now do t h e time s t e p s double t =0 , dt ; int k =0; const double saveInterval = 0.1; double saveStep = 0.1;
84
8 Parallelism
int counter = 1; while (t < tend ) { // augment time s t e p c o u n t e r k ++;
43 44 45 46 47 48
// a p p l y f i n i t e volume scheme parevolve ( grid , mapper ,c ,t , dt );
49 50 51
// augment time t += dt ;
52 53 54
// c h e c k i f d a t a s h o u l d be w r i t t e n if ( t >= saveStep ) { // w r i t e d a t a vtkout ( grid ,c , " pconc " , counter ,t , grid . comm (). rank ());
55 56 57 58 59 60
// i n c r e a s e c o u n t e r and s a v e S t e p f o r n e x t i n t e r v a l saveStep += saveInterval ; ++ counter ;
61 62 63
}
64 65
// p r i n t i n f o a b o u t time , t i m e s t e p s i z e and c o u n t e r if ( grid . comm (). rank ()==0) std :: cout