1
! Copyright (C) 2006 Imperial College London and others.
3
! Please see the AUTHORS file in the main source directory for a full list
4
! of copyright holders.
7
! Applied Modelling and Computation Group
8
! Department of Earth Science and Engineering
9
! Imperial College London
11
! amcgsoftware@imperial.ac.uk
13
! This library is free software; you can redistribute it and/or
14
! modify it under the terms of the GNU Lesser General Public
15
! License as published by the Free Software Foundation,
16
! version 2.1 of the License.
18
! This library is distributed in the hope that it will be useful,
19
! but WITHOUT ANY WARRANTY; without even the implied warranty of
20
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
! Lesser General Public License for more details.
23
! You should have received a copy of the GNU Lesser General Public
24
! License along with this library; if not, write to the Free Software
25
! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28
!!!=========================================!!!
29
!!! SOLVERS SUBROUTINES !!!
30
!!!=========================================!!!
38
SUBROUTINE SOLVER( CMC, P, RHS, &
39
NCMC, NONODS, FINCMC, COLCMC, MIDCMC, &
40
ERROR, RELAX, RELAX_DIAABS, RELAX_DIA, N_LIN_ITS )
42
! Solve CMC * P = RHS for RHS.
43
! RELAX: overall relaxation coeff; =1 for no relaxation.
44
! RELAX_DIAABS: relaxation of the absolute values of the sum of the row of the matrix;
45
! - recommend >=2 for hard problems, =0 for easy
46
! RELAX_DIA: relaxation of diagonal; =1 no relaxation (normally applied).
47
! N_LIN_ITS = no of linear iterations
48
! ERROR= solver tolerence between 2 consecutive iterations
50
REAL, intent( in ) :: ERROR, RELAX, RELAX_DIAABS, RELAX_DIA
51
INTEGER, intent( in ) :: N_LIN_ITS, NCMC, NONODS
52
REAL, DIMENSION( NCMC ), intent( in ) :: CMC
53
REAL, DIMENSION( NONODS ), intent( inout ) :: P
54
REAL, DIMENSION( NONODS ), intent( in ) :: RHS
55
INTEGER, DIMENSION( NONODS + 1 ), intent( in ) :: FINCMC
56
INTEGER, DIMENSION( NCMC ), intent( in ) :: COLCMC
57
INTEGER, DIMENSION( NONODS ), intent( in ) :: MIDCMC
59
INTEGER :: ITS, ILOOP, ISTART, IFINI, ISTEP, NOD, COUNT
60
REAL :: R, SABS_DIAG, RTOP, RBOT, POLD, MAX_ERR
62
write(357,*) 'In Solver'
64
Loop_Non_Linear_Iter: DO ITS = 1, N_LIN_ITS
67
Loop_Internal: DO ILOOP = 1, 2
78
Loop_Nods: DO NOD = ISTART, IFINI, ISTEP
79
R = RELAX_DIA * CMC( MIDCMC( NOD )) * P( NOD ) + RHS( NOD )
81
DO COUNT = FINCMC( NOD ), FINCMC( NOD + 1 ) - 1
82
R = R - CMC( COUNT ) * P( COLCMC( COUNT ))
83
SABS_DIAG = SABS_DIAG + ABS( CMC( COUNT ))
85
RTOP = R + RELAX_DIAABS * SABS_DIAG * P( NOD )
86
RBOT = RELAX_DIAABS * SABS_DIAG + RELAX_DIA * CMC( MIDCMC( NOD ))
88
P( NOD ) = RELAX * ( RTOP / RBOT ) + ( 1.0 - RELAX ) * P( NOD )
89
MAX_ERR = MAX( MAX_ERR, ABS( POLD - P( NOD )))
93
IF( MAX_ERR < ERROR ) CYCLE
95
END DO Loop_Non_Linear_Iter
97
write(357,*) 'Leaving Solver'
100
END SUBROUTINE SOLVER
103
SUBROUTINE GETCMC( CMC, CTP, DIAINV, CT, FREDOP, NONODS, &
104
NCOLCT, FINDCT, COLCT, &
105
NCMC, FINCMC, COLCMC )
107
INTEGER, intent( in ) :: FREDOP, NONODS, NCOLCT, NCMC
108
INTEGER, DIMENSION( NCMC ), intent( inout ) :: CMC
109
INTEGER, DIMENSION( NCOLCT ), intent( in ) :: CTP
110
INTEGER, DIMENSION( NONODS ), intent( in ) :: DIAINV
111
INTEGER, DIMENSION( NCOLCT ), intent( in ) :: COLCT, CT
112
INTEGER, DIMENSION( FREDOP + 1 ), intent( in ) :: FINDCT, FINCMC
113
INTEGER, DIMENSION( NCMC ), intent( in ) :: COLCMC
116
INTEGER :: ROW, START, FINISH, ST2, FI2, COL, ST1, FI1, I, J, ACR, ICOL
119
write(357,*) 'In GetCMC'
121
!write(357,*)'ncmc,FREDOP,nonods=',ncmc,FREDOP,nonods
123
CMC( 1 : NCMC ) = 0.0
125
Loop_Row: DO ROW = 1, FREDOP
126
START = FINCMC( ROW )
127
FINISH = FINCMC( ROW + 1 ) - 1
129
FI2 = FINDCT( ROW + 1 ) - 1
131
DO ACR = START, FINISH, 1
134
! Multiplying vector column 'ROW' of C1 by vector column 'COL' of C1.
136
FI1 = FINDCT( COL + 1 ) - 1
138
Loop_I: DO I = ST1, FI1
139
Loop_J: DO J = ST2, FI2
140
IF( COLCT( I ) == COLCT( J )) THEN
142
CTC = CTC + CT( I ) * CTP( J ) * DIAINV( ICOL )
153
write(357,*) 'Leaving GetCMC'
156
END SUBROUTINE GETCMC
159
subroutine getnc( totele, nonods, nloc, nc )
161
integer, intent( in ) :: totele, nonods, nloc
162
integer, intent( inout ) :: nc
164
integer :: nod, ele, ele1, ele2, count
166
write(357,*) 'In GetNC'
169
Loop_cvnod: do nod = 1, nonods
170
ele1 = 1 + ( nod - 2 ) / ( nloc - 1 )
171
ele2 = 1 + ( nod - 1 ) / ( nloc - 1 )
173
Loop_element: do ele = max( 1, ele1 ), min( totele, ele2 ), 1
181
write(357,*) 'Leaving GetNC'
186
subroutine getnele( band, nonods, nele )
188
integer, intent( in ) :: band, nonods
189
integer, intent( inout ) :: nele
190
! band is the semi-bandwidth.
192
integer :: nod, count, iband, col
194
write(357,*) 'In GetNELE'
198
Loop_cvnod: do nod = 1, nonods
200
Loop_Band: do iband = -band, band, 1
202
if( ( col >= 1 ) .and. ( col <= nonods ) ) count = count + 1
212
end subroutine getnele
215
end module solvers_module