SICOPOLIS V3.1
 All Classes Files Functions Variables Macros
sico_sle_solvers.F90
Go to the documentation of this file.
1 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 !
3 ! Module : s i c o _ s l e _ s o l v e r s
4 !
5 !> @file
6 !!
7 !! Solvers for systems of linear equations used by SICOPOLIS.
8 !!
9 !! @section Copyright
10 !!
11 !! Copyright 2009-2013 Ralf Greve, Tatsuru Sato
12 !!
13 !! @section License
14 !!
15 !! This file is part of SICOPOLIS.
16 !!
17 !! SICOPOLIS is free software: you can redistribute it and/or modify
18 !! it under the terms of the GNU General Public License as published by
19 !! the Free Software Foundation, either version 3 of the License, or
20 !! (at your option) any later version.
21 !!
22 !! SICOPOLIS is distributed in the hope that it will be useful,
23 !! but WITHOUT ANY WARRANTY; without even the implied warranty of
24 !! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 !! GNU General Public License for more details.
26 !!
27 !! You should have received a copy of the GNU General Public License
28 !! along with SICOPOLIS. If not, see <http://www.gnu.org/licenses/>.
29 !<
30 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
31 
32 !-------------------------------------------------------------------------------
33 !> Solvers for systems of linear equations used by SICOPOLIS.
34 !<------------------------------------------------------------------------------
36 
37 use sico_types
38 
39 contains
40 
41 !-------------------------------------------------------------------------------
42 !> SOR solver for a system of linear equations lgs_a*lgs_x=lgs_b
43 !! [matrix storage: compressed sparse row CSR,
44 !! represented by arrays lgs_a_value(values), lgs_a_index (indices)
45 !! and lgs_a_ptr (pointers)].
46 !<------------------------------------------------------------------------------
47 subroutine sor_sprs(lgs_a_value, lgs_a_index, lgs_a_diag_index, lgs_a_ptr, &
48  lgs_b_value, &
49  nnz, nmax, omega, eps_sor, lgs_x_value, ierr)
50 
51 implicit none
52 
53 integer(i4b), intent(in) :: nnz, nmax
54 real(dp), intent(in) :: omega, eps_sor
55 integer(i4b), dimension(nmax+1), intent(in) :: lgs_a_ptr
56 integer(i4b), dimension(nnz), intent(in) :: lgs_a_index
57 integer(i4b), dimension(nmax), intent(in) :: lgs_a_diag_index
58 real(dp), dimension(nnz), intent(in) :: lgs_a_value
59 real(dp), dimension(nmax), intent(in) :: lgs_b_value
60 
61 integer(i4b), intent(out) :: ierr
62 real(dp), dimension(nmax), intent(inout) :: lgs_x_value
63 
64 integer(i4b) :: iter
65 integer(i4b) :: nr, k
66 real(dp), allocatable, dimension(:) :: lgs_x_value_prev
67 real(dp) :: b_nr
68 logical :: flag_convergence
69 
70 allocate(lgs_x_value_prev(nmax))
71 
72 iter_loop : do iter=1, 1000
73 
74  lgs_x_value_prev = lgs_x_value
75 
76  do nr=1, nmax
77 
78  b_nr = 0.0_dp
79 
80  do k=lgs_a_ptr(nr), lgs_a_ptr(nr+1)-1
81  b_nr = b_nr + lgs_a_value(k)*lgs_x_value(lgs_a_index(k))
82  end do
83 
84  lgs_x_value(nr) = lgs_x_value(nr) &
85  -omega*(b_nr-lgs_b_value(nr)) &
86  /lgs_a_value(lgs_a_diag_index(nr))
87 
88  end do
89 
90  flag_convergence = .true.
91  do nr=1, nmax
92  if (abs(lgs_x_value(nr)-lgs_x_value_prev(nr)) > eps_sor) then
93  flag_convergence = .false.
94  exit
95  end if
96  end do
97 
98  if (flag_convergence) then
99  write(6,'(11x,a,i5)') 'sor_sprs: iter = ', iter
100  ierr = 0 ! convergence criterion fulfilled
101  deallocate(lgs_x_value_prev)
102  return
103  end if
104 
105 end do iter_loop
106 
107 write(6,'(a,i5)') 'sor_sprs: iter = ', iter
108 ierr = -1 ! convergence criterion not fulfilled
109 deallocate(lgs_x_value_prev)
110 
111 end subroutine sor_sprs
112 
113 !-------------------------------------------------------------------------------
114 !> Solution of a system of linear equations Ax=b with tridiagonal matrix A.
115 !! @param[in] a0 a0(j) is element A_(j,j-1) of Matrix A
116 !! @param[in] a1 a1(j) is element A_(j,j) of Matrix A
117 !! @param[in] a2 a2(j) is element A_(j,j+1) of Matrix A
118 !! @param[in] b inhomogeneity vector
119 !! @param[in] nrows size of matrix A (indices run from 0 (!!!) to nrows)
120 !! @param[out] x Solution vector.
121 !<------------------------------------------------------------------------------
122 subroutine tri_sle(a0, a1, a2, x, b, nrows)
123 
124 implicit none
125 
126 integer(i4b), intent(in) :: nrows
127 real(dp), dimension(0:*), intent(in) :: a0, a2
128 real(dp), dimension(0:*), intent(inout) :: a1, b
129 
130 real(dp), dimension(0:*), intent(out) :: x
131 
132 real(dp), allocatable, dimension(:) :: help_x
133 integer(i4b) :: n
134 
135 !-------- Generate an upper triangular matrix
136 ! ('obere Dreiecksmatrix') --------
137 
138 do n=1, nrows
139  a1(n) = a1(n) - a0(n)/a1(n-1)*a2(n-1)
140 end do
141 
142 do n=1, nrows
143  b(n) = b(n) - a0(n)/a1(n-1)*b(n-1)
144 ! a0(n) = 0.0_dp , not needed in the following, therefore
145 ! not set
146 end do
147 
148 !-------- Iterative solution of the new system --------
149 
150 ! x(nrows) = b(nrows)/a1(nrows)
151 
152 ! do n=nrows-1, 0, -1
153 ! x(n) = (b(n)-a2(n)*x(n+1))/a1(n)
154 ! end do
155 
156 allocate(help_x(0:nrows))
157 
158 help_x(0) = b(nrows)/a1(nrows)
159 
160 do n=1, nrows
161  help_x(n) = b(nrows-n)/a1(nrows-n) &
162  -a2(nrows-n)/a1(nrows-n)*help_x(n-1)
163 end do
164 
165 do n=0, nrows
166  x(n) = help_x(nrows-n)
167 end do
168 
169 ! (The trick with the help_x was introduced in order to avoid
170 ! the negative step in the original, blanked-out loop.)
171 
172 deallocate(help_x)
173 
174 ! WARNING: Subroutine does not check for elements of the main
175 ! diagonal becoming zero. In this case it crashes even
176 ! though the system may be solvable. Otherwise ok.
177 
178 end subroutine tri_sle
179 
180 !-------------------------------------------------------------------------------
181 
182 end module sico_sle_solvers
183 !