Professional Documents
Culture Documents
Advanced Finite Elements Methods: Eric Sonnendr Ucker, Ahmed Ratnani
Advanced Finite Elements Methods: Eric Sonnendr Ucker, Ahmed Ratnani
LESSONS NOTES
WINTERSEMESTER 2015/2016
A Developper tools 27
A.1 Installation and Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
A.2 Editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
A.3 Versioning: svn & git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
A.4 CMake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
A.5 Unit-tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
A.6 Calling Fortran codes from Python: f2py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
A.7 Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3
4 CONTENTS
B Numerical Integration 29
B.1 Quadrature formulae . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
this will create a directory lessons that contains a CMakeLists.txt and source codes for each chapter. Using
cmake, you need to create a build directory and run the following lines:
1 mkdir −p build
2 cd build
3 # cmake must points to the path of CMakeLists.txt file
4 cmake ..
5 make
5
6 CONTENTS
Chapter 1
1.1 Introduction
In this lecture, we will learn how to write Modern Fortran codes. By modern, we mean Object-Oriented
Programming. But why using an old language like Fortran, while we can use C++?
Many reasons for that. First of all
Legacy codes Through the years, the scientific community wrote a lot of good codes.
OOP What a mathematician or a physicist is asking from Fortran and the OOP, is not for sure what the C++
can offer!
In these notes, you will not learn all the features of Fortran. For more details about the language capabilities,
we refer the reader to the books [7, 2, 6, 1]. However, we will introduce, step by step, the features we need.
Remember to always keep it simple (and stupid).
7
8 CHAPTER 1. GETTING STARTED WITH FORTRAN
1 PROGRAM E X _ 1
2 IMPLICIT NONE
3 PRINT ∗ , ’ H e l l o From F o r t r a n ! ’
4 END PROGRAM E X _ 1
You can also use the CMake tool. All our examples make use of it. Now let’s create a procedure/subroutine
that prints the previous message.
1 PROGRAM EX_2
2 IMPLICIT NONE
3 CALL MY_PRINT ( )
4 CONTAINS
5 SUBROUTINE MY_PRINT ( )
6 IMPLICIT NONE
7 PRINT ∗ , ’ H e l l o From F o r t r a n P r o c e d u r e ! ’
8 END SUBROUTINE MY_PRINT
9 END PROGRAM EX_2
Now let’s print some basic declarations. For the moment, we will only cover integers, reals, booleans, con-
stants and arrays.
1 PROGRAM EX_3
2 IMPLICIT NONE
3 CALL MY_PRINT_1 ( )
4 CALL MY_PRINT_2 ( )
5 CONTAINS
6 ! ...................................................
7 SUBROUTINE MY_PRINT_1 ( )
8 IMPLICIT NONE
9 INTEGER : : i
10 INTEGER , PARAMETER : : J = 1
11 REAL ( KIND=8) : : x
12 REAL ( KIND=4) : : y
13
14 PRINT ∗ , ”>>> E n t e r MY PRINT 1”
15
16 i = J + 1
17 x = 2.0 ∗ i
18 y = 2.0 ∗ i
19
20 PRINT ∗, ”J : ”, J
21 PRINT ∗, ”I : ”, i
22 PRINT ∗, ”X : ”, x
23 PRINT ∗, ”Y : ”, y
24
25 PRINT ∗ , ”<<< L e a v e MY PRINT 1”
26
27 END SUBROUTINE MY_PRINT_1
28 ! ...................................................
29
30 ! ...................................................
31 SUBROUTINE MY_PRINT_2 ( )
32 IMPLICIT NONE
33 INTEGER , PARAMETER : : N = 5
34 INTEGER : : i
35 INTEGER , DIMENSION ( 5 ) : : arr_i
36 REAL ( KIND=8) , DIMENSION ( N ) : : arr_x
37 REAL ( KIND=8) , DIMENSION ( N ) : : arr_y
38
39 PRINT ∗ , ”>>> E n t e r MY PRINT 2”
40
41 arr_i = 1
42
43 DO i = 1 , N
1.2. GETTING STARTED 9
44 arr_x ( i ) = i ∗ 1 . 0 d0 / N
45 arr_y ( i ) = i ∗ 1 . 0 / N
46 END DO
47
48 PRINT ∗ , ” ARR I : ” , arr_i
49 PRINT ∗ , ”ARR X : ” , arr_x
50 PRINT ∗ , ”ARR Y : ” , arr_y
51
52 PRINT ∗ , ”<<< L e a v e MY PRINT 2”
53
54 END SUBROUTINE MY_PRINT_2
55 ! ...................................................
56
57 END PROGRAM EX_3
Now, let’s consider the classical case when we want to model an unknown (temperature, pressure, . . . ). Usually,
for instance if we use a Galerkin-Ritz method, our unknown will live in a vectorial space and then, knowning
the basis, one only needs to have the expansion coefficients over it. For this purpose, we introduce the concept
of MODULE which plays the role of the C++ namespace. We introduce also how to construct a data structure
using the keyword TYPE. The following example describes a first attempt to model an unknown. We call it a
field and it relies on the use of the implicit constructor of Fortran.
1 ! ...................................................
2 MODULE MODULE_FIELD
3 IMPLICIT NONE
4 PRIVATE
5 PUBLIC : : FIELD , FIELD_DIMENSION , FIELD_PRINT
6
7 TYPE FIELD
8 INTEGER : : n_dim
9 INTEGER : : n_size
10 END TYPE FIELD
11
12 CONTAINS
13 ! ...................................................
14 FUNCTION F IE LD _D I ME NS IO N ( self ) RESULT( val )
15 IMPLICIT NONE
16 TYPE( FIELD ) , INTENT ( IN ) : : self
17 INTEGER : : val
18
19 val = self % n_dim
20 END FUNCTION F IE LD _ DI ME NS I ON
21 ! ...................................................
22
23 ! ...................................................
24 FUNCTION FIELD_SIZE ( self ) RESULT( val )
25 IMPLICIT NONE
26 TYPE( FIELD ) , INTENT ( IN ) : : self
27 INTEGER : : val
28
29 val = self % n_size
30 END FUNCTION FIELD_SIZE
31 ! ...................................................
32
33 ! ...................................................
34 SUBROUTINE FIELD_PRINT ( self )
35 IMPLICIT NONE
36 TYPE( FIELD ) , INTENT ( IN ) : : self
37
38 PRINT ∗ , ’ F i e l d : dim ’ , self % n_dim
39 PRINT ∗ , ’ size ’ , self % n_size
40 END SUBROUTINE FIELD_PRINT
41 ! ......................... ..........................
42 END MODULE MODULE_FIELD
43 ! ............................ .......................
44
45 ! ...................................................
46 PROGRAM EX_4
47 USE MODULE_FIELD
48 IMPLICIT NONE
49 TYPE( FIELD ) : : U
50
51 U = FIELD ( 1 , 1 0 ) ! Use t h e i m p l i c i t c o n s t r u c t o r
52 CALL FIELD_PRINT ( U ) ! Call a class subroutine
53
54 END PROGRAM EX_4
55 ! ...................................................
10 CHAPTER 1. GETTING STARTED WITH FORTRAN
Remark 1.2.1 Later, we will see how to add the allocation of the coefficients array directly through the implicit
constructor.
1 ! .............................. .....................
2 PROGRAM EX_5
3 IMPLICIT NONE
4 INTEGER , PARAMETER : : M = 5
5 INTEGER , PARAMETER : : N = 5
6 REAL( KIND=8) , DIMENSION ( M , N ) : : Mat
7 REAL( KIND=8) , DIMENSION ( N ) :: x
8 REAL( KIND=8) , DIMENSION ( M ) :: y
9 INTEGER : : i
10 INTEGER : : j
11
12 ! ...
13 Mat = 0 . 0
14 DO j = 1 , N
15 DO i = 1 , M
16 Mat ( i , j ) = ( i+j ) ∗ 1 . 0
17 END DO
18 END DO
19 ! ...
20
21 ! ...
22 x = 1.0
23 ! ...
24
25 ! ...
26 CALL M A T R I X _ P R O D U C T _ V E C T O R _ D E N S E ( Mat , x , y )
27 ! ...
28
29 PRINT ∗ , ” y = M x : ” , y
30
31 CONTAINS
32 ! ...................................................
33 SUBROUTINE M A T R I X _ P R O D U C T _ V E C T O R _ D E N S E ( A , x , y )
34 IMPLICIT NONE
35 REAL ( KIND=8) , DIMENSION ( : , : ) , INTENT ( IN ) : : A
36 REAL ( KIND=8) , DIMENSION ( : ) , INTENT ( IN ) :: x
37 REAL ( KIND=8) , DIMENSION ( : ) , INTENT (INOUT) :: y
38 ! LOCAL
39 INTEGER : : M
40 INTEGER : : N
41 INTEGER : : i
42 INTEGER : : j
43
44 M = SIZE ( A , 1 )
45 N = SIZE ( A , 2 )
46
47 ! ...
48 y = 0.0
49 DO i = 1 , M
50 DO j = 1 , N
51 y(i) = y(i) + A(i , j) ∗ x(j)
52 END DO
53 END DO
54 ! ...
55
56 END SUBROUTINE M A T R I X _ P R O D U C T _ V E C T O R _ D E N S E
57 ! ...................................................
58 END PROGRAM EX_5
59 ! ...................................................
1.3. BASIC STATEMENTS 11
Let us now consider the case of a sparse matrix in CSR format. The following code describes the matrix-vector
product:
1 ! ................................. ..................
2 PROGRAM EX_6
3 IMPLICIT NONE
4 INTEGER , PARAMETER :: N = 4
5 INTEGER , PARAMETER :: NNZ = 9
6 REAL( KIND=8) , DIMENSION ( N ) :: x
7 REAL( KIND=8) , DIMENSION ( N ) :: y
8 REAL( KIND=8) , DIMENSION ( NNZ ) :: A
9 INTEGER ( KIND=8) , DIMENSION ( NNZ ) :: JA
10 INTEGER ( KIND=4) , DIMENSION ( N+1) :: IA
11
12 ! ...
13 JA ( 1 ) = 1 ; A (1) = 1.0
14 JA ( 2 ) = 3 ; A (2) = 2.0
15 JA ( 3 ) = 4 ; A (3) = 3.0
16 JA ( 4 ) = 2 ; A (4) = 4.0
17 JA ( 5 ) = 2 ; A (5) = 5.0
18 JA ( 6 ) = 3 ; A (6) = 6.0
19 JA ( 7 ) = 2 ; A (7) = 7.0
20 JA ( 8 ) = 3 ; A (8) = 8.0
21 JA ( 9 ) = 4 ; A (9) = 9.0
22 ! ...
23
24 ! ...
25 IA ( 1 ) = 1
26 IA ( 2 ) = 4
27 IA ( 3 ) = 5
28 IA ( 4 ) = 7
29 IA ( 5 ) = 10
30 ! ...
31
32 ! ...
33 x = 1.0
34 ! ...
35
36 ! ...
37 CALL M A T R I X _ P R O D U C T _ V E C T O R _ C S R ( IA , JA , A , x , y )
38 ! ...
39
40 PRINT ∗ , ” y = M x : ” , y
41
42 CONTAINS
43 ! ........................................... ........
44 SUBROUTINE M A T R I X _ P R O D U C T _ V E C T O R _ C S R ( IA , JA , A , x , y)
45 IMPLICIT NONE
46 REAL ( KIND=8) , DIMENSION ( : ) , INTENT ( IN ) :: A
47 INTEGER ( KIND=8) , DIMENSION ( : ) , INTENT ( IN ) : : JA
48 INTEGER ( KIND=4) , DIMENSION ( : ) , INTENT ( IN ) : : IA
49 REAL ( KIND=8) , DIMENSION ( : ) , INTENT ( IN ) :: x
50 REAL ( KIND=8) , DIMENSION ( : ) , INTENT (INOUT) :: y
51 ! LOCAL
52 INTEGER : : N
53 INTEGER : : i
54 INTEGER : : k_max
55 INTEGER : : k_min
56
57 N = SIZE ( IA , 1 ) − 1
58
59 ! ...
60 y = 0.0
61 DO i = 1 , N
62 k_min = IA ( i )
63 k_max = IA ( i+1) − 1
64 PRINT ∗ , i , k_min , k_max
65 y ( i ) = DOT_PRODUCT ( A ( k_min : k_max ) , X ( JA ( k_min : k_max ) ) )
66 END DO
67 ! ...
68 END SUBROUTINE M A T R I X _ P R O D U C T _ V E C T O R _ C S R
69 ! ...................................................
70
71 END PROGRAM EX_6
72 ! ...................................................
1.3.2 IF statements
We now implement the matrix that discretizes the Poisson problem in 1D using finite differences with homoge-
neous Dirichlet boundary conditions:
1 ! ...................................................
2 PROGRAM EX_7
3 IMPLICIT NONE
4 ! Example t h a t g e n e r a t e A L a p l a c i a n w i t h D i r i c h l e t BC and FD
5 !
6 ! The l a p l a c i a n l o o k s l i k e :
7 ! > 2 −1 ... 0
8 ! > −1 2 −1 0 ... 0
9 ! > 0 −1 2 −1 0 . . . 0
10 ! 1/ dx ˆ2 > ....
11 ! > ....
12 ! > 0 ... −1 2 −1
13 ! > 0 ... −1 2
14 !
15 INTEGER , PARAMETER : : N = 5
16 REAL( KIND=8) , DIMENSION ( N , N ) : : Mat
17 INTEGER : : i
18 REAL( KIND=8) : : dx
19
20 ! ...
21 dx = 1 . / N
22 ! ...
23
24 ! ...
25 Mat = 0 . 0
26 DO i = 1 , N
27 I F ( i == 1 ) THEN
28 Mat ( i , i ) = 2 . 0
29 Mat ( i , i+1) = −1.0
30 ELSEIF ( i == N ) THEN
31 Mat ( i , i−1) = −1.0
32 Mat ( i , i ) = 2 . 0
33 ELSE
34 Mat ( i , i−1) = −1.0
35 Mat ( i , i ) = 2 . 0
36 Mat ( i , i+1) = −1.0
37 END I F
38 END DO
39 Mat = ( 1 . / dx ∗ ∗2 ) ∗ Mat
40 ! ...
41
42 END PROGRAM EX_7
43 ! ...................................................
1 ! ...................................................
2 MODULE M A T R I X _ U T I L I T I E S
3 IMPLICIT NONE
4 PRIVATE
5 PUBLIC : : MATRIX , &
6 & MATRIX_CREATE_DENSE , MATRIX_CREATE_CSR , &
7 & MATRIX_FREE_DENSE , MATRIX_FREE_CSR , &
8 & MATRIX_PRODUCT_VECTOR
9
10 TYPE MATRIX
11 INTEGER : : matrix_type
12 INTEGER : : N
13 INTEGER : : NNZ
14 REAL ( KIND=8) , DIMENSION ( : , : ) , ALLOCATABLE : : dense_A
15 REAL ( KIND=8) , DIMENSION ( : ) , ALLOCATABLE : : csr_A
16 INTEGER ( KIND=4) , DIMENSION ( : ) , ALLOCATABLE : : csr_IA
1.3. BASIC STATEMENTS 13
99 self % csr_A = A
100
101 self % matrix_type = 1
102
103 END SUBROUTINE M A T R I X _ C R E A T E _ C S R
104 ! ...................................................
105
106 ! ...................................................
107 SUBROUTINE M AT RI X_ F RE E_ CS R ( self )
108 IMPLICIT NONE
109 TYPE( MATRIX ) , INTENT (INOUT) : : self
110 ! LOCAL
111
112 DEALLOCATE( self % csr_IA )
113 DEALLOCATE( self % csr_JA )
114 DEALLOCATE( self % csr_A )
115
116 END SUBROUTINE M AT RI X _F RE E_ C SR
117 ! ...................................................
118
119 ! ........................................... ........
120 SUBROUTINE M A T R I X _ P R O D U C T _ V E C T O R _ C S R ( IA , JA , A , x , y)
121 IMPLICIT NONE
122 REAL ( KIND=8) , DIMENSION ( : ) , INTENT ( IN ) :: A
123 INTEGER ( KIND=8) , DIMENSION ( : ) , INTENT ( IN ) : : JA
124 INTEGER ( KIND=4) , DIMENSION ( : ) , INTENT ( IN ) : : IA
125 REAL ( KIND=8) , DIMENSION ( : ) , INTENT ( IN ) :: x
126 REAL ( KIND=8) , DIMENSION ( : ) , INTENT (INOUT) :: y
127 ! LOCAL
128 INTEGER : : N
129 INTEGER : : i
130 INTEGER : : k_max
131 INTEGER : : k_min
132
133 N = SIZE ( IA , 1 ) − 1
134
135 ! ...
136 y = 0.0
137 DO i = 1 , N
138 k_min = IA ( i )
139 k_max = IA ( i+1) − 1
140 y ( i ) = DOT_PRODUCT ( A ( k_min : k_max ) , X ( JA ( k_min : k_max ) ) )
141 END DO
142 ! ...
143 END SUBROUTINE M A T R I X _ P R O D U C T _ V E C T O R _ C S R
144 ! ...................................................
145
146 ! ...................................................
147 SUBROUTINE M A T R I X _ P R O D U C T _ V E C T O R ( self , x , y )
148 IMPLICIT NONE
149 TYPE( MATRIX ) , INTENT ( IN ) : : self
150 REAL ( KIND=8) , DIMENSION ( : ) , INTENT ( IN ) :: x
151 REAL ( KIND=8) , DIMENSION ( : ) , INTENT (INOUT) :: y
152 ! LOCAL
153
154 SELECT CASE( self % matrix_type )
155 CASE ( 0 )
156 CALL M A T R I X _ P R O D U C T _ V E C T O R _ D E N S E ( self % dense_A , x , y )
157 CASE ( 1 )
158 CALL M A T R I X _ P R O D U C T _ V E C T O R _ C S R ( self % csr_IA , self % csr_JA , self % csr_A ←-
, x , y)
159 CASE DEFAULT
160 PRINT ∗ , ”MATRIX PRODUCT VECTOR : m a t r i x −t y p e n o t y e t i m p l e m e n t e d ”
161 END SELECT
162
163 END SUBROUTINE M A T R I X _ P R O D U C T _ V E C T O R
164 ! ...................................................
165
166 END MODULE M A T R I X _ U T I L I T I E S
167 ! ...................................................
168
169 ! ................................. ..................
170 PROGRAM EX_8
171 USE MATR I X _ U T I L I T I E S
172 IMPLICIT NONE
173 INTEGER , PARAMETER :: M = 5
174 INTEGER , PARAMETER :: N = 4
175 INTEGER , PARAMETER :: NNZ = 9
176 REAL( KIND=8) , DIMENSION ( NNZ ) :: A
177 INTEGER ( KIND=8) , DIMENSION ( NNZ ) :: JA
178 INTEGER ( KIND=4) , DIMENSION ( N+1) :: IA
179 REAL( KIND=8) , DIMENSION ( M , M ) :: Mat
1.3. BASIC STATEMENTS 15
In order to enhance the readablity of our last code, we may want to have one single subroutine to create a
matrix object no matter what type it is. This can be done through the INTERFACE statement.
1 INTERFACE MATRIX_CREATE
2 MODULE PROCEDURE MATRIX_CREATE_DENSE , MATRIX_CREATE_CSR
3 END INTERFACE
Now depending on the actual arguments of your CALL, the compiler will pick the right subroutine.
16 CHAPTER 1. GETTING STARTED WITH FORTRAN
• Undefined
• Null
• Associated
1 REAL , POINTER : : p1
2 INTEGER , DIMENSION ( : ) , POINTER : : p2
3
4 TYPE box
5 INTEGER i_1
6 INTEGER i_2
7 END TYPE
8 TYPE ( box ) , POINTER : : p3
When a pointer is associated, it should give the reference of a Target. This leads to the following rules:
1 REAL , POINTER : : p1
2 REAL , POINTER : : p2
3 REAL , TARGET : : x
4
5 x = 2.0
6
7 p1 => x ! OK
8 p2 => p1 ! OK
9 ! x = p1 ! KO
10 x = 1.0
11
12 PRINT ∗ , p2
7 READ ( ∗ , ∗ ) i
8 p = > a (i , 1:10:3)
9 ! p p o i n t s now t o a (1) , a (4) , a (7) , a (10)
10 PRINT ∗ , p (3)
♣ A pointer can also be allocated. A disctinction between non-allocated and allocated pointers should be
done, using for example the prefix ptr
.
1.5. INPUT/OUTPUT 17
1.5 Input/Output
1.6 Tips
Let’s go back to our dense matrix. The following example shows that you must pay attention to the order of
loops. Indeed, there is an overhead when setting nested loops. The loop range must be increasing from top to
down.
1 SUBROUTINE D O _ F A S T ( x , n , m )
2 IMPLICIT NONE
3 INTEGER, DIMENSION( n , m ) , INTENT(INOUT) :: x
4 INTEGER, INTENT( IN ) :: n
5 INTEGER, INTENT( IN ) :: m
6 ! LOCAL
7 INTEGER : : i , j
8
9 x = 0
10 DO j =1 , m
11 DO i =1 , n
12 x ( i , j ) = i+j
13 END DO
14 END DO
15
16 END SUBROUTINE D O _ F A S T
17
18 SUBROUTINE D O _ S L O W ( x , n , m )
19 IMPLICIT NONE
20 INTEGER, DIMENSION( n , m ) , INTENT(INOUT) :: x
21 INTEGER, INTENT( IN ) :: n
22 INTEGER, INTENT( IN ) :: m
23 ! LOCAL
24 INTEGER : : i , j
25
26 x = 0
27 DO i =1 , n
28 DO j =1 , m
29 x ( i , j ) = i+j
30 END DO
31 END DO
32
33 END SUBROUTINE D O _ S L O W
34
35 PROGRAM E X A M P L E
36 IMPLICIT NONE
37 INTEGER, PARAMETER : : n _ l o o p s = 10
38 INTEGER : : n
39 INTEGER : : m
40 INTEGER : : i
41 INTEGER, DIMENSION ( : , : ) , ALLOCATABLE : : x
42 REAL : : start , finish
43
44 n = 100000 ; m = 1000
45 ALLOCATE( x ( n , m ) )
46
47 CALL C P U _ T I M E ( s t a r t )
48 DO i =1 , n _ l o o p s
49 CALL D O _ F A S T ( x , n , m )
50 END DO
51 CALL C P U _ T I M E ( f i n i s h )
52 p r i n t ∗ , ”> Done w i t h f a s t . ”
53 p r i n t ’ ( ” Time = ” , f 6 . 3 , ” s e c o n d s . ” ) ’ , ( f i n i s h −s t a r t ) / n _ l o o p s
54
55 CALL C P U _ T I M E ( s t a r t )
56 DO i =1 , n _ l o o p s
57 CALL D O _ s l o w ( x , n , m )
58 END DO
59 CALL C P U _ T I M E ( f i n i s h )
60 p r i n t ∗ , ”> Done w i t h s l o w . ”
61 p r i n t ’ ( ” Time = ” , f 6 . 3 , ” s e c o n d s . ” ) ’ , ( f i n i s h −s t a r t ) / n _ l o o p s
62
63 END PROGRAM E X A M P L E
In this example, we clearly see the impact of the overhead when n > m:
2 ahmed $ ./a.out
3 > Done with fast.
4 Time = 0.366 seconds.
5 > Done with slow.
6 Time = 0.794 seconds.
Let us now change the compilation options. First we use the option -O1
Nowdays compilers are smart enough to optimize our loops but not enough to get the best performance.
♣ Always pay attention to the range of nested loops
Chapter 2
2.1 Introduction
We will introduce the basic concepts of OOP through our matrix example. As we can notice in the last code
(see subsection 1.3.3), we have now two kinds of matrices: dense and CSR. Before going further, let’s start by
cleaning our code a little. We split the data-structure into two types: DENSE and CSR. This leads to the following
definitions:
1 TYPE MATRIX_DENSE
2 INTEGER : : N
3 REAL( KIND=8) , DIMENSION ( : , : ) , ALLOCATABLE : : A
4 END TYPE MATRIX_DENSE
5
6 TYPE MATRIX_CSR
7 INTEGER : : N
8 INTEGER : : NNZ
9 REAL( KIND=8) , DIMENSION ( : ) , ALLOCATABLE : : A
10 INTEGER ( KIND=4) , DIMENSION ( : ) , ALLOCATABLE : : IA
11 INTEGER ( KIND=8) , DIMENSION ( : ) , ALLOCATABLE : : JA
12 END TYPE MATRIX_CSR
What is an object?
When you don’t want the external user to access or modify directly some private data in your structure then
using a data-structure is meaningless and it’s not the right way to implement your idea. Objects should hide
their data behind some abstractions and only expose functions or subroutines that operate on that data. This
is a part of what is called Programming by contract.
19
20 CHAPTER 2. MODERN FORTRAN: OBJECT-ORIENTED PROGRAMMING
1 TYPE MATRIX
2 INTEGER : : N
3 END TYPE MATRIX
4
Now, automatically, the objects MATRIX DENSE and MATRIX CSR will inherit the type parameter N which repre-
sents the number of rows and columns (we only consider square matrices).
Type parameters
2.3 Polymorphism
The idea behind the entension of the matrix type, is to collect objects that share some specific behavior for
example. In the case of a matrix, what we usually want to do is: matrix-vector product, solve a linear system,
compute some norms, . . . . Through polymorphism the data type of your variable may vary at run time. A
typical use would be the following:
5 ! . . . t a k e t h e d e n s e m a t r i x and do some s t u f f
6 ptr_matrix => dense
7 ! ...
8
• The use of the TARGET attribut for both DENSE and CSR variables,
• The variables DENSE and CSR are declared with the keyword TYPE while the matrix pointer, the polymorphic
variable, is defined with the keyword CLASS.
Unlimited polymorphism
♣ Be careful, blocks should be small, otherwise it will be painful to navigate through the file, specially if
there many ASSOCIATE blocks
.
The same strategy can be applied for the MATRIX PRODUCT VECTOR subroutine.
♣ This is straitforward when the involved subroutines/functions have the same signature. This is not the
case in general, and sometime, you may need to use opional arguments.
1 TYPE MATRIX
2 INTEGER : : N
3 END TYPE MATRIX
4
♣ Do not use the PASS statement. The resulting code is less clear.
8 ABSTRACT INTERFACE
9 SUBROUTINE MATRIX_FREE ( self )
10 IMPORT MATRIX
11 IMPLICIT NONE
12 CLASS ( MATRIX ) , INTENT(INOUT) : : self
13 END SUBROUTINE MATRIX_FREE
14 END INTERFACE
15
16 ABSTRACT INTERFACE
17 SUBROUTINE MATRIX_PRODUCT_VECTOR ( self , x , y )
18 IMPORT MATRIX
19 IMPLICIT NONE
20 CLASS ( MATRIX ) , INTENT( IN ) : : self
21 REAL( KIND=8) , DIMENSION ( : ) , INTENT( IN ) :: x
22 REAL( KIND=8) , DIMENSION ( : ) , INTENT(INOUT) :: y
23 END SUBROUTINE MATRIX_PRODUCT_VECTOR
24 END INTERFACE
2.7 Operators
The aim of this section is to make our code more clear through the definition of some basic operators: +, −, ∗, ==
, ! = and ask our objects to provide these operations. Before doing so, we need to ask ourselves some questions:
2. although we understand what to do when adding two csr/dense matrices, can we add a csr matrix to a
dense matrix? what about the opposite?
24 CHAPTER 2. MODERN FORTRAN: OBJECT-ORIENTED PROGRAMMING
Chapter 3
3.1 Introduction
3.1.1 The 1D case: code description
We decribe here the initial Fortran code for our project. This code solves the 1D Poisson equation. It has two
files fem1d lagrange.F90 and main.F90. The first file contains the following routines:
FEM1D LAGRANGE STIFFNESS This subroutine assembles the stiffness and mass matrices and the load
R8MAT FS factors and solves a system with one right hand side.
25
26 CHAPTER 3. PROJECT: A FINITE ELEMENT LIBRARY
1 gfortran −c fem1d_lagrange.F90
2 gfortran main.F90 fem1d_lagrange.o −o fem.exe
1 ./fem.exe
1 TYPE DEF_ABSTRACT_SPACE
2 INTEGER : : oi_dim
3 END TYPE DEF_ABSTRACT_SPACE
A function that lives in the discrete space will be called a field. We can therefor define an abstract field as
well as specific fields depending on the spaces H 1 , H(div ), H(rot ), L2 .
1 TYPE DEF_ABSTRACT_FIELD
2 INTEGER : : oi_dim
3 END TYPE DEF_ABSTRACT_FIELD
Appendix A
Developper tools
27
28 APPENDIX A. DEVELOPPER TOOLS
Appendix B
Numerical Integration
1 1 3
Figure B.1: The quadrature points formulae for a mesh {x0 = 0, x1 = 4
, x2 = 2
, x3 = 4
, x4 = 1} for a quadratic polynomial
degree.
29
30 APPENDIX B. NUMERICAL INTEGRATION
Appendix C
Definition C.1.1 (The vec operator) Let A = (aij ) ∈ Mn×m , the vec operator is defined as,
A:,1
vecA = ... ∈ Rmn (C.1.1)
A:,m
which is simply a vector composed by stacking all the columns of A. Where we denote A:,j the j th column of A.
We also define the inverse operator of vec by,
Definition C.1.2 (Kronecker product) Let A = (aij ) ∈ Mm×n and B = (bij ) ∈ Mr×s be two matrices.
The Kronecker product of A and B, denoted by A ⊗ B ∈ Mmr×ns , defines the following matrix:
a11 B a12 B ··· a1n B
a21 B a22 B ··· a2n B
A⊗B = (C.1.3)
.. .. ..
. . .
am1 B am2 B ··· amn B
Example
Let
a11 a12 b11 b12
A= , B=
a21 a22 b21 b22
31
32 APPENDIX C. APPLIED LINEAR ALGEBRA
Properties
Proposition C.1.3 If α is a scalar, then
A ⊗ αB = αA ⊗ B (C.1.5)
Proposition C.1.4 We have,
(A + B) ⊗ C = A ⊗ C + B ⊗ C (C.1.6)
A ⊗ (B + C) = A ⊗ B + A ⊗ C (C.1.7)
Proposition C.1.5 (Associativity)
A ⊗ B ⊗ C = A ⊗ (B ⊗ C) = (A ⊗ B) ⊗ C (C.1.8)
Proposition C.1.6 (Mixed Product Rule)
(A ⊗ B)(C ⊗ D) = AC ⊗ BD (C.1.9)
and,
(A ⊗ B)p = Ap ⊗ B p , ∀p ∈ N (C.1.10)
Proposition C.1.7
(A ⊗ B)T = AT ⊗ B T (C.1.11)
Proposition C.1.8
(A ⊗ B)−1 = A−1 ⊗ B −1 (C.1.12)
Proposition C.1.9
vec(ABC) = (C T ⊗ A)vec(B) (C.1.13)
Proposition C.1.10
tr(A ⊗ B) = tr(B ⊗ A) = tr(A)tr(B) (C.1.14)
Proposition C.1.11 Let A ∈ Mn×n and B ∈ Mm×m , we have,
mspec(A ⊗ B) = {λµ, λ ∈ mspec(A), µ ∈ mspec(B)} (C.1.15)
Proposition C.1.12 Let A ∈ Mn×n and B ∈ Mm×m , we have,
det(A ⊗ B) = (detA)m (detB)n (C.1.16)
We deduce from C.1.15,
Proposition C.1.13 Let A ∈ Mn×n , we have,
ρ(A ⊗ A) = ρ(A)2 (C.1.17)
Proposition C.1.14 Let f be an analytic function, A ∈ Mn×n such that f (A) exists, then we have,
f (Im ⊗ A) = Im ⊗ f (A) (C.1.18)
f (A ⊗ Im ) = f (A) ⊗ Im (C.1.19)
Proposition C.1.15 Let X ∈ Rn and Y ∈ Rm , be two vectors. We have,
XY T = X ⊗ (Y T ) = (Y T ) ⊗ X (C.1.20)
moreover, we have,
vec(XY T ) = Y ⊗ X (C.1.21)
C.1. KRONECKER ALGEBRA 33
Definition C.1.16 (Kronecker permutation matrix) The Kronecker permutation matrix Pn,m ∈
Mnm×nm , is defined by,
n,m
X
Pn,m = Ei,j,n×m ⊗ Ej,i,m×n (C.1.22)
i,j=1
Proposition C.1.18 Let us consider the Kronecker permutation matrix Pn,m ∈ Mnm×nm . Then we have,
• Pn,m
T −1
= Pn,m = Pm,n
• Pn,m is orthogonal,
• Pn,n is a reflector,
• trPn,n = n,
• if X ∈ Rn and Y ∈ Rm , then,
Pn,m (Y ⊗ X) = X ⊗ Y (C.1.24)
Proposition C.1.19 Let A ∈ Mn×n and B ∈ Mm×m , then we have the following properties,
Proposition C.1.20 Let A, C ∈ Mn×m and B, D ∈ Mr×s . If A is (left equivalent, right equivalent, equivalent)
to C, and assume that B is (left equivalent, right equivalent, equivalent) to D. Then, A ⊗ B is (left equivalent,
right equivalent, equivalent) to C ⊗ D.
Remark C.1.21 The use of Kronecker product preconditioners is well known [13, 8, 12, 5], it is based on
results of the form,
C.1.2 Solving AX + XB = C
Let A ∈ Mn×n , B ∈ Mm×m and C ∈ Mn×m . The aim of this section, is to solve the equation:
AX + XB = C (C.1.30)
we can rewrite this equation in term of the Kronecker sum:
(B T ⊕ A)vecX = vecC (C.1.31)
or equivalently,
Gx = c (C.1.32)
where, G = (B T ⊕ A), x = vecX, and c = vecC.
Using the property C.1.29, we can easily check that C.1.30 has a unique solution if and only if G is nonsingular,
i.e λ + µ 6= 0, ∀λ ∈ mspec(A), ∀µ ∈ mspec(B), which can be written in the form,
mspec(A) ∩ mspec(−B) = ∅ (C.1.33)
Proposition C.1.24 If mspec(A)∩mspec(−B)
∅, then there
= exists a unique matrix X ∈ Mn×m , satisfying
A C A 0
C.1.30. Moreover, the matrices and are similar and verify,
0 −B 0 −B
A C I X A 0 I −X
= . (C.1.34)
0 −B 0 I 0 −B 0 I
[1] Ed Akin. Object Oriented Programming Via FORTRAN 90/95. Cambridge University Press, New York,
NY, USA, 2003.
[2] N.S. Clerman and W. Spector. Modern Fortran: Style and Usage. Cambridge University Press, 2011.
[3] NMPP Division. Fortran programming guidelines. In progress.
[4] A. Graham. Kronecker products and matrix calculus with applications. 1981.
[5] Laura Grigori and Hua Xiang. Kronecker Product Approximation Preconditioners for Convection-diffusion
Model Problems. Technical Report RR-6536, INRIA, 2008.
[6] Arjen Markus. Modern Fortran in Practice. Cambridge University Press, 2012. Cambridge Books Online.
[7] Michael Metcalf, John Reid, and Malcolm Cohen. Modern Fortran Explained. Oxford University Press,
Inc., New York, NY, USA, 4th edition, 2011.
[8] Langville A. N. and Stewart W. J. A kronecker product approximate preconditioner for sans. Numerical
Linear Algebra with Applications, 11:723–752, 2004.
[9] Philip Rabinowitz and J. Davis Philip. Methods of numerical integration (second edition). Academic Press,
second edition, 1984.
[10] Bernstein D. S. Matrix Mathematics: Theory, Facts, and Formulas. PRINCETON UNIVERSITY PRESS,
second edition, 2009.
[11] Y. Saad. Iterative Methods for Sparse Linear Systems. Society for Industrial and Applied Mathematics,
Philadelphia, PA, USA, 2nd edition, 2003.
[12] Elisabeth Ullmann. A kronecker product preconditioner for stochastic galerkin finite element discretizations.
Siam Journal on Scientific Computing, 32:923–946, 2010.
[13] Charles F. van Loan. The ubiquitous kronecker product. J. Comput. Appl. Math., 123:85–100, November
2000.
37