Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/src/BandMatrix.F90
3203 views
1
!/*****************************************************************************/
2
! *
3
! * Elmer, A Finite Element Software for Multiphysical Problems
4
! *
5
! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6
! *
7
! * This library is free software; you can redistribute it and/or
8
! * modify it under the terms of the GNU Lesser General Public
9
! * License as published by the Free Software Foundation; either
10
! * version 2.1 of the License, or (at your option) any later version.
11
! *
12
! * This library is distributed in the hope that it will be useful,
13
! * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
! * Lesser General Public License for more details.
16
! *
17
! * You should have received a copy of the GNU Lesser General Public
18
! * License along with this library (in file ../LGPL-2.1); if not, write
19
! * to the Free Software Foundation, Inc., 51 Franklin Street,
20
! * Fifth Floor, Boston, MA 02110-1301 USA
21
! *
22
! *****************************************************************************/
23
!
24
!/******************************************************************************
25
! *
26
! * Authors: Juha Ruokolainen
27
! * Email: [email protected]
28
! * Web: http://www.csc.fi/elmer
29
! * Address: CSC - IT Center for Science Ltd.
30
! * Keilaranta 14
31
! * 02101 Espoo, Finland
32
! *
33
! * Original Date: 01 Oct 1998
34
! *
35
! *****************************************************************************/
36
37
#include "huti_fdefs.h"
38
39
!> \ingroup ElmerLib
40
!> \{
41
42
!-------------------------------------------------------------------------------
43
!> Module defining utility routines & matrix storage for band matrix format.
44
!> This module is currently of no or, only little use as the default
45
!> matrix storage format is CRS.
46
!-------------------------------------------------------------------------------
47
48
MODULE BandMatrix
49
50
USE GeneralUtils
51
52
IMPLICIT NONE
53
54
CONTAINS
55
56
#define BAND_INDEX(i,j) (((j)-1)*(3*A % Subband+1) + (i)-(j)+2*A % Subband+1)
57
#define SBAND_INDEX(i,j) (((j)-1)*(A % Subband+1) + (i)-(j)+1)
58
59
!------------------------------------------------------------------------------
60
!> Zero a Band format matrix
61
!------------------------------------------------------------------------------
62
SUBROUTINE Band_ZeroMatrix(A)
63
!------------------------------------------------------------------------------
64
TYPE(Matrix_t) :: A !< Structure holding matrix
65
66
A % Values = 0.0D0
67
IF ( ASSOCIATED( A % MassValues ) ) A % MassValues = 0.0d0
68
IF ( ASSOCIATED( A % DampValues ) ) A % DampValues = 0.0d0
69
END SUBROUTINE Band_ZeroMatrix
70
!------------------------------------------------------------------------------
71
72
73
!------------------------------------------------------------------------------
74
!> Zero given row from a Band format matrix
75
!------------------------------------------------------------------------------
76
SUBROUTINE Band_ZeroRow( A,n )
77
!------------------------------------------------------------------------------
78
TYPE(Matrix_t) :: A !< Structure holding matrix
79
INTEGER :: n !< Row number to be zerod
80
!------------------------------------------------------------------------------
81
82
INTEGER :: j,k
83
84
IF ( A % Format == MATRIX_BAND ) THEN
85
DO j=MAX(1,n-A % Subband), MIN(A % NumberOfRows, n+A % Subband)
86
A % Values(BAND_INDEX(n,j)) = 0.0d0
87
END DO
88
ELSE
89
DO j=MAX(1,n-A % Subband),n
90
A % Values(SBAND_INDEX(n,j)) = 0.0d0
91
END DO
92
END IF
93
END SUBROUTINE Band_ZeroRow
94
!------------------------------------------------------------------------------
95
96
!------------------------------------------------------------------------------
97
!> Add a given element to the band matrix.
98
!------------------------------------------------------------------------------
99
SUBROUTINE Band_AddToMatrixElement( A,i,j,value )
100
!------------------------------------------------------------------------------
101
TYPE(Matrix_t) :: A !< Structure holding matrix
102
INTEGER :: i !< row number of the matrix element
103
INTEGER :: j !< column number of the matrix element
104
REAL(KIND=dp) :: value !< Value to be added
105
!------------------------------------------------------------------------------
106
INTEGER :: k
107
!------------------------------------------------------------------------------
108
IF ( A % Format == MATRIX_BAND ) THEN
109
k = BAND_INDEX(i,j)
110
A % Values(k) = A % Values(k) + Value
111
ELSE
112
IF ( j <= i ) THEN
113
k = SBAND_INDEX(i,j)
114
A % Values(k) = A % Values(k) + Value
115
END IF
116
END IF
117
END SUBROUTINE Band_AddToMatrixElement
118
!------------------------------------------------------------------------------
119
120
121
!------------------------------------------------------------------------------
122
!> Set a given element in the band matrix.
123
!------------------------------------------------------------------------------
124
SUBROUTINE Band_SetMatrixElement( A,i,j,value )
125
!------------------------------------------------------------------------------
126
TYPE(Matrix_t) :: A !< Structure holding matrix
127
INTEGER :: i !< row number of the matrix element
128
INTEGER :: j !< column number of the matrix element
129
REAL(KIND=dp) :: value !< Value to be set
130
!------------------------------------------------------------------------------
131
132
IF ( A % Format == MATRIX_BAND ) THEN
133
A % Values(BAND_INDEX(i,j)) = Value
134
ELSE
135
IF ( j <= i ) A % Values(SBAND_INDEX(i,j)) = Value
136
END IF
137
END SUBROUTINE Band_SetMatrixElement
138
!------------------------------------------------------------------------------
139
140
!------------------------------------------------------------------------------
141
!> Get a given matrix element of a band matrix format.
142
!------------------------------------------------------------------------------
143
FUNCTION Band_GetMatrixElement( A,i,j ) RESULT ( value )
144
!------------------------------------------------------------------------------
145
TYPE(Matrix_t) :: A !< Structure holding matrix
146
INTEGER :: i !< row number of the matrix element
147
INTEGER :: j !< column number of the matrix element
148
REAL(KIND=dp) :: value !< Value to be obtained
149
!------------------------------------------------------------------------------
150
IF ( A % Format == MATRIX_BAND ) THEN
151
Value = A % Values(BAND_INDEX(i,j))
152
ELSE
153
IF ( j <= i ) Value = A % Values(SBAND_INDEX(i,j))
154
END IF
155
END FUNCTION Band_GetMatrixElement
156
!------------------------------------------------------------------------------
157
158
159
!------------------------------------------------------------------------------
160
!> Add a set of values (.i.e. element stiffness matrix) to a Band format matrix.
161
!------------------------------------------------------------------------------
162
SUBROUTINE Band_GlueLocalMatrix( A,N,Dofs,Indeces,LocalMatrix )
163
!------------------------------------------------------------------------------
164
REAL(KIND=dp) :: LocalMatrix(:,:) !< A (N x Dofs) x ( N x Dofs) matrix holding the values to be
165
!! added to the Band format matrix
166
TYPE(Matrix_t) :: A !< Structure holding matrix, values are affected in the process
167
INTEGER :: N !< Number of nodes in element
168
INTEGER :: Dofs !< Number of degrees of freedom for one node
169
INTEGER :: Indeces(:) !< Maps element node numbers to global (or partition) node numbers
170
!! (to matrix rows and columns, if Dofs = 1)
171
!------------------------------------------------------------------------------
172
! Local variables
173
!------------------------------------------------------------------------------
174
INTEGER :: i,j,k,l,c,ind,Row,Col
175
REAL(KIND=dp), POINTER :: Values(:)
176
!------------------------------------------------------------------------------
177
178
Values => A % Values
179
180
IF ( A % Format == MATRIX_BAND ) THEN
181
DO i=1,N
182
DO k=0,Dofs-1
183
Row = Dofs * Indeces(i) - k
184
DO j=1,N
185
DO l=0,Dofs-1
186
Col = Dofs * Indeces(j) - l
187
ind = BAND_INDEX(Row,Col)
188
Values(ind) = &
189
Values(ind) + LocalMatrix(Dofs*i-k,Dofs*j-l)
190
END DO
191
END DO
192
END DO
193
END DO
194
ELSE
195
DO i=1,N
196
DO k=0,Dofs-1
197
Row = Dofs * Indeces(i) - k
198
DO j=1,N
199
DO l=0,Dofs-1
200
Col = Dofs * Indeces(j) - l
201
IF ( Col <= Row ) THEN
202
ind = SBAND_INDEX(Row,Col)
203
Values(ind) = &
204
Values(ind) + LocalMatrix(Dofs*i-k,Dofs*j-l)
205
END IF
206
END DO
207
END DO
208
END DO
209
END DO
210
END IF
211
212
END SUBROUTINE Band_GlueLocalMatrix
213
!------------------------------------------------------------------------------
214
215
216
!------------------------------------------------------------------------------
217
!> Set value of unknown x_n to given value for symmetric band matrix. This is
218
!> done by replacing the equation of the unknown by x_n = Value (i.e.
219
!> zeroing the row of the unknown in the matrix, and setting diagonal to
220
!> identity). Also the respective column is set to zero (except for the
221
!> diagonal) to preserve symmetry, while also substituting the rhs by
222
!> by rhs(i) = rhs(i) - A(i,n) * Value.
223
!------------------------------------------------------------------------------
224
SUBROUTINE SBand_SetDirichlet( A, b, n, Value )
225
!------------------------------------------------------------------------------
226
TYPE(Matrix_t) :: A !< Structure holding matrix, values are affected in the process
227
REAL(KIND=dp) :: b(:) !< RHS vector
228
REAL(KIND=dp), INTENT(IN) :: Value !< Value for the unknown
229
INTEGER, INTENT(IN) :: n !< Ordered number of the unknown (i.e. matrix row and column number)
230
!------------------------------------------------------------------------------
231
232
INTEGER :: j
233
!------------------------------------------------------------------------------
234
235
DO j=MAX(1,n-A % Subband),n-1
236
b(j) = b(j) - Value * A % Values(SBAND_INDEX(n,j))
237
A % Values(SBAND_INDEX(n,j)) = 0.0d0
238
END DO
239
240
DO j=n+1,MIN(n+A % Subband, A % NumberOfRows)
241
b(j) = b(j) - Value * A % Values(SBAND_INDEX(j,n))
242
A % Values(SBAND_INDEX(j,n)) = 0.0d0
243
END DO
244
245
b(n) = Value
246
A % Values(SBAND_INDEX(n,n)) = 1.0d0
247
!------------------------------------------------------------------------------
248
END SUBROUTINE SBand_SetDirichlet
249
!------------------------------------------------------------------------------
250
251
252
253
!------------------------------------------------------------------------------
254
!> Create the structures required for a Band format matrix.
255
!------------------------------------------------------------------------------
256
FUNCTION Band_CreateMatrix( N,Subband,Symmetric,AllocValues ) RESULT(A)
257
!------------------------------------------------------------------------------
258
INTEGER :: N !< Number of rows for the matrix
259
INTEGER :: Subband !< Max(ABS(Col-Diag(Row))) of the matrix
260
LOGICAL :: Symmetric !< Symmetric or not
261
LOGICAL :: AllocValues !< Should the values arrays be allocated ?
262
TYPE(Matrix_t), POINTER :: A !< Pointer to the created Matrix_t structure.
263
!------------------------------------------------------------------------------
264
INTEGER :: i,j,k,istat
265
!------------------------------------------------------------------------------
266
267
A => AllocateMatrix()
268
269
A % Subband = Subband
270
A % NumberOfRows = N
271
272
IF ( AllocValues ) THEN
273
IF ( Symmetric ) THEN
274
ALLOCATE( A % Values((A % Subband+1)*N), STAT=istat )
275
ELSE
276
ALLOCATE( A % Values((3*A % Subband+1)*N), STAT=istat )
277
END IF
278
END IF
279
280
IF ( istat /= 0 ) THEN
281
CALL Fatal( 'Band_CreateMatrix', 'Memory allocation error.' )
282
END IF
283
284
NULLIFY( A % ILUValues )
285
END FUNCTION Band_CreateMatrix
286
!------------------------------------------------------------------------------
287
288
289
!------------------------------------------------------------------------------
290
!> Matrix vector product (v = Au) for a matrix given in Band format.
291
!------------------------------------------------------------------------------
292
SUBROUTINE Band_MatrixVectorMultiply( A,u,v )
293
!------------------------------------------------------------------------------
294
REAL(KIND=dp), DIMENSION(*) :: u !< vector to be multiplied
295
REAL(KIND=dp), DIMENSION(*) :: v !< result vector
296
TYPE(Matrix_t) :: A !< Structure holding the matrix
297
!------------------------------------------------------------------------------
298
REAL(KIND=dp), POINTER :: Values(:)
299
300
INTEGER :: i,j,k,n
301
REAL(KIND=dp) :: s
302
!------------------------------------------------------------------------------
303
304
Values => A % Values
305
n = A % NumberOfRows
306
307
IF ( A % Format == MATRIX_BAND ) THEN
308
DO i=1,n
309
s = 0.0d0
310
DO j=MAX(1,i-A % Subband), MIN(n,i+A % Subband)
311
s = s + u(j) * Values(BAND_INDEX(i,j))
312
END DO
313
v(i) = s
314
END DO
315
ELSE
316
DO i=1,n
317
s = 0.0d0
318
DO j=MAX(1,i-A % Subband),i
319
s = s + u(j) * Values(SBAND_INDEX(i,j))
320
END DO
321
322
DO j=i+1,MIN(i+A % Subband, A % NumberOfRows)
323
s = s + u(j) * Values(SBAND_INDEX(j,i))
324
END DO
325
v(i) = s
326
END DO
327
END IF
328
329
END SUBROUTINE Band_MatrixVectorMultiply
330
!------------------------------------------------------------------------------
331
332
333
!------------------------------------------------------------------------------
334
!> Matrix vector product (v = Au) for a matrix given in Band format. The
335
!> matrix is accessed from a global variable GlobalMatrix.
336
!------------------------------------------------------------------------------
337
SUBROUTINE Band_MatrixVectorProd( u,v,ipar )
338
!------------------------------------------------------------------------------
339
REAL(KIND=dp), DIMENSION(*) :: u !< Vector to be multiplied
340
REAL(KIND=dp), DIMENSION(*) :: v !< Result vector of the multiplication
341
INTEGER, DIMENSION(*) :: ipar !< structure holding info from (HUTIter-iterative solver package)
342
!------------------------------------------------------------------------------
343
REAL(KIND=dp), POINTER :: Values(:)
344
345
TYPE(Matrix_t), POINTER :: A
346
INTEGER :: i,j,k,n
347
REAL(KIND=dp) :: s
348
!------------------------------------------------------------------------------
349
A => GlobalMatrix
350
351
Values => A % Values
352
n = A % NumberOfRows
353
354
IF ( A % Format == MATRIX_BAND ) THEN
355
IF ( HUTI_EXTOP_MATTYPE == HUTI_MAT_NOTTRPSED ) THEN
356
DO i=1,n
357
s = 0.0d0
358
DO j=MAX(1,i-A % Subband), MIN(n,i+A % Subband)
359
s = s + u(j) * Values(BAND_INDEX(i,j))
360
END DO
361
v(i) = s
362
END DO
363
ELSE
364
v(1:n) = 0.0d0
365
DO i=1,n
366
s = u(i)
367
DO j=MAX(1,i-A % Subband), MIN(n,i+A % Subband)
368
v(j) = v(j) + s * Values(BAND_INDEX(i,j))
369
END DO
370
END DO
371
END IF
372
ELSE
373
DO i=1,n
374
s = 0.0d0
375
DO j=MAX(1,i-A % Subband),i
376
s = s + u(j) * Values(SBAND_INDEX(i,j))
377
END DO
378
379
DO j=i+1,MIN(i+A % Subband, A % NumberOfRows)
380
s = s + u(j) * Values(SBAND_INDEX(j,i))
381
END DO
382
v(i) = s
383
END DO
384
END IF
385
386
END SUBROUTINE Band_MatrixVectorProd
387
!------------------------------------------------------------------------------
388
389
390
391
!------------------------------------------------------------------------------
392
!> Diagonal preconditioning of a Band format matrix.
393
!------------------------------------------------------------------------------
394
SUBROUTINE Band_DiagPrecondition( u,v,ipar )
395
!------------------------------------------------------------------------------
396
REAL(KIND=dp), DIMENSION(*) :: u !< Vector to be multiplied
397
REAL(KIND=dp), DIMENSION(*) :: v !< Result vector of the multiplication
398
INTEGER, DIMENSION(*) :: ipar !< structure holding info from (HUTIter-iterative solver package)
399
!------------------------------------------------------------------------------
400
INTEGER :: i,j,k,n
401
TYPE(Matrix_t), POINTER :: A
402
403
REAL(KIND=dp), POINTER :: Values(:)
404
405
A => GlobalMatrix
406
Values => GlobalMatrix % Values
407
408
n = A % NumberOfRows
409
410
IF ( A % Format == MATRIX_BAND ) THEN
411
DO i=1,n
412
k = BAND_INDEX(i,i)
413
IF ( ABS(Values(k)) > AEPS ) THEN
414
u(i) = v(i) / Values(k)
415
ELSE
416
u(i) = v(i)
417
END IF
418
END DO
419
ELSE
420
DO i=1,n
421
k = SBAND_INDEX(i,i)
422
IF ( ABS(Values(k)) > AEPS ) THEN
423
u(i) = v(i) / Values(k)
424
ELSE
425
u(i) = v(i)
426
END IF
427
END DO
428
END IF
429
END SUBROUTINE Band_DiagPrecondition
430
!------------------------------------------------------------------------------
431
432
END MODULE BandMatrix
433
434
!> \} ElmerLib
435
436
437