Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/src/IterSolve.F90
5213 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: 08 Jun 1997
34
! *
35
! ****************************************************************************/
36
37
#include "huti_fdefs.h"
38
39
!> \ingroup ElmerLib
40
!> \{
41
42
43
44
45
!------------------------------------------------------------------------------
46
!> Module containing control of the iterative solvers for linear systems
47
!> that come with the Elmer suite.
48
!------------------------------------------------------------------------------
49
MODULE IterSolve
50
51
USE Lists
52
USE BandMatrix
53
USE IterativeMethods
54
USE huti_sfe
55
56
IMPLICIT NONE
57
58
!/*
59
! * Iterative method selection
60
! */
61
INTEGER, PARAMETER, PRIVATE :: ITER_BiCGStab = 320
62
INTEGER, PARAMETER, PRIVATE :: ITER_TFQMR = 330
63
INTEGER, PARAMETER, PRIVATE :: ITER_CG = 340
64
INTEGER, PARAMETER, PRIVATE :: ITER_CGS = 350
65
INTEGER, PARAMETER, PRIVATE :: ITER_GMRES = 360
66
INTEGER, PARAMETER, PRIVATE :: ITER_BiCGStab2 = 370
67
INTEGER, PARAMETER, PRIVATE :: ITER_SGS = 380
68
INTEGER, PARAMETER, PRIVATE :: ITER_JACOBI = 390
69
INTEGER, PARAMETER, PRIVATE :: ITER_RICHARDSON = 391
70
INTEGER, PARAMETER, PRIVATE :: ITER_BICGSTABL = 400
71
INTEGER, PARAMETER, PRIVATE :: ITER_GCR = 410
72
INTEGER, PARAMETER, PRIVATE :: ITER_IDRS = 420
73
INTEGER, PARAMETER, PRIVATE :: ITER_MPRGP = 430
74
75
!/*
76
! * Preconditioning type code
77
! */
78
INTEGER, PARAMETER, PRIVATE :: PRECOND_NONE = 500
79
INTEGER, PARAMETER, PRIVATE :: PRECOND_DIAGONAL = 510
80
INTEGER, PARAMETER, PRIVATE :: PRECOND_ILUn = 520
81
INTEGER, PARAMETER, PRIVATE :: PRECOND_ILUT = 530
82
INTEGER, PARAMETER, PRIVATE :: PRECOND_MG = 540
83
INTEGER, PARAMETER, PRIVATE :: PRECOND_BILUn = 550
84
INTEGER, PARAMETER, PRIVATE :: PRECOND_Vanka = 560
85
INTEGER, PARAMETER, PRIVATE :: PRECOND_Circuit = 570
86
INTEGER, PARAMETER, PRIVATE :: PRECOND_Slave = 580
87
88
INTEGER, PARAMETER :: stack_max=64
89
INTEGER :: stack_pos=0
90
LOGICAL :: FirstCall(stack_max)
91
92
REAL(KIND=dp), POINTER :: fm_Diag(:), fm_G(:,:)
93
94
CONTAINS
95
96
97
#ifndef HUTI_MAXTOLERANCE
98
#define HUTI_MAXTOLERANCE dpar(2)
99
#endif
100
#ifndef HUTI_SGSPARAM
101
#define HUTI_SGSPARAM dpar(3)
102
#endif
103
#ifndef HUTI_PSEUDOCOMPLEX
104
#define HUTI_PSEUDOCOMPLEX ipar(7)
105
#endif
106
#ifndef HUTI_BICGSTABL_L
107
#define HUTI_BICGSTABL_L ipar(16)
108
#endif
109
#ifndef HUTI_DIVERGENCE
110
#define HUTI_DIVERGENCE 3
111
#endif
112
#ifndef HUTI_GCR_RESTART
113
#define HUTI_GCR_RESTART ipar(17)
114
#endif
115
#ifndef HUTI_IDRS_S
116
#define HUTI_IDRS_S ipar(18)
117
#endif
118
#ifndef HUTI_MPRGP_GAMMA
119
#define HUTI_MPRGP_GAMMA dpar(6)
120
#endif
121
#ifndef HUTI_MPRGP_TOLFACTOR
122
#define HUTI_MPRGP_TOLFACTOR dpar(7)
123
#endif
124
!#ifndef HUTI_MPRGP_BOUND
125
!#define HUTI_MPRGP_BOUND ipar(19)
126
!#endif
127
#ifndef HUTI_MPRGP_ADAPT
128
#define HUTI_MPRGP_ADAPT ipar(19)
129
#endif
130
131
!------------------------------------------------------------------------------
132
!> Dummy preconditioner, if linear system scaling is active this corresponds
133
!> to diagonal preconditioning.
134
!------------------------------------------------------------------------------
135
SUBROUTINE pcond_dummy(u,v,ipar )
136
!------------------------------------------------------------------------------
137
INTEGER :: ipar(*)
138
REAL(KIND=dp) :: u(HUTI_NDIM), v(HUTI_NDIM)
139
INTEGER :: i
140
!------------------------------------------------------------------------------
141
!$OMP PARALLEL DO
142
DO i=1,HUTI_NDIM
143
u(i) = v(i)
144
END DO
145
!$OMP END PARALLEL DO
146
!------------------------------------------------------------------------------
147
END SUBROUTINE pcond_dummy
148
!------------------------------------------------------------------------------
149
150
!------------------------------------------------------------------------------
151
!> Complex dummy preconditioner, if linear system scaling is active this corresponds
152
!> to diagonal preconditioning.
153
!------------------------------------------------------------------------------
154
SUBROUTINE pcond_dummy_cmplx(u,v,ipar )
155
!------------------------------------------------------------------------------
156
INTEGER :: ipar(*)
157
COMPLEX(KIND=dp) :: u(HUTI_NDIM), v(HUTI_NDIM)
158
!------------------------------------------------------------------------------
159
u = v
160
!------------------------------------------------------------------------------
161
END SUBROUTINE pcond_dummy_cmplx
162
!------------------------------------------------------------------------------
163
164
!------------------------------------------------------------------------------
165
SUBROUTINE fm_DiagPrec( u,v,ipar )
166
!------------------------------------------------------------------------------
167
IMPLICIT NONE
168
169
REAL(KIND=dp) :: u(*),v(*)
170
INTEGER :: ipar(*)
171
172
INTEGER :: n
173
174
n = HUTI_NDIM
175
u(1:n) = v(1:n)*fm_diag(1:n)
176
!------------------------------------------------------------------------------
177
END SUBROUTINE fm_DiagPrec
178
!------------------------------------------------------------------------------
179
180
181
!------------------------------------------------------------------------------
182
SUBROUTINE fm_MatVec( u,v,ipar )
183
!------------------------------------------------------------------------------
184
IMPLICIT NONE
185
186
INTEGER :: ipar(*)
187
REAL(KIND=dp) :: u(*),v(*), ct, rsum, cumt=0, s
188
189
INTEGER :: i,j,n
190
191
n = HUTI_NDIM
192
#if 1
193
! CALL DSYMV('U',n,1.0_dp,Jacobian,n,u,1,0.0_dp,v,1)
194
CALL DGEMV('N',n,n,1.0_dp,fm_G,n,u,1,0.0_dp,v,1)
195
#else
196
v(1:n) = 0
197
!$omp parallel do private(i,j,s) shared(n,u,v,fM_G)
198
DO i=1,n
199
s = 0._dp
200
DO j=1,n
201
s = s + fm_G(i,j) * u(j)
202
END DO
203
v(i) = s
204
END DO
205
!$omp end parallel do
206
#endif
207
!------------------------------------------------------------------------------
208
END SUBROUTINE fm_MatVec
209
!------------------------------------------------------------------------------
210
211
212
!------------------------------------------------------------------------------
213
!> Create mask for skipping edges on a given boundary.
214
!------------------------------------------------------------------------------
215
SUBROUTINE CreateEdgeSkipMask(SkipMask)
216
217
LOGICAL, POINTER :: SkipMask(:)
218
INTEGER :: t,n0,e0,t0,bc_id,i,j
219
LOGICAL :: Found, Piola
220
TYPE(ValueList_t), POINTER :: BC
221
TYPE(Element_t), POINTER :: Element
222
TYPE(Mesh_t), POINTER :: Mesh
223
TYPE(Variable_t), POINTER :: pVar
224
225
Mesh => CurrentModel % Mesh
226
227
NULLIFY(pVar)
228
DO t=1,CurrentModel % NumberOfSolvers
229
IF(ListGetLogical(CurrentModel % Solvers(t) % Values,'Edge Basis',Found ) ) THEN
230
pVar => CurrentModel % Solvers(t) % Variable
231
EXIT
232
END IF
233
END DO
234
IF(.NOT. ASSOCIATED(pVar)) THEN
235
CALL Fatal('CreateEdgeSkipMask','Could not find "Edge Basis" defined in any Solver!')
236
END IF
237
238
n0 = Mesh % NumberOfNodes
239
t0 = Mesh % NumberOfBulkElements
240
e0 = Mesh % NumberOfEdges
241
242
Piola = ListGetLogicalAnySolver( CurrentModel,'Use Piola Transform' )
243
244
SkipMask = .FALSE.
245
246
DO t=t0+1,t0+Mesh % NumberOfBoundaryElements
247
Element => Mesh % Elements(t)
248
249
IF(.NOT. ASSOCIATED( Element % BoundaryInfo ) ) CYCLE
250
DO bc_id=1,CurrentModel % NumberOfBCs
251
IF ( Element % BoundaryInfo % Constraint == CurrentModel % BCs(bc_id) % Tag ) EXIT
252
END DO
253
IF ( bc_id > CurrentModel % NumberOfBCs ) CYCLE
254
BC => CurrentModel % BCs(bc_id) % Values
255
256
IF(ListGetLogical(BC,'Edge Skip Mask',Found ) ) THEN
257
SkipMask(pVar % Perm(n0+Element % EdgeIndexes)) = .TRUE.
258
END IF
259
END DO
260
261
n0 = COUNT(SkipMask)
262
CALL Info('CreateEdgeSkipMask','Mask include edges on BC: '//I2S(n0)//' (out of '//I2S(e0)//')',Level=7)
263
264
265
! It is not self-evident that we should include the additional Piola nodes
266
! in the set of nodes to be skipped in smoothing / krylov iteration.
267
! Numerical evidence seems to suggest that this is a good idea.
268
IF(Piola) THEN
269
270
IF(SIZE(pVar % Perm) < n0+e0+2*Mesh % NumberOfFaces) THEN
271
CALL Fatal('CreateEdgeSkipMask','Size of Perm too small for Piola!')
272
END IF
273
274
DO t=1, Mesh % NumberOfFaces
275
Element => Mesh % Faces(t)
276
277
! Only for quads do we have the extra dofs related to Piola transformed edge elements.
278
IF(Element % TYPE % ElementCode / 100 == 4 ) THEN
279
IF(ALL(SkipMask(pVar % Perm(n0+Element % EdgeIndexes)))) THEN
280
DO i=0,1
281
j = pVar % Perm(n0+e0+2*t-i)
282
IF(j>0) SkipMask(j) = .TRUE.
283
END DO
284
END IF
285
END IF
286
END DO
287
288
n0 = COUNT(SkipMask)
289
CALL Info('CreateEdgeSkipMask','Mask include total dofs on BC: '//I2S(n0), Level=7)
290
END IF
291
292
293
END SUBROUTINE CreateEdgeSkipMask
294
295
296
!------------------------------------------------------------------------------
297
!> Create mask for skipping nodes on a given boundary.
298
!------------------------------------------------------------------------------
299
SUBROUTINE CreateNodeSkipMask(SkipMask, pVar )
300
301
LOGICAL, POINTER :: SkipMask(:)
302
TYPE(Variable_t), POINTER :: pVar
303
304
INTEGER :: t,n0,e0,t0,bc_id
305
LOGICAL :: Found
306
TYPE(ValueList_t), POINTER :: BC
307
TYPE(Element_t), POINTER :: Element
308
TYPE(Mesh_t), POINTER :: Mesh
309
310
IF(.NOT. ListGetLogicalAnyBC(CurrentModel,'Edge Skip Mask' ) ) RETURN
311
312
Mesh => CurrentModel % Mesh
313
t0 = Mesh % NumberOfBulkElements
314
SkipMask = .FALSE.
315
316
DO t=t0+1,t0+Mesh % NumberOfBoundaryElements
317
Element => Mesh % Elements(t)
318
319
IF(.NOT. ASSOCIATED( Element % BoundaryInfo ) ) CYCLE
320
DO bc_id=1,CurrentModel % NumberOfBCs
321
IF ( Element % BoundaryInfo % Constraint == CurrentModel % BCs(bc_id) % Tag ) EXIT
322
END DO
323
IF ( bc_id > CurrentModel % NumberOfBCs ) CYCLE
324
BC => CurrentModel % BCs(bc_id) % Values
325
326
IF(ListGetLogical(BC,'Edge Skip Mask',Found ) ) THEN
327
WHERE(pVar % Perm(Element % NodeIndexes) > 0)
328
SkipMask(pVar % Perm(Element % NodeIndexes)) = .TRUE.
329
END WHERE
330
END IF
331
END DO
332
333
n0 = COUNT(SkipMask)
334
CALL Info('CreateNodeSkipMask','Created mask for skipping nodes: '//I2S(n0),Level=7)
335
336
END SUBROUTINE CreateNodeSkipMask
337
338
339
340
!> Computed masked dot product.
341
!----------------------------------------------------------------------
342
FUNCTION MaskedDotProd( ndim, x, xind, y, yind ) RESULT(dres)
343
!----------------------------------------------------------------------
344
IMPLICIT NONE
345
346
! Parameters
347
INTEGER :: ndim, xind, yind
348
REAL(KIND=dp) :: x(*)
349
REAL(KIND=dp) :: y(*)
350
REAL(KIND=dp) :: dres
351
352
! Local variables
353
REAL(KIND=dp) :: s
354
INTEGER :: i
355
356
LOGICAL, POINTER, SAVE :: SkipMask(:) => NULL()
357
358
IF(.NOT. ASSOCIATED(SkipMask)) THEN
359
ALLOCATE(SkipMask(ndim))
360
CALL CreateEdgeSkipMask(SkipMask)
361
END IF
362
363
dres = 0
364
!$OMP PARALLEL DO REDUCTION(+:dres)
365
DO i = 1, ndim
366
IF(SkipMask(i)) CYCLE
367
dres = dres + y(i) * x(i)
368
END DO
369
!$OMP END PARALLEL DO
370
!!!CALL SParActiveSUM(dres,0)
371
372
!----------------------------------------------------------------------
373
END FUNCTION MaskedDotProd
374
!----------------------------------------------------------------------
375
376
377
!> Compute global 2-norm of vector x
378
!----------------------------------------------------------------------
379
FUNCTION MaskedNorm( ndim, x, xind ) RESULT(dres)
380
!----------------------------------------------------------------------
381
IMPLICIT NONE
382
383
! Parameters
384
385
INTEGER :: ndim, xind
386
REAL(KIND=dp) :: x(*)
387
REAL(KIND=dp) :: dres
388
389
! Local variables
390
INTEGER :: i
391
LOGICAL, POINTER, SAVE :: SkipMask(:) => NULL()
392
393
IF(.NOT. ASSOCIATED(SkipMask)) THEN
394
ALLOCATE(SkipMask(ndim))
395
CALL CreateEdgeSkipMask(SkipMask)
396
END IF
397
398
dres = 0
399
!$OMP PARALLEL DO REDUCTION(+:dres)
400
DO i = 1, ndim
401
IF(SkipMask(i)) CYCLE
402
dres = dres + x(i)*x(i)
403
END DO
404
!$OMP END PARALLEL DO
405
!!!CALL SParActiveSUM(dres,0)
406
dres = SQRT(dres)
407
408
!----------------------------------------------------------------------
409
END FUNCTION MaskedNorm
410
!----------------------------------------------------------------------
411
412
413
!----------------------------------------------------------------------
414
FUNCTION Otmp_ddot( ndim, x, xind, y, yind ) RESULT(dres)
415
!----------------------------------------------------------------------
416
IMPLICIT NONE
417
418
! Parameters
419
INTEGER :: ndim, xind, yind
420
REAL(KIND=dp) :: x(*)
421
REAL(KIND=dp) :: y(*)
422
REAL(KIND=dp) :: dres
423
424
INTEGER :: i
425
426
IF( xind/=1 .OR. yind /=1 ) THEN
427
dres = ddot(ndim,x,xind,y,yind)
428
RETURN
429
END IF
430
431
dres = 0
432
!$OMP PARALLEL do shared(x,y) reduction(+:dres)
433
DO i=1,ndim
434
dres = dres + x(i) * y(i)
435
END DO
436
!$OMP END PARALLEL DO
437
438
!----------------------------------------------------------------------
439
END FUNCTION Otmp_ddot
440
!----------------------------------------------------------------------
441
442
443
!----------------------------------------------------------------------
444
FUNCTION Otmp_zdotc( ndim, x, xind, y, yind ) RESULT(zres)
445
!----------------------------------------------------------------------
446
IMPLICIT NONE
447
448
! Parameters
449
INTEGER :: ndim, xind, yind
450
COMPLEX(KIND=dp) :: x(*)
451
COMPLEX(KIND=dp) :: y(*)
452
COMPLEX(KIND=dp) :: zres
453
454
INTEGER :: i
455
456
IF( xind/=1 .OR. yind /=1 ) THEN
457
zres = zdotc(ndim,x,xind,y,yind)
458
RETURN
459
END IF
460
461
zres = 0
462
!$OMP PARALLEL do shared(x,y) reduction(+:zres)
463
DO i=1,ndim
464
zres = zres + DCONJG(x(i)) * y(i)
465
END DO
466
!$OMP END PARALLEL DO
467
468
!----------------------------------------------------------------------
469
END FUNCTION Otmp_zdotc
470
!----------------------------------------------------------------------
471
472
473
!------------------------------------------------------------------------------
474
!> The routine that decides which linear system solver to call, and calls it.
475
!> There are two main sources of iterations within Elmer.
476
!> 1) The old HUTiter library that includes the most classic iterative Krylov
477
!> methods.
478
!> 2) The internal MODULE IterativeMethods that includes some classic iterative
479
!> methods and also some more recent Krylov methods.
480
!------------------------------------------------------------------------------
481
RECURSIVE SUBROUTINE IterSolver( A,x,b,Solver,ndim,DotF, &
482
NormF,MatvecF,PrecF,StopcF )
483
!------------------------------------------------------------------------------
484
USE huti_sfe
485
USE ListMatrix
486
USE SParIterGlobals
487
IMPLICIT NONE
488
489
!------------------------------------------------------------------------------
490
TYPE(Solver_t) :: Solver
491
REAL(KIND=dp), DIMENSION(:), TARGET CONTIG :: x,b
492
TYPE(Matrix_t), TARGET :: A
493
INTEGER, OPTIONAL :: ndim
494
INTEGER(KIND=AddrInt), OPTIONAL :: DotF, NormF, MatVecF, PrecF, StopcF
495
!------------------------------------------------------------------------------
496
TYPE(Matrix_t), POINTER :: Adiag,CM,PrecMat,SaveGlobalM
497
498
REAL(KIND=dp) :: dpar(HUTI_DPAR_DFLTSIZE),stopfun
499
! external stopfun
500
REAL(KIND=dp), ALLOCATABLE :: work(:,:)
501
INTEGER :: i,j,k,N,ipar(HUTI_IPAR_DFLTSIZE),wsize,istat,IterType,PCondType,ILUn,Blocks
502
LOGICAL :: Internal, NullEdges
503
LOGICAL :: ComponentwiseStopC, NormwiseStopC, RowEquilibration
504
LOGICAL :: Condition,GotIt, Refactorize,Found,GotDiagFactor,Robust
505
LOGICAL :: ComplexSystem, PseudoComplexSystem, DoFatal, LeftOriented
506
507
REAL(KIND=dp) :: ILUT_TOL, DiagFactor
508
509
TYPE(ValueList_t), POINTER :: Params
510
511
CHARACTER(:), ALLOCATABLE :: str
512
513
EXTERNAL MultigridPrec
514
EXTERNAL NormwiseBackwardError, ComponentwiseBackwardError
515
EXTERNAL NormwiseBackwardErrorGeneralized
516
EXTERNAL NormwiseBackwardError_Z
517
518
INTEGER(KIND=Addrint) :: dotProc, normProc, pcondProc, &
519
pconddProc, mvProc, iterProc, StopcProc
520
INTEGER(KIND=Addrint) :: AddrFunc
521
INTEGER :: astat
522
COMPLEX(KIND=dp), ALLOCATABLE :: xC(:), bC(:)
523
COMPLEX(KIND=dp), ALLOCATABLE :: workC(:,:)
524
EXTERNAL :: AddrFunc
525
526
INTERFACE
527
SUBROUTINE VankaCreate(A,Solver)
528
USE Types
529
TYPE(Matrix_t) :: A
530
TYPE(Solver_t) :: Solver
531
END SUBROUTINE VankaCreate
532
533
SUBROUTINE VankaPrec(u,v,ipar)
534
USE Types
535
INTEGER :: ipar(*)
536
REAL(KIND=dp) :: u(*),v(*)
537
END SUBROUTINE VankaPrec
538
539
SUBROUTINE CircuitPrec(u,v,ipar)
540
USE Types
541
INTEGER :: ipar(*)
542
REAL(KIND=dp) :: u(*),v(*)
543
END SUBROUTINE CircuitPrec
544
545
SUBROUTINE CircuitPrecComplex(u,v,ipar)
546
USE Types
547
INTEGER :: ipar(*)
548
COMPLEX(KIND=dp) :: u(*),v(*)
549
END SUBROUTINE CircuitPrecComplex
550
551
SUBROUTINE SlavePrec(u,v,ipar)
552
USE Types
553
INTEGER :: ipar(*)
554
REAL(KIND=dp) :: u(*),v(*)
555
END SUBROUTINE SlavePrec
556
557
SUBROUTINE SlavePrecComplex(u,v,ipar)
558
USE Types
559
INTEGER :: ipar(*)
560
COMPLEX(KIND=dp) :: u(*),v(*)
561
END SUBROUTINE SlavePrecComplex
562
END INTERFACE
563
!------------------------------------------------------------------------------
564
N = A % NumberOfRows
565
IF ( PRESENT(ndim) ) n=ndim
566
567
ipar = 0
568
dpar = 0.0D0
569
pconddProc = 0
570
!------------------------------------------------------------------------------
571
Params => Solver % Values
572
str = ListGetString( Params,'Linear System Iterative Method',Found )
573
IF( .NOT. Found ) THEN
574
CALL Warn('IterSolver','> Linear System Iterative Method < not found, using BiCGstab')
575
str = 'bicgstab'
576
ELSE
577
CALL Info('IterSolver','Using iterative method: '//TRIM(str),Level=9)
578
END IF
579
580
IF( ListGetLogical( Params,'Linear System Skip Complex',GotIt ) ) THEN
581
CALL Info('IterSolver','This time skipping complex treatment',Level=20)
582
A % COMPLEX = .FALSE.
583
ComplexSystem = .FALSE.
584
ELSE
585
ComplexSystem = ListGetLogical( Params,'Linear System Complex',Found )
586
IF( .NOT. Found ) ComplexSystem = A % COMPLEX
587
END IF
588
589
PseudoComplexSystem = ListGetLogical( Params,'Linear System Pseudo Complex',Found )
590
591
IF( ComplexSystem ) THEN
592
CALL Info('IterSolver','Matrix is complex valued',Level=10)
593
ELSE IF( PseudoComplexSystem ) THEN
594
CALL Info('IterSolver','Matrix is pseudo complex valued',Level=10)
595
ELSE
596
CALL Info('IterSolver','Matrix is real valued',Level=12)
597
END IF
598
599
600
SELECT CASE(str)
601
CASE('bicgstab2')
602
! NOTE:
603
! BiCGStab2 should be nearly the same as BiCGStabl with the parameter l=2, but
604
! the implementation of BiCGStabl uses the right-oriented preconditioning, while
605
! BiCGStab2 works as expected only with the left-oriented preconditioning. Due to
606
! the difference in the preconditioning the convergence histories may be quite different.
607
! The complex BiCGStab2 does not convince, use BiCGStabl instead:
608
IF (ComplexSystem ) THEN
609
IterType = ITER_BICGstabl
610
ELSE
611
IterType = ITER_BiCGStab2
612
END IF
613
CASE('bicgstabl')
614
IterType = ITER_BICGstabl
615
CASE('bicgstab')
616
IterType = ITER_BiCGStab
617
CASE('tfqmr')
618
IterType = ITER_TFQMR
619
CASE('cgs')
620
IterType = ITER_CGS
621
CASE('cg')
622
IterType = ITER_CG
623
CASE('gmres')
624
IterType = ITER_GMRES
625
CASE('sgs')
626
IterType = ITER_SGS
627
CASE('jacobi')
628
IterType = ITER_jacobi
629
CASE('richardson')
630
IterType = ITER_richardson
631
CASE('gcr')
632
IterType = ITER_GCR
633
CASE('idrs')
634
IterType = ITER_IDRS
635
CASE DEFAULT
636
IterType = ITER_BiCGStab
637
CASE('mprgp')
638
IterType = ITER_MPRGP
639
END SELECT
640
641
!------------------------------------------------------------------------------
642
643
HUTI_WRKDIM = 0
644
HUTI_PSEUDOCOMPLEX = 0
645
IF( PseudoComplexSystem ) THEN
646
HUTI_PSEUDOCOMPLEX = 1
647
IF ( ListGetLogical( Params,'Block Split Complex',Found ) ) HUTI_PSEUDOCOMPLEX = 2
648
END IF
649
Internal = .FALSE.
650
651
SELECT CASE ( IterType )
652
653
! Solvers from HUTiter
654
!-------------------------------------------------------
655
CASE (ITER_BiCGStab)
656
HUTI_WRKDIM = HUTI_BICGSTAB_WORKSIZE
657
658
CASE (ITER_BiCGStab2)
659
HUTI_WRKDIM = HUTI_BICGSTAB_2_WORKSIZE
660
661
CASE (ITER_TFQMR)
662
HUTI_WRKDIM = HUTI_TFQMR_WORKSIZE
663
664
CASE (ITER_CG)
665
HUTI_WRKDIM = HUTI_CG_WORKSIZE
666
667
CASE (ITER_CGS)
668
HUTI_WRKDIM = HUTI_CGS_WORKSIZE
669
670
CASE (ITER_GMRES)
671
HUTI_GMRES_RESTART = ListGetInteger( Params,&
672
'Linear System GMRES Restart', GotIt )
673
IF ( .NOT. GotIT ) HUTI_GMRES_RESTART = 10
674
HUTI_WRKDIM = HUTI_GMRES_WORKSIZE + HUTI_GMRES_RESTART
675
676
! Solvers from IterativeMethods.src
677
!-------------------------------------------------------
678
CASE (ITER_SGS)
679
HUTI_WRKDIM = 1
680
HUTI_SGSPARAM = ListGetConstReal( Params,'SGS Overrelaxation Factor',&
681
GotIt,minv=0.0_dp,maxv=2.0_dp)
682
IF(.NOT. GotIt) HUTI_SGSPARAM = 1.8
683
Internal = .TRUE.
684
685
CASE (ITER_Jacobi, ITER_Richardson)
686
HUTI_WRKDIM = 1
687
Internal = .TRUE.
688
689
CASE (ITER_GCR)
690
HUTI_WRKDIM = 1
691
HUTI_GCR_RESTART = ListGetInteger( Params, &
692
'Linear System GCR Restart', GotIt )
693
IF ( .NOT. GotIt ) THEN
694
i = ListGetInteger( Params,'Linear System Max Iterations', minv=1 )
695
IF( i > 200 ) THEN
696
i = 200
697
CALL Info('IterSolver','"Linear System GCR Restart" not given, setting it to '//I2S(i),Level=4)
698
END IF
699
HUTI_GCR_RESTART = i
700
END IF
701
Internal = .TRUE.
702
703
CASE (ITER_BICGSTABL)
704
HUTI_WRKDIM = 1
705
HUTI_BICGSTABL_L = ListGetInteger( Params,'BiCGstabl polynomial degree',&
706
GotIt,minv=2)
707
IF(.NOT. GotIt) HUTI_BICGSTABL_L = 2
708
Internal = .TRUE.
709
710
CASE (ITER_IDRS)
711
HUTI_WRKDIM = 1
712
HUTI_IDRS_S = ListGetInteger( Params,'IDRS parameter',GotIt,minv=1)
713
IF(.NOT. GotIt) HUTI_IDRS_S = 4
714
Internal = .TRUE.
715
716
CASE (ITER_MPRGP)
717
HUTI_WRKDIM = 1
718
Internal = .TRUE.
719
HUTI_MPRGP_GAMMA = ListGetConstReal( Params, 'Linear System MPRGP Gamma', GotIt )
720
IF(.NOT. GotIt) HUTI_MPRGP_GAMMA = 1.0_dp
721
HUTI_MPRGP_TOLFACTOR = ListGetConstReal( Params, 'Linear System MPRGP TolFactor', GotIt )
722
IF(.NOT. GotIt) HUTI_MPRGP_TOLFACTOR = 5.0_dp
723
!HUTI_MPRGP_BOUND = ListGetString( Params, 'Linear System MPRGP Bound Type', GotIt )
724
!IF(.NOT. GotIt) HUTI_MPRGP_BOUND = 'lower' ! TODO: should write error if no bounds
725
HUTI_MPRGP_ADAPT = 1
726
IF( ListGetLogical( Params, 'Linear System MPRGP Adaptive', GotIt ) ) THEN
727
HUTI_MPRGP_ADAPT = 1
728
ELSE
729
IF(GotIt) HUTI_MPRGP_ADAPT = 0
730
END IF
731
732
END SELECT
733
!------------------------------------------------------------------------------
734
735
wsize = HUTI_WRKDIM
736
737
StopcProc = 0
738
IF (PRESENT(StopcF)) THEN
739
StopcProc = StopcF
740
HUTI_STOPC = HUTI_USUPPLIED_STOPC
741
ELSE
742
ComponentwiseStopC = ListGetLogical(Params,'Linear System Componentwise Backward Error',GotIt)
743
IF (ComponentwiseStopC) THEN
744
IF (ComplexSystem) THEN
745
CALL Info('IterSolver', 'Linear System Componentwise Backward Error is active')
746
CALL Fatal('IterSolver', 'Error computation does not support Linear System Complex = True')
747
END IF
748
StopcProc = AddrFunc(ComponentwiseBackwardError)
749
HUTI_STOPC = HUTI_USUPPLIED_STOPC
750
ELSE
751
NormwiseStopC = ListGetLogical(Params,'Linear System Normwise Backward Error',GotIt)
752
IF (NormwiseStopC) THEN
753
RowEquilibration = ListGetLogical(Params,'Linear System Row Equilibration',GotIt)
754
IF (RowEquilibration) THEN
755
IF (ComplexSystem) THEN
756
StopcProc = AddrFunc(NormwiseBackwardError_Z)
757
ELSE
758
StopcProc = AddrFunc(NormwiseBackwardError)
759
END IF
760
ELSE
761
IF (ComplexSystem) THEN
762
CALL Info('IterSolver', 'Linear System Normwise Backward Error is active')
763
CALL Fatal('IterSolver', 'Error computation needs Linear System Row Equilibration = True')
764
ELSE
765
StopcProc = AddrFunc(NormwiseBackwardErrorGeneralized)
766
END IF
767
END IF
768
HUTI_STOPC = HUTI_USUPPLIED_STOPC
769
ELSE
770
HUTI_STOPC = HUTI_TRESID_SCALED_BYB
771
END IF
772
END IF
773
END IF
774
HUTI_NDIM = N
775
776
HUTI_DBUGLVL = ListGetInteger( Params, &
777
'Linear System Residual Output', GotIt )
778
IF ( .NOT.Gotit ) HUTI_DBUGLVL = 1
779
780
IF ( Parenv % myPE /= 0 ) HUTI_DBUGLVL=0
781
782
HUTI_MAXIT = ListGetInteger( Params, &
783
'Linear System Max Iterations', minv=1 )
784
785
HUTI_MINIT = ListGetInteger( Params, &
786
'Linear System Min Iterations', GotIt )
787
788
IF( ComplexSystem ) THEN
789
ALLOCATE(workC(N/2,wsize), stat=istat)
790
IF ( istat /= 0 ) THEN
791
CALL Fatal( 'IterSolve', 'Memory allocation failure.' )
792
END IF
793
workC = cmplx(0,0,dp)
794
ELSE
795
ALLOCATE(work(N,wsize), stat=istat)
796
IF ( istat /= 0 ) THEN
797
CALL Fatal( 'IterSolve', 'Memory allocation failure.' )
798
END IF
799
!$OMP PARALLEL PRIVATE(j)
800
DO j=1,wsize
801
!$OMP DO
802
DO i=1,N
803
work(i,j) = real(0,dp)
804
END DO
805
!$OMP END DO
806
END DO
807
!$OMP END PARALLEL
808
END IF
809
810
IF ( (IterType == ITER_BiCGStab2 .OR. IterType == ITER_BiCGStabL .OR. &
811
IterType == ITER_BiCGStab ) .AND. ALL(x == 0.0) ) x = 1.0d-8
812
813
HUTI_INITIALX = HUTI_USERSUPPLIEDX
814
815
HUTI_TOLERANCE = ListGetCReal( Params, &
816
'Linear System Convergence Tolerance' )
817
818
HUTI_MAXTOLERANCE = ListGetCReal( Params, &
819
'Linear System Divergence Limit', GotIt)
820
IF(.NOT. GotIt) HUTI_MAXTOLERANCE = 1.0d20
821
822
IF( ListGetLogical( Params,'Linear System Robust',GotIt) ) THEN
823
HUTI_ROBUST = 1
824
HUTI_ROBUST_TOLERANCE = ListGetCReal( Params,'Linear System Robust Tolerance',GotIt)
825
IF(.NOT. GotIt ) HUTI_ROBUST_TOLERANCE = HUTI_TOLERANCE**(2.0/3.0)
826
HUTI_ROBUST_MAXTOLERANCE = ListGetCReal( Params,'Linear System Robust Limit',GotIt)
827
IF(.NOT. GotIt ) HUTI_ROBUST_MAXTOLERANCE = SQRT( HUTI_TOLERANCE )
828
HUTI_ROBUST_STEPSIZE = ListGetCReal( Params,'Linear System Robust Margin',GotIt)
829
IF(.NOT. GotIt ) HUTI_ROBUST_STEPSIZE = 1.1_dp
830
HUTI_ROBUST_MAXBADIT = ListGetInteger( Params,'Linear System Robust Max Iterations',GotIt)
831
IF(.NOT. GotIt ) HUTI_ROBUST_MAXBADIT = HUTI_MAXIT / 2
832
HUTI_ROBUST_START = ListGetInteger( Params,'Linear System Robust Start Iteration',GotIt)
833
IF(.NOT. GotIt ) HUTI_ROBUST_START = 1
834
ELSE
835
HUTI_ROBUST = 0
836
END IF
837
838
839
IF( ListGetLogical( Params,'IDRS Smoothing',GotIt) ) THEN
840
HUTI_SMOOTHING = 1
841
ELSE
842
HUTI_SMOOTHING = 0
843
END IF
844
845
846
!------------------------------------------------------------------------------
847
848
! By default the right-oriented preconditioning is applied, but BiCGStab2,
849
! GMRES and TFQMR are called with the left-oriented preconditining since
850
! the right-oriented preconditioning does not work as expected. The methods
851
! from the module IterativeMethods use always the right-oriented preconditioning:
852
!
853
SELECT CASE ( IterType )
854
CASE (ITER_BiCGStab2, ITER_GMRES, ITER_TFQMR)
855
LeftOriented = .TRUE.
856
CASE DEFAULT
857
LeftOriented = ListGetLogical(Params, 'Linear System Left Preconditioning', GotIt)
858
IF (Internal) LeftOriented = .FALSE.
859
END SELECT
860
861
862
IF ( .NOT. PRESENT(PrecF) ) THEN
863
str = ListGetString( Params, 'Linear System Preconditioning',gotit )
864
IF ( .NOT.gotit ) str = 'none'
865
866
A % Cholesky = ListGetLogical( Params,'Linear System Symmetric ILU', Gotit )
867
868
ILUn = -1
869
IF ( str == 'none' ) THEN
870
PCondType = PRECOND_NONE
871
872
ELSE IF ( str == 'diagonal' ) THEN
873
PCondType = PRECOND_DIAGONAL
874
875
ELSE IF ( str == 'ilut' ) THEN
876
ILUT_TOL = ListGetCReal( Params, &
877
'Linear System ILUT Tolerance',GotIt )
878
PCondType = PRECOND_ILUT
879
880
ELSE IF ( SEQL(str, 'ilu') ) THEN
881
ILUn = ListGetInteger( Params, &
882
'Linear System ILU Order', gotit )
883
IF ( .NOT.gotit ) THEN
884
IF(LEN(str)>=4) ILUn = ICHAR(str(4:4)) - ICHAR('0')
885
END IF
886
IF ( ILUn < 0 .OR. ILUn > 9 ) ILUn = 0
887
PCondType = PRECOND_ILUn
888
889
ELSE IF ( SEQL(str, 'bilu') ) THEN
890
ILUn = 0
891
IF(LEN(str)>=5) ILUn = ICHAR(str(5:5)) - ICHAR('0')
892
IF ( ILUn < 0 .OR. ILUn > 9 ) ILUn = 0
893
IF( Solver % Variable % Dofs == 1) THEN
894
CALL Warn('IterSolver','BILU for one dofs is equal to ILU!')
895
PCondType = PRECOND_ILUn
896
ELSE
897
PCondType = PRECOND_BILUn
898
END IF
899
900
ELSE IF ( str == 'multigrid' ) THEN
901
PCondType = PRECOND_MG
902
903
ELSE IF ( SEQL(str,'vanka') ) THEN
904
PCondType = PRECOND_VANKA
905
906
ELSE IF ( str == 'auxiliary space solver' .OR. str == 'slave' ) THEN
907
PCondType = PRECOND_SLAVE
908
909
ELSE IF ( str == 'circuit' ) THEN
910
ILUn = ListGetInteger( Params, 'Linear System ILU Order', gotit )
911
IF(.NOT.Gotit ) ILUn=-1
912
PCondType = PRECOND_Circuit
913
914
ELSE
915
PCondType = PRECOND_NONE
916
CALL Warn( 'IterSolve', 'Unknown preconditioner type: '//TRIM(str)//', feature disabled.' )
917
END IF
918
919
IF ( .NOT. ListGetLogical( Params, 'No Precondition Recompute',GotIt ) ) THEN
920
CALL ResetTimer("Prec-"//TRIM(str))
921
922
n = ListGetInteger( Params, 'Linear System Precondition Recompute', GotIt )
923
IF ( n <= 0 ) n = 1
924
925
Refactorize = ListGetLogical( Params, 'Linear System Refactorize', Gotit )
926
IF ( .NOT. Gotit ) Refactorize = .TRUE.
927
928
IF (.NOT.(ASSOCIATED(A % ILUValues).OR.ASSOCIATED(A % CILUValues)).OR. &
929
(Refactorize.AND.MOD(A % SolveCount, n)==0) ) THEN
930
931
932
IF ( A % FORMAT == MATRIX_CRS ) THEN
933
934
! Optionally one may emphasize the diagonal entries in the linear system
935
! to make the preconditioning more stable.
936
!-------------------------------------------------------------------------
937
DiagFactor = ListGetCReal( Params,'Linear System ILU Factor',GotIt )
938
GotDiagFactor = ( DiagFactor > EPSILON( DiagFactor ) )
939
IF( GotDiagFactor ) THEN
940
CALL Info('IterSolver','Applying diagonal relaxation for ILU', Level=8)
941
DiagFactor = DiagFactor + 1.0_dp
942
A % Values( A % Diag ) = DiagFactor * A % Values( A % Diag )
943
END IF
944
945
IF ( ComplexSystem ) THEN
946
IF ( PCondType == PRECOND_ILUn .OR. (PCondType==PRECOND_Circuit.AND.ILUn>=0) ) THEN
947
NullEdges = ListGetLogical(Params, 'Edge Basis', GotIt)
948
CM => A % ConstraintMatrix
949
IF(NullEdges.OR.ASSOCIATED(CM)) THEN
950
CALL Info('IterSolver','Omitting edge dofs from being target of ILUn',Level=20)
951
952
IF(ASSOCIATED(A % ILURows)) DEALLOCATE(A % ILURows)
953
IF(ASSOCIATED(A % ILUCols)) DEALLOCATE(A % ILUCols)
954
IF(ASSOCIATED(A % ILUDiag)) DEALLOCATE(A % ILUDiag)
955
IF(ASSOCIATED(A % CILUValues)) DEALLOCATE(A % CILUValues)
956
957
PrecMat => AllocateMatrix()
958
PrecMat % FORMAT = MATRIX_LIST
959
PrecMat % CIluValues => NULL()
960
961
IF(ASSOCIATED(CM)) THEN
962
DO i=CM % NumberOfRows,1,-1
963
k = i + A % NumberOfRows
964
CALL List_AddMatrixIndex( PrecMat % ListMatrix,k,k)
965
IF(MOD(k,2)==0) THEN
966
CALL List_AddMatrixIndex(PrecMat % ListMatrix, k, k-1)
967
ELSE
968
CALL List_AddMatrixIndex(PrecMat % ListMatrix, k, k+1)
969
END IF
970
971
DO j=CM % Rows(i+1)-1,CM % Rows(i),-1
972
CALL List_AddToMatrixElement( PrecMat % ListMatrix, &
973
i + A % NumberOfRows, CM % Cols(j), CM % Values(j))
974
975
CALL List_AddToMatrixElement( PrecMat % ListMatrix, &
976
CM % Cols(j), i + A % NumberOfRows, CM % Values(j))
977
END DO
978
END DO
979
END IF
980
981
k = A % NumberOfRows - A % ExtraDOFs
982
DO i=A % NumberOfRows,1,-1
983
IF(i>k) THEN
984
CALL List_AddMatrixIndex(PrecMat % ListMatrix, i, i)
985
IF(MOD(i,2)==0) THEN
986
CALL List_AddMatrixIndex(PrecMat % ListMatrix, i, i-1)
987
ELSE
988
CALL List_AddMatrixIndex(PrecMat % ListMatrix, i, i+1)
989
END IF
990
ELSE IF (NullEdges) THEN
991
CALL List_AddToMatrixElement(PrecMat % ListMatrix, i, i, 1._dp)
992
IF(MOD(i,2)==0) THEN
993
CALL List_AddMatrixIndex(PrecMat % ListMatrix, i, i-1)
994
ELSE
995
CALL List_AddMatrixIndex(PrecMat % ListMatrix, i, i+1)
996
END IF
997
END IF
998
999
DO j=A % Rows(i+1)-1,A % Rows(i),-1
1000
IF (i>k .OR. A % Cols(j)>k .OR. .NOT.NullEdges) THEN
1001
CALL List_AddToMatrixElement(PrecMat % ListMatrix, i, A % Cols(j), A % Values(j))
1002
END IF
1003
END DO
1004
END DO
1005
1006
CALL List_ToCRSMatrix(PrecMat)
1007
Condition = CRS_ComplexIncompleteLU(PrecMat,ILUn)
1008
1009
A % ILURows => PrecMat % IluRows
1010
A % ILUCols => PrecMat % IluCols
1011
A % ILUDiag => PrecMat % IluDiag
1012
A % CILUvalues => PrecMat % CIluValues
1013
1014
DEALLOCATE(PrecMat % Values)
1015
IF(.NOT.ASSOCIATED(A % ILURows,PrecMat % Rows)) DEALLOCATE(PrecMat % Rows)
1016
IF(.NOT.ASSOCIATED(A % ILUCols,PrecMat % Cols)) DEALLOCATE(PrecMat % Cols)
1017
IF(.NOT.ASSOCIATED(A % ILUDiag,PrecMat % Diag)) DEALLOCATE(PrecMat % Diag)
1018
DEALLOCATE(PrecMat)
1019
ELSE
1020
Condition = CRS_ComplexIncompleteLU(A,ILUn)
1021
END IF
1022
ELSE IF ( PCondType == PRECOND_ILUT ) THEN
1023
Condition = CRS_ComplexILUT( A,ILUT_TOL )
1024
END IF
1025
ELSE IF (ILUn>=0 .OR. PCondType == PRECOND_ILUT) THEN ! Not ComplexSystem
1026
SELECT CASE(PCondType)
1027
CASE(PRECOND_ILUn, PRECOND_Circuit)
1028
NullEdges = ListGetLogical(Params, 'Edge Basis', GotIt)
1029
CM => A % ConstraintMatrix
1030
IF(NullEdges.OR.ASSOCIATED(CM)) THEN
1031
1032
IF(ASSOCIATED(A % ILURows)) DEALLOCATE(A % ILURows)
1033
IF(ASSOCIATED(A % ILUCols)) DEALLOCATE(A % ILUCols)
1034
IF(ASSOCIATED(A % ILUDiag)) DEALLOCATE(A % ILUDiag)
1035
IF(ASSOCIATED(A % ILUValues)) DEALLOCATE(A % ILUValues)
1036
1037
PrecMat => AllocateMatrix()
1038
PrecMat % FORMAT = MATRIX_LIST
1039
1040
IF(ASSOCIATED(CM)) THEN
1041
DO i=CM % NumberOfRows,1,-1
1042
CALL List_AddMatrixIndex( PrecMat % ListMatrix, &
1043
i + A % NumberOfRows, i + A % NumberOFrows)
1044
1045
DO j=CM % Rows(i+1)-1,CM % Rows(i),-1
1046
CALL List_AddToMatrixElement( PrecMat % ListMatrix, &
1047
i + A % NumberOfRows, CM % Cols(j), CM % Values(j))
1048
1049
CALL List_AddToMatrixElement( PrecMat % ListMatrix, &
1050
CM % Cols(j), i + A % NumberOfRows, CM % Values(j))
1051
END DO
1052
END DO
1053
END IF
1054
1055
k = A % NumberOfRows - A % ExtraDOFs
1056
DO i=A % NumberOfRows,1,-1
1057
IF(i>k) THEN
1058
CALL List_AddMatrixIndex(PrecMat % ListMatrix, i, i)
1059
ELSE IF (NullEdges) THEN
1060
CALL List_AddToMatrixElement(PrecMat % ListMatrix, i, i, 1._dp)
1061
END IF
1062
1063
DO j=A % Rows(i+1)-1,A % Rows(i),-1
1064
IF (i>k .OR. A % Cols(j)>k .OR. .NOT.NullEdges) THEN
1065
CALL List_AddToMatrixElement(PrecMat % ListMatrix, i, A % Cols(j), A % Values(j))
1066
END IF
1067
END DO
1068
END DO
1069
1070
CALL List_ToCRSMatrix(PrecMat)
1071
Condition = CRS_IncompleteLU(PrecMat,ILUn,Params)
1072
1073
A % ILURows => PrecMat % IluRows
1074
A % ILUCols => PrecMat % IluCols
1075
A % ILUDiag => PrecMat % IluDiag
1076
A % ILUvalues => PrecMat % IluValues
1077
1078
DEALLOCATE(PrecMat % Values)
1079
IF(.NOT.ASSOCIATED(A % ILURows,PrecMat % Rows)) DEALLOCATE(PrecMat % Rows)
1080
IF(.NOT.ASSOCIATED(A % ILUCols,PrecMat % Cols)) DEALLOCATE(PrecMat % Cols)
1081
IF(.NOT.ASSOCIATED(A % ILUDiag,PrecMat % Diag)) DEALLOCATE(PrecMat % Diag)
1082
DEALLOCATE(PrecMat)
1083
ELSE
1084
Condition = CRS_IncompleteLU(A,ILUn,Params)
1085
END IF
1086
CASE(PRECOND_ILUT)
1087
Condition = CRS_ILUT( A,ILUT_TOL )
1088
CASE(PRECOND_BILUn)
1089
Blocks = Solver % Variable % Dofs
1090
IF ( Blocks <= 1 ) THEN
1091
Condition = CRS_IncompleteLU(A,ILUn,Params)
1092
ELSE
1093
IF( .NOT. ASSOCIATED( A % ILUValues ) ) THEN
1094
Adiag => AllocateMatrix()
1095
CALL CRS_BlockDiagonal(A,Adiag,Blocks)
1096
Condition = CRS_IncompleteLU(Adiag,ILUn,Params)
1097
A % ILURows => Adiag % ILURows
1098
A % ILUCols => Adiag % ILUCols
1099
A % ILUValues => Adiag % ILUValues
1100
A % ILUDiag => Adiag % ILUDiag
1101
IF (ILUn > 0) THEN
1102
DEALLOCATE(Adiag % Rows,Adiag % Cols, Adiag % Diag, Adiag % Values)
1103
END IF
1104
DEALLOCATE( Adiag )
1105
ELSE
1106
Condition = CRS_IncompleteLU(A,ILUn,Params)
1107
END IF
1108
END IF
1109
CASE(PRECOND_VANKA)
1110
! CALL VankaCreate( A, SolverParam )
1111
END SELECT
1112
END IF
1113
1114
IF( GotDiagFactor ) THEN
1115
CALL Info('IterSolver','Reverting diagonal relaxation for ILU', Level=10)
1116
A % Values( A % Diag ) = A % Values( A % Diag ) / DiagFactor
1117
END IF
1118
1119
ELSE
1120
IF ( PCondType == PRECOND_ILUn ) THEN
1121
CALL Warn( 'IterSolve', 'No ILU Preconditioner for Band Matrix format,' )
1122
CALL Warn( 'IterSolve', 'using Diagonal preconditioner instead...' )
1123
PCondType = PRECOND_DIAGONAL
1124
END IF
1125
END IF
1126
END IF
1127
CALL CheckTimer("Prec-"//TRIM(str),Level=8,Delete=.TRUE.)
1128
END IF
1129
END IF
1130
1131
A % SolveCount = A % SolveCount + 1
1132
!------------------------------------------------------------------------------
1133
1134
IF ( PRESENT(MatvecF) ) THEN
1135
mvProc = MatvecF
1136
ELSE
1137
IF ( .NOT. ComplexSystem ) THEN
1138
mvProc = AddrFunc( CRS_MatrixVectorProd )
1139
ELSE
1140
mvProc = AddrFunc( CRS_ComplexMatrixVectorProd )
1141
END IF
1142
END IF
1143
1144
IF ( PRESENT(dotF) ) THEN
1145
dotProc = dotF
1146
ELSE
1147
dotProc = 0
1148
END IF
1149
1150
IF ( PRESENT(normF) ) THEN
1151
normProc = normF
1152
ELSE
1153
normProc = 0
1154
END IF
1155
1156
1157
IF ( PRESENT(PrecF) ) THEN
1158
pcondProc = PrecF
1159
ELSE
1160
SELECT CASE( PCondType )
1161
CASE (PRECOND_NONE)
1162
IF ( .NOT. ComplexSystem ) THEN
1163
pcondProc = AddrFunc( pcond_dummy )
1164
ELSE
1165
pcondProc = AddrFunc( pcond_dummy_cmplx )
1166
END IF
1167
1168
CASE (PRECOND_DIAGONAL)
1169
IF ( .NOT. ComplexSystem ) THEN
1170
pcondProc = AddrFunc( CRS_DiagPrecondition )
1171
ELSE
1172
pcondProc = AddrFunc( CRS_ComplexDiagPrecondition )
1173
END IF
1174
1175
CASE (PRECOND_ILUn, PRECOND_ILUT, PRECOND_BILUn )
1176
IF ( .NOT. ComplexSystem ) THEN
1177
pcondProc = AddrFunc( CRS_LUPrecondition )
1178
ELSE
1179
pcondProc = AddrFunc( CRS_ComplexLUPrecondition )
1180
END IF
1181
1182
CASE (PRECOND_MG)
1183
pcondProc = AddrFunc( MultiGridPrec )
1184
1185
CASE (PRECOND_VANKA)
1186
pcondProc = AddrFunc( VankaPrec )
1187
1188
CASE (PRECOND_Slave)
1189
IF(ListGetLogical( Solver % Values,'Linear System Refactorize First',Found ) ) THEN
1190
CALL LIstAddLogical( Solver % Values,'Linear System Refactorize',.TRUE.)
1191
END IF
1192
IF ( .NOT. ComplexSystem ) THEN
1193
pcondProc = AddrFunc( SlavePrec )
1194
ELSE
1195
pcondProc = AddrFunc( SlavePrecComplex )
1196
END IF
1197
1198
CASE (PRECOND_Circuit)
1199
IF ( .NOT. ComplexSystem ) THEN
1200
pcondProc = AddrFunc( CircuitPrec )
1201
ELSE
1202
pcondProc = AddrFunc( CircuitPrecComplex )
1203
END IF
1204
1205
CASE DEFAULT
1206
pcondProc = 0
1207
END SELECT
1208
END IF
1209
1210
1211
IF ( .NOT. ComplexSystem ) THEN
1212
SELECT CASE ( IterType )
1213
1214
! Solvers from HUTiter library
1215
!-------------------------------------------------------
1216
CASE (ITER_BiCGStab)
1217
iterProc = AddrFunc( HUTI_D_BICGSTAB )
1218
CASE (ITER_BiCGStab2)
1219
iterProc = AddrFunc( HUTI_D_BICGSTAB_2 )
1220
CASE (ITER_TFQMR)
1221
iterProc = AddrFunc( HUTI_D_TFQMR )
1222
CASE (ITER_CG)
1223
iterProc = AddrFunc( HUTI_D_CG )
1224
CASE (ITER_CGS)
1225
iterProc = AddrFunc( HUTI_D_CGS )
1226
CASE (ITER_GMRES)
1227
iterProc = AddrFunc( HUTI_D_GMRES )
1228
1229
! Solvers from IterativeMethods.src
1230
!-------------------------------------------------------
1231
CASE (ITER_SGS)
1232
iterProc = AddrFunc( itermethod_sgs )
1233
CASE (ITER_JACOBI)
1234
iterProc = AddrFunc( itermethod_jacobi )
1235
CASE (ITER_RICHARDSON)
1236
iterProc = AddrFunc( itermethod_richardson )
1237
CASE (ITER_GCR)
1238
iterProc = AddrFunc( itermethod_gcr )
1239
CASE (ITER_BICGSTABL)
1240
iterProc = AddrFunc( itermethod_bicgstabl )
1241
CASE (ITER_IDRS)
1242
iterProc = AddrFunc( itermethod_idrs )
1243
CASE (ITER_MPRGP)
1244
iterProc = AddrFunc( itermethod_mprgp )
1245
1246
END SELECT
1247
1248
IF( Internal ) THEN
1249
IF( ListGetLogical( Params,'Linear System Skip Mask',Found ) ) THEN
1250
CALL Info('IterSolver','Using edge skip mask for linear system solver!')
1251
dotProc = AddrFunc(MaskedDotProd)
1252
normproc = AddrFunc(MaskedNorm)
1253
ELSE IF( PseudoComplexSystem ) THEN
1254
IF( HUTI_PSEUDOCOMPLEX == 1 ) THEN
1255
CALL Info('IterSolver','Setting dot product function to: PseudoZDotProd',Level=15)
1256
dotProc = AddrFunc( PseudoZDotProd )
1257
ELSE
1258
CALL Info('IterSolver','Setting dot product function to: PseudoZDotProd2',Level=15)
1259
dotProc = AddrFunc( PseudoZDotProd2 )
1260
END IF
1261
ELSE
1262
! IF ( dotProc == 0 ) dotProc = AddrFunc(ddot)
1263
END IF
1264
IF ( normProc == 0 ) normproc = AddrFunc(dnrm2)
1265
IF( HUTI_DBUGLVL == 0) HUTI_DBUGLVL = HUGE( HUTI_DBUGLVL )
1266
END IF
1267
1268
IF ( dotProc == 0 ) dotProc = AddrFunc(Otmp_ddot)
1269
1270
ELSE
1271
HUTI_NDIM = HUTI_NDIM / 2
1272
SELECT CASE ( IterType )
1273
1274
! Solvers from HUTiter library
1275
!-------------------------------------------------------
1276
CASE (ITER_BiCGStab)
1277
iterProc = AddrFunc( HUTI_Z_BICGSTAB )
1278
CASE (ITER_BiCGStab2)
1279
iterProc = AddrFunc( HUTI_Z_BICGSTAB_2 )
1280
CASE (ITER_TFQMR)
1281
iterProc = AddrFunc( HUTI_Z_TFQMR )
1282
CASE (ITER_CG)
1283
iterProc = AddrFunc( HUTI_Z_CG )
1284
CASE (ITER_CGS)
1285
iterProc = AddrFunc( HUTI_Z_CGS )
1286
CASE (ITER_GMRES)
1287
iterProc = AddrFunc( HUTI_Z_GMRES )
1288
1289
! Solvers from IterativeMethods.src
1290
!-------------------------------------------------------
1291
CASE (ITER_GCR)
1292
iterProc = AddrFunc( itermethod_z_gcr )
1293
CASE (ITER_BICGSTABL)
1294
iterProc = AddrFunc( itermethod_z_bicgstabl )
1295
CASE (ITER_IDRS)
1296
iterProc = AddrFunc( itermethod_z_idrs )
1297
CASE DEFAULT
1298
CALL Fatal('IterSolver', 'Complex arithmetic version of the given linear solver is not available')
1299
END SELECT
1300
1301
IF( Internal ) THEN
1302
! IF ( dotProc == 0 ) dotProc = AddrFunc(zdotc)
1303
IF ( normProc == 0 ) normproc = AddrFunc(dznrm2)
1304
IF( HUTI_DBUGLVL == 0) HUTI_DBUGLVL = HUGE( HUTI_DBUGLVL )
1305
END IF
1306
1307
IF ( dotProc == 0 ) dotProc = AddrFunc(Otmp_zdotc)
1308
1309
END IF
1310
1311
!------------------------------------------------------------------------------
1312
1313
stack_pos = stack_pos+1
1314
IF(stack_pos>stack_max) THEN
1315
CALL Fatal('IterSolver', 'Recursion too deep ('//I2S(stack_pos)//' vs '//I2S(stack_max)//')')
1316
ELSE IF(stack_pos<=0) THEN
1317
CALL Fatal('IterSolver', 'eh')
1318
END IF
1319
FirstCall(stack_pos) = .TRUE.
1320
1321
SaveGlobalM => GlobalMatrix
1322
GlobalMatrix => A
1323
1324
IF ( ComplexSystem ) THEN
1325
! Associate xC and bC with complex variables
1326
ALLOCATE(xC(HUTI_NDIM), bC(HUTI_NDIM), STAT=astat)
1327
IF (astat /= 0) THEN
1328
CALL Fatal('IterSolve','Unable to allocate memory for complex arrays')
1329
END IF
1330
! Initialize xC and bC
1331
DO i=1,HUTI_NDIM
1332
xC(i) = cmplx(x(2*i-1),x(2*i),dp)
1333
END DO
1334
DO i=1,HUTI_NDIM
1335
bC(i) = cmplx(b(2*i-1),b(2*i),dp)
1336
END DO
1337
1338
CALL Info('IterSolver','Calling complex iterative solver',Level=32)
1339
1340
IF (LeftOriented) THEN
1341
CALL IterCall( iterProc, xC, bC, ipar, dpar, workC, &
1342
mvProc, pcondProc, pconddProc, dotProc, normProc, stopcProc )
1343
ELSE
1344
CALL IterCall( iterProc, xC, bC, ipar, dpar, workC, &
1345
mvProc, pconddProc, pcondProc, dotProc, normProc, stopcProc )
1346
END IF
1347
1348
! Copy result back
1349
DO i=1,HUTI_NDIM
1350
x(2*i-1) = REAL(REAL(xC(i)),dp)
1351
x(2*i) = REAL(AIMAG(xC(i)),dp)
1352
END DO
1353
DEALLOCATE(bC,xC)
1354
ELSE
1355
CALL Info('IterSolver','Calling real-valued iterative solver',Level=32)
1356
1357
IF (LeftOriented) THEN
1358
CALL IterCall( iterProc, x, b, ipar, dpar, work, &
1359
mvProc, pcondProc, pconddProc, dotProc, normProc, stopcProc )
1360
ELSE
1361
CALL IterCall( iterProc, x, b, ipar, dpar, work, &
1362
mvProc, pconddProc, pcondProc, dotProc, normProc, stopcProc )
1363
END IF
1364
ENDIF
1365
1366
GlobalMatrix => SaveGlobalM
1367
1368
stack_pos=stack_pos-1
1369
1370
IF ( ComplexSystem ) HUTI_NDIM = HUTI_NDIM * 2
1371
1372
!------------------------------------------------------------------------------
1373
IF ( HUTI_INFO == HUTI_CONVERGENCE ) THEN
1374
IF( ASSOCIATED( Solver % Variable ) ) THEN
1375
Solver % Variable % LinConverged = 1
1376
END IF
1377
ELSE
1378
CALL Info('IterSolve','Returned return code: '//I2S(HUTI_INFO),Level=15)
1379
IF( HUTI_INFO == HUTI_DIVERGENCE ) THEN
1380
CALL NumericalError( 'IterSolve', 'System diverged over maximum tolerance.')
1381
ELSE IF( HUTI_INFO == HUTI_MAXITER ) THEN
1382
DoFatal = ListGetLogical( Params,'Linear System Abort Not Converged',Found )
1383
IF(.NOT. Found ) DoFatal = .TRUE.
1384
IF( DoFatal ) THEN
1385
CALL NumericalError('IterSolve','Too many iterations were needed.')
1386
ELSE
1387
CALL Info('IterSolve','Linear iteration did not converge to tolerance',Level=6)
1388
END IF
1389
ELSE IF( HUTI_INFO == HUTI_HALTED ) THEN
1390
CALL Warn('IterSolve','Iteration halted due to problem in algorithm, trying to continue')
1391
END IF
1392
IF( ASSOCIATED( Solver % Variable ) ) THEN
1393
Solver % Variable % LinConverged = 0
1394
END IF
1395
END IF
1396
!------------------------------------------------------------------------------
1397
IF ( ComplexSystem ) THEN
1398
DEALLOCATE( workC )
1399
ELSE
1400
DEALLOCATE( work )
1401
END IF
1402
1403
!------------------------------------------------------------------------------
1404
END SUBROUTINE IterSolver
1405
!------------------------------------------------------------------------------
1406
1407
!-----------------------------------------------------------------------
1408
!> This routine may be used to either inform user or terminate following
1409
!> convergence/numerical issues, based on a flag in the SIF. Default
1410
!> behaviour terminates execution.
1411
!-----------------------------------------------------------------------
1412
SUBROUTINE NumericalError( Caller, String, IsFatal )
1413
!-----------------------------------------------------------------------
1414
CHARACTER(LEN=*) :: Caller, String
1415
LOGICAL, OPTIONAL :: IsFatal
1416
!-----------------------------------------------------------------------
1417
LOGICAL :: DoFatal, Found
1418
!-----------------------------------------------------------------------
1419
1420
!Fatality logic:
1421
! 1) Respect calling routine's wishes if present
1422
! 2) Respect solver specific option if present
1423
! 3) Respect global abort flag if present
1424
! 4) Otherwise fatal (backwards compatibility)
1425
1426
IF(PRESENT(IsFatal)) THEN
1427
DoFatal = IsFatal
1428
ELSE
1429
DoFatal = ListGetLogical(CurrentModel % Simulation,&
1430
'Global Abort Not Converged',Found)
1431
IF(.NOT. Found ) DoFatal = .TRUE.
1432
END IF
1433
1434
IF(DoFatal) THEN
1435
CALL Fatal(Caller,'Numerical Error: '//TRIM(String))
1436
ELSE
1437
CALL Warn(Caller,'Numerical Error: '//TRIM(String))
1438
END IF
1439
1440
!-----------------------------------------------------------------------
1441
END SUBROUTINE NumericalError
1442
!-----------------------------------------------------------------------
1443
1444
1445
END MODULE IterSolve
1446
1447
!> \} ElmerLib
1448
1449