Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/src/BandwidthOptimize.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: 17 Oct 1996
34
! *
35
! *****************************************************************************/
36
37
!> \ingroup ElmerLib
38
!> \{
39
40
!-------------------------------------------------------------------------------
41
!> Module for reordering variables for bandwidth and/or gaussian elimination
42
!> fillin optimization. Also computes node to element connections (which
43
!> implies node to node connections, and thus the global matrix structure).
44
!-------------------------------------------------------------------------------
45
MODULE BandwidthOptimize
46
47
!-------------------------------------------------------------------------------
48
USE ListMatrix
49
!-------------------------------------------------------------------------------
50
51
IMPLICIT NONE
52
53
!-------------------------------------------------------------------------------
54
TYPE Label_t
55
INTEGER :: Value
56
TYPE(Label_t), POINTER :: Next
57
END TYPE Label_t
58
59
TYPE LabelPointer_t
60
TYPE(Label_t), POINTER :: ListHead
61
END TYPE LabelPointer_t
62
63
LOGICAL, PRIVATE :: ForceReorder
64
!-------------------------------------------------------------------------------
65
66
CONTAINS
67
68
!-------------------------------------------------------------------------------
69
!> Subroutine for computing the bandwidth of a sparse matrix.
70
!-------------------------------------------------------------------------------
71
FUNCTION ComputeBandwidth( N, List, Reorder, &
72
InvInitialReorder ) RESULT(HalfBandWidth)
73
!-------------------------------------------------------------------------------
74
TYPE(ListMatrix_t) :: List(:)
75
INTEGER :: n
76
INTEGER :: HalfBandWidth
77
INTEGER, OPTIONAL, TARGET :: Reorder(:), InvInitialReorder(:)
78
!-------------------------------------------------------------------------------
79
INTEGER :: i,j,k,istat
80
TYPE(ListMatrixEntry_t), POINTER :: CList
81
INTEGER, POINTER :: pReorder(:), pInvInitialReorder(:)
82
!-------------------------------------------------------------------------------
83
HalfBandWidth = 0
84
85
! Let's try with pointers as gcc 10 might not like PRESENT within OMP pragmas..
86
pReorder => NULL()
87
pInvInitialReorder => NULL()
88
89
IF( PRESENT(Reorder) ) pReorder => Reorder
90
IF( PRESENT(InvInitialReorder) ) pInvInitialReorder => InvInitialReorder
91
92
!$OMP PARALLEL DO &
93
!$OMP SHARED(List, pReorder, pInvInitialReorder, N) &
94
!$OMP PRIVATE(Clist, j, k) &
95
!$OMP REDUCTION(max:HalfBandWidth) &
96
!$OMP DEFAULT(NONE)
97
DO i=1,n
98
CList => List(i) % Head
99
j = i
100
IF ( ASSOCIATED(pInvInitialReorder ) ) j = pInvInitialReorder(j)
101
DO WHILE( ASSOCIATED( CList ) )
102
k = CList % Index
103
IF ( ASSOCIATED(pInvInitialReorder) ) k = pInvInitialReorder(k)
104
IF ( ASSOCIATED( pReorder ) ) THEN
105
HalfBandwidth = MAX( HalfBandWidth, ABS(pReorder(j)-pReorder(k)) )
106
ELSE
107
HalfBandwidth = MAX( HalfBandWidth, ABS(j-k) )
108
END IF
109
Clist => Clist % Next
110
END DO
111
END DO
112
!$OMP END PARALLEL DO
113
!-------------------------------------------------------------------------------
114
END FUNCTION ComputeBandwidth
115
!-------------------------------------------------------------------------------
116
117
118
#if 0
119
SUBROUTINE OrderPermByMortars(Mesh,Perm)
120
TYPE(Mesh_t), POINTER :: Mesh
121
INTEGER :: Perm(:)
122
123
INTEGER :: SlaveTag, MasterTag, DefaultTag, i,j,k,n
124
INTEGER, ALLOCATABLE :: NodeTag(:)
125
LOGICAL, ALLOCATABLE :: SlaveBC(:), MasterBC(:)
126
TYPE(Element_t), POINTER :: Element
127
LOGICAL :: Found
128
129
n = CurrentModel % NumberOfBCs
130
ALLOCATE(SlaveBC(n), MasterBC(n) )
131
SlaveBC = .FALSE.; MasterBC = .FALSE.
132
133
DO i=1,CurrentModel % NumberOfBCs
134
j = ListGetInteger( Currentmodel % BCs(i) % Values,'Mortar BC', Found )
135
IF(Found ) THEN
136
SlaveBC(i) = .TRUE.
137
MasterBC(j) = .TRUE.
138
END IF
139
END DO
140
141
IF(.NOT. ANY(SlaveBC)) RETURN
142
143
! Tags should have values 1,2,3
144
SlaveTag = ListGetInteger( CurrentModel % Solver % Values,'Slave Tag',UnfoundFatal=.TRUE.)
145
MasterTag = ListGetInteger( CurrentModel % Solver % Values,'Master Tag',UnfoundFatal=.TRUE.)
146
DefaultTag = 6 - SlaveTag - MasterTag
147
148
ALLOCATE( NodeTag( Mesh % NumberOfNodes ) )
149
NodeTag = DefaultTag
150
151
DO i=Mesh % NumberOfBulkElements+1, &
152
Mesh % NumberOfBulkElements + Mesh % NumberOfBoundaryElements
153
Element => Mesh % Elements(i)
154
IF(.NOT. ASSOCIATED(Element % BoundaryInfo) ) CYCLE
155
j = Element % BoundaryInfo % Constraint
156
157
IF(SlaveBC(j)) NodeTag(Element % NodeIndexes) = SlaveTag
158
IF(MasterBC(j)) NodeTag(Element % NodeIndexes) = MasterTag
159
END DO
160
161
k = 0
162
! Here we go through cases 1,2,3
163
DO j=1,3
164
DO i=1, Mesh % NumberOfNodes
165
IF(Perm(i)==0) CYCLE
166
IF(NodeTag(i) == j) THEN
167
k = k + 1
168
Perm(i) = k
169
END IF
170
END DO
171
END DO
172
173
END SUBROUTINE OrderPermByMortars
174
#endif
175
176
177
!-------------------------------------------------------------------------------
178
!> Subroutine for reordering variables for bandwidth and/or gaussian elimination
179
!> fillin optimization. Also computes node to element connections (which
180
!> implies node to node connections, and thus the global matrix structure).
181
!-------------------------------------------------------------------------------
182
FUNCTION OptimizeBandwidth( ListMatrix, Perm, InvInitialReorder, LocalNodes, &
183
Optimize, UseOptimized, Equation ) RESULT( HalfBandWidth )
184
!-------------------------------------------------------------------------------
185
use spariterglobals
186
187
INTEGER, DIMENSION(:) :: Perm, InvInitialReorder
188
LOGICAL :: Optimize, UseOptimized
189
CHARACTER(LEN=*) :: Equation
190
TYPE(ListMatrix_t) :: ListMatrix(:)
191
192
INTEGER :: HalfBandWidth, LocalNodes
193
!-------------------------------------------------------------------------------
194
195
LOGICAL(KIND=1), ALLOCATABLE :: DoneAlready(:)
196
INTEGER, ALLOCATABLE :: PermLocal(:),DoneIndex(:)
197
LOGICAL :: Newroot, Finished
198
INTEGER :: MinDegree,StartNode,MaxLevel
199
INTEGER :: Indx,i,j,k,n,k1,k2,HalfBandWidthBefore,HalfBandWidthAfter,istat
200
201
TYPE(Element_t),POINTER :: Element
202
TYPE(ListMatrixEntry_t), POINTER :: p
203
!-------------------------------------------------------------------------------
204
205
CALL Info( 'OptimizeBandwidth', &
206
'---------------------------------------------------------', Level=6 )
207
CALL Info( 'OptimizeBandwidth', 'Computing matrix structure for: '// TRIM(Equation) , Level=6)
208
209
HalfBandwidth = ComputeBandWidth( LocalNodes, ListMatrix )+1
210
211
CALL Info( 'OptimizeBandwidth','Initial bandwidth for '&
212
//TRIM(Equation)//': '//I2S(HalfBandwidth),Level=4)
213
214
IF ( .NOT.Optimize ) THEN
215
CALL Info( 'OptimizeBandwidth', &
216
'---------------------------------------------------------', Level=6 )
217
RETURN
218
END IF
219
220
!-------------------------------------------------------------------------------
221
HalfBandWidthBefore = HalfBandWidth
222
223
!-------------------------------------------------------------------------------
224
! Search for node to start
225
!-------------------------------------------------------------------------------
226
StartNode = 1
227
MinDegree = ListMatrix(StartNode) % Degree
228
DO i=1,LocalNodes
229
IF ( ListMatrix(i) % Degree < MinDegree ) THEN
230
StartNode = i
231
MinDegree = ListMatrix(i) % Degree
232
END IF
233
ListMatrix(i) % Level = 0
234
END DO
235
236
ALLOCATE(DoneAlready(LocalNodes),STAT=istat)
237
IF( istat /= 0 ) THEN
238
CALL Fatal('OptimizeBandwidth','Allocation error for DoneAlready of size: '&
239
//I2S(LocalNodes))
240
END IF
241
242
MaxLevel = 0
243
DoneAlready = .FALSE.
244
245
CALL Levelize( StartNode,0 )
246
247
NewRoot = .TRUE.
248
DO WHILE( NewRoot )
249
NewRoot = .FALSE.
250
MinDegree = ListMatrix(StartNode) % Degree
251
k = StartNode
252
253
DO i=1,LocalNodes
254
IF ( ListMatrix(i) % Level == MaxLevel ) THEN
255
IF ( ListMatrix(i) % Degree < MinDegree ) THEN
256
k = i
257
MinDegree = ListMatrix(i) % Degree
258
END IF
259
END IF
260
END DO
261
262
IF ( k /= StartNode ) THEN
263
j = MaxLevel
264
MaxLevel = 0
265
DoneAlready = .FALSE.
266
267
CALL Levelize( k,0 )
268
269
IF ( j > MaxLevel ) THEN
270
NewRoot = .TRUE.
271
StartNode = j
272
END IF
273
END IF
274
END DO
275
!-------------------------------------------------------------------------------
276
ALLOCATE( PermLocal(SIZE(Perm)), STAT=istat )
277
IF( istat /= 0 ) THEN
278
CALL Fatal('OptimizeBandwidth','Allocation error for PermLocal: '//&
279
I2S(SIZE(Perm)))
280
END IF
281
PermLocal = 0
282
283
ALLOCATE( DoneIndex(LocalNodes), STAT=istat )
284
IF( istat /= 0 ) THEN
285
CALL Fatal('OptimizeBandwidth','Allocation error for DoneIndex: '&
286
//I2S(LocalNodes))
287
END IF
288
DoneIndex = 0
289
!-------------------------------------------------------------------------------
290
! This loop really does the thing
291
!-------------------------------------------------------------------------------
292
Indx = 1
293
PermLocal(Indx) = StartNode
294
DoneIndex(StartNode) = Indx
295
Indx = Indx + 1
296
297
DO i=1,LocalNodes
298
IF ( PermLocal(i)==0 ) THEN
299
DO j=1,LocalNodes
300
IF ( DoneIndex(j)==0 ) THEN
301
PermLocal(Indx) = j
302
DoneIndex(j) = Indx
303
Indx = Indx + 1
304
EXIT
305
END IF
306
END DO
307
END IF
308
CALL Renumber(ListMatrix(PermLocal(i)) % Head)
309
END DO
310
!-------------------------------------------------------------------------------
311
! Store it the other way round for FEM, and reverse order for profile
312
! optimization
313
!-------------------------------------------------------------------------------
314
DoneIndex = 0
315
DO i=1,LocalNodes
316
DoneIndex(PermLocal(i)) = LocalNodes-i+1
317
END DO
318
319
PermLocal = Perm
320
Perm = 0
321
DO i=1,SIZE(Perm)
322
k = PermLocal(i)
323
IF (k>0) Perm(i) = DoneIndex(k)
324
END DO
325
DEALLOCATE( DoneIndex )
326
327
HalfBandWidthAfter = ComputeBandwidth( LocalNodes, &
328
ListMatrix,Perm,InvInitialReorder )+1
329
330
CALL Info( 'OptimizeBandwidth','Optimized bandwidth for '&
331
//TRIM(Equation)//': '//I2S(HalfBandwidthAfter),Level=4)
332
333
HalfBandWidth = HalfBandWidthAfter
334
335
IF ( HalfBandWidthBefore < HalfBandWidth .AND. .NOT. UseOptimized ) THEN
336
CALL Info( 'OptimizeBandwidth',&
337
'Bandwidth optimization rejected, using original ordering.',Level=4 )
338
HalfBandWidth = HalfBandWidthBefore
339
Perm = PermLocal
340
END IF
341
CALL Info( 'OptimizeBandwidth',&
342
'---------------------------------------------------------',Level=6 )
343
344
DEALLOCATE( PermLocal,DoneAlready )
345
!-------------------------------------------------------------------------------
346
347
CONTAINS
348
349
!-------------------------------------------------------------------------------
350
SUBROUTINE Renumber( Current )
351
!-------------------------------------------------------------------------------
352
TYPE(ListMatrixEntry_t), POINTER :: Current
353
!-------------------------------------------------------------------------------
354
INTEGER :: k
355
TYPE(ListMatrixEntry_t), POINTER :: p
356
!-------------------------------------------------------------------------------
357
p => Current
358
DO WHILE( ASSOCIATED(p) )
359
k = p % Index
360
IF ( k <= LocalNodes ) THEN
361
IF ( DoneIndex(k) == 0 ) THEN
362
PermLocal(Indx) = k
363
DoneIndex(k) = Indx
364
Indx = Indx + 1
365
END IF
366
END IF
367
p => p % Next
368
END DO
369
!-------------------------------------------------------------------------------
370
END SUBROUTINE Renumber
371
!-------------------------------------------------------------------------------
372
373
!-------------------------------------------------------------------------------
374
SUBROUTINE Levelize(nin,Levelin)
375
!-------------------------------------------------------------------------------
376
INTEGER :: nin,Levelin
377
!-------------------------------------------------------------------------------
378
INTEGER :: j,k,n, Level
379
TYPE(ListMatrixEntry_t), POINTER :: p=>Null()
380
381
TYPE Stack_t
382
TYPE(ListMatrixEntry_t), POINTER :: p
383
END TYPE Stack_t
384
385
INTEGER :: stackp
386
TYPE(Stack_t), POINTER CONTIG :: stack(:), copystack(:)
387
388
INTEGER :: istat
389
!-------------------------------------------------------------------------------
390
n = nin
391
Level=Levelin
392
393
ALLOCATE(stack(512),STAT=istat)
394
IF( istat /= 0 ) THEN
395
CALL Fatal('Levelize','Allocation error for stack of size 512')
396
END IF
397
398
stackp = 0
399
400
p=>ListMatrix(n) % Head
401
DO WHILE(ASSOCIATED(p))
402
IF ( stackp>=SIZE(stack) ) THEN
403
ALLOCATE( copystack(stackp*2) )
404
DO j=1,stackp
405
copystack(j) = stack(j)
406
END DO
407
DEALLOCATE(stack)
408
stack => copystack
409
END IF
410
stackp = stackp+1
411
stack(stackp) % p => p
412
413
ListMatrix(n) % Level = Level
414
DoneAlready(n) = .TRUE.
415
MaxLevel = MAX( MaxLevel,Level )
416
417
p => ListMatrix(n) % Head
418
419
DO WHILE(.TRUE.)
420
IF ( ASSOCIATED(p) ) THEN
421
n = p % Index
422
IF ( n <= LocalNodes ) THEN
423
IF ( .NOT.DoneAlready(n) ) THEN
424
Level = Level+1; EXIT
425
END IF
426
END IF
427
ELSE IF ( stackp>=1 ) THEN
428
p => stack(stackp) % p
429
Level = Level-1
430
Stackp = Stackp-1
431
ELSE
432
EXIT
433
END IF
434
p => p % Next
435
END DO
436
END DO
437
438
DEALLOCATE(Stack)
439
!-------------------------------------------------------------------------------
440
END SUBROUTINE Levelize
441
!-------------------------------------------------------------------------------
442
443
444
!-------------------------------------------------------------------------------
445
END FUNCTION OptimizeBandwidth
446
!-------------------------------------------------------------------------------
447
448
END MODULE BandwidthOptimize
449
450
!> \{ ElmerLib
451
452