Loading [MathJax]/extensions/tex2jax.js
Neko 0.9.99
A portable framework for high-order spectral element flow simulations
All Classes Namespaces Files Functions Variables Typedefs Enumerator Macros Pages
gmres_sx.f90
Go to the documentation of this file.
1! Copyright (c) 2021-2024, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
35 use krylov, only : ksp_t, ksp_monitor_t
36 use precon, only : pc_t
37 use ax_product, only : ax_t
38 use num_types, only: rp
39 use field, only : field_t
40 use coefs, only : coef_t
41 use gather_scatter, only : gs_t, gs_op_add
42 use bc_list, only : bc_list_t
43 use math, only : glsc3, rzero, rone, copy, cmult2, col2, col3, add2s2, abscmp
44 use comm
45 implicit none
46 private
47
49 type, public, extends(ksp_t) :: sx_gmres_t
50 integer :: lgmres = 30
51 real(kind=rp), allocatable :: w(:)
52 real(kind=rp), allocatable :: c(:)
53 real(kind=rp), allocatable :: r(:)
54 real(kind=rp), allocatable :: z(:,:)
55 real(kind=rp), allocatable :: h(:,:)
56 real(kind=rp), allocatable :: ml(:)
57 real(kind=rp), allocatable :: v(:,:)
58 real(kind=rp), allocatable :: s(:)
59 real(kind=rp), allocatable :: mu(:)
60 real(kind=rp), allocatable :: gam(:)
61 real(kind=rp), allocatable :: wk1(:)
62 real(kind=rp) :: rnorm
63 contains
64 procedure, pass(this) :: init => sx_gmres_init
65 procedure, pass(this) :: free => sx_gmres_free
66 procedure, pass(this) :: solve => sx_gmres_solve
67 procedure, pass(this) :: solve_coupled => sx_gmres_solve_coupled
68 end type sx_gmres_t
69
70contains
71
73 subroutine sx_gmres_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
74 class(sx_gmres_t), target, intent(inout) :: this
75 integer, intent(in) :: n
76 integer, intent(in) :: max_iter
77 class(pc_t), optional, intent(in), target :: M
78 real(kind=rp), optional, intent(in) :: rel_tol
79 real(kind=rp), optional, intent(in) :: abs_tol
80 logical, optional, intent(in) :: monitor
81
82 call this%free()
83
84 if (present(m)) then
85 this%M => m
86 end if
87
88 allocate(this%w(n))
89 allocate(this%r(n))
90 allocate(this%ml(n))
91 allocate(this%mu(n))
92 allocate(this%wk1(n))
93
94 allocate(this%c(this%lgmres))
95 allocate(this%s(this%lgmres))
96 allocate(this%gam(this%lgmres + 1))
97
98 allocate(this%z(n,this%lgmres))
99 allocate(this%v(n,this%lgmres))
100
101 allocate(this%h(this%lgmres,this%lgmres))
102
103
104 if (present(rel_tol) .and. present(abs_tol) .and. present(monitor)) then
105 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
106 else if (present(rel_tol) .and. present(abs_tol)) then
107 call this%ksp_init(max_iter, rel_tol, abs_tol)
108 else if (present(monitor) .and. present(abs_tol)) then
109 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
110 else if (present(rel_tol) .and. present(monitor)) then
111 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
112 else if (present(rel_tol)) then
113 call this%ksp_init(max_iter, rel_tol = rel_tol)
114 else if (present(abs_tol)) then
115 call this%ksp_init(max_iter, abs_tol = abs_tol)
116 else if (present(monitor)) then
117 call this%ksp_init(max_iter, monitor = monitor)
118 else
119 call this%ksp_init(max_iter)
120 end if
121
122 end subroutine sx_gmres_init
123
125 subroutine sx_gmres_free(this)
126 class(sx_gmres_t), intent(inout) :: this
127
128 call this%ksp_free()
129
130 if (allocated(this%w)) then
131 deallocate(this%w)
132 end if
133
134 if (allocated(this%c)) then
135 deallocate(this%c)
136 end if
137
138 if (allocated(this%r)) then
139 deallocate(this%r)
140 end if
141
142 if (allocated(this%z)) then
143 deallocate(this%z)
144 end if
145
146 if (allocated(this%h)) then
147 deallocate(this%h)
148 end if
149
150 if (allocated(this%ml)) then
151 deallocate(this%ml)
152 end if
153
154 if (allocated(this%v)) then
155 deallocate(this%v)
156 end if
157
158 if (allocated(this%s)) then
159 deallocate(this%s)
160 end if
161
162 if (allocated(this%mu)) then
163 deallocate(this%mu)
164 end if
165
166 if (allocated(this%gam)) then
167 deallocate(this%gam)
168 end if
169
170 if (allocated(this%wk1)) then
171 deallocate(this%wk1)
172 end if
173
174 nullify(this%M)
175
176 end subroutine sx_gmres_free
177
179 function sx_gmres_solve(this, Ax, x, f, n, coef, blst, gs_h, niter) result(ksp_results)
180 class(sx_gmres_t), intent(inout) :: this
181 class(ax_t), intent(in) :: ax
182 type(field_t), intent(inout) :: x
183 integer, intent(in) :: n
184 real(kind=rp), dimension(n), intent(in) :: f
185 type(coef_t), intent(inout) :: coef
186 type(bc_list_t), intent(inout) :: blst
187 type(gs_t), intent(inout) :: gs_h
188 type(ksp_monitor_t) :: ksp_results
189 integer, optional, intent(in) :: niter
190 integer :: iter, max_iter, glb_n
191 integer :: i, j, k, ierr
192 real(kind=rp), parameter :: one = 1.0
193 real(kind=rp) :: rnorm
194 real(kind=rp) :: alpha, temp, l
195 real(kind=rp) :: ratio, div0, norm_fac
196 logical :: conv
197 integer outer
198
199 conv = .false.
200 iter = 0
201 glb_n = n / x%msh%nelv * x%msh%glb_nelv
202
203 if (present(niter)) then
204 max_iter = niter
205 else
206 max_iter = this%max_iter
207 end if
208
209 call rone(this%ml, n)
210 call rone(this%mu, n)
211 norm_fac = one / sqrt(coef%volume)
212 call rzero(x%x, n)
213 call rzero(this%gam, this%lgmres + 1)
214 call rone(this%s, this%lgmres)
215 call rone(this%c, this%lgmres)
216 call rzero(this%h, this%lgmres * this%lgmres)
217 outer = 0
218 call this%monitor_start('GMRES')
219 do while (.not. conv .and. iter .lt. max_iter)
220 outer = outer + 1
221
222 if(iter.eq.0) then
223 call col3(this%r,this%ml,f,n)
224 else
225 !update residual
226 call copy (this%r,f,n)
227 call ax%compute(this%w, x%x, coef, x%msh, x%Xh)
228 call gs_h%op(this%w, n, gs_op_add)
229 call blst%apply(this%w, n)
230 call add2s2(this%r,this%w,-one,n)
231 call col2(this%r,this%ml,n)
232 endif
233 this%gam(1) = sqrt(glsc3(this%r, this%r, coef%mult, n))
234 if(iter.eq.0) then
235 div0 = this%gam(1) * norm_fac
236 ksp_results%res_start = div0
237 endif
238
239 if (abscmp(this%gam(1), 0.0_rp)) return
240
241 rnorm = 0.0_rp
242 temp = one / this%gam(1)
243 call cmult2(this%v(1,1), this%r, temp, n)
244 do j = 1, this%lgmres
245 iter = iter+1
246 call col3(this%w, this%mu, this%v(1,j), n)
247
248 !Apply precond
249 call this%M%solve(this%z(1,j), this%w, n)
250
251 call ax%compute(this%w, this%z(1,j), coef, x%msh, x%Xh)
252 call gs_h%op(this%w, n, gs_op_add)
253 call blst%apply(this%w, n)
254 call col2(this%w, this%ml, n)
255
256 do i = 1, j
257 this%h(i,j) = 0.0_rp
258 do k = 1, n
259 this%h(i,j) = this%h(i,j) + &
260 this%w(k) * this%v(k,i) * coef%mult(k,1,1,1)
261 end do
262 end do
263
264 !Could probably be done inplace...
265 call mpi_allreduce(this%h(1,j), this%wk1, j, &
266 mpi_real_precision, mpi_sum, neko_comm, ierr)
267 call copy(this%h(1,j), this%wk1, j)
268
269 do i = 1, j
270 do k = 1, n
271 this%w(k) = this%w(k) - this%h(i,j) * this%v(k,i)
272 end do
273 end do
274
275 !apply Givens rotations to new column
276 do i=1,j-1
277 temp = this%h(i,j)
278 this%h(i ,j) = this%c(i)*temp + this%s(i)*this%h(i+1,j)
279 this%h(i+1,j) = -this%s(i)*temp + this%c(i)*this%h(i+1,j)
280 end do
281
282 alpha = sqrt(glsc3(this%w, this%w, coef%mult, n))
283 rnorm = 0.0_rp
284 if(abscmp(alpha, 0.0_rp)) then
285 conv = .true.
286 exit
287 end if
288 l = sqrt(this%h(j,j) * this%h(j,j) + alpha**2)
289 temp = one / l
290 this%c(j) = this%h(j,j) * temp
291 this%s(j) = alpha * temp
292 this%h(j,j) = l
293 this%gam(j+1) = -this%s(j) * this%gam(j)
294 this%gam(j) = this%c(j) * this%gam(j)
295
296 rnorm = abs(this%gam(j+1)) * norm_fac
297 call this%monitor_iter(iter, rnorm)
298 ratio = rnorm / div0
299 if (rnorm .lt. this%abs_tol) then
300 conv = .true.
301 exit
302 end if
303
304 if (iter + 1 .gt. max_iter) exit
305
306 if( j .lt. this%lgmres) then
307 temp = one / alpha
308 call cmult2(this%v(1,j+1), this%w, temp, n)
309 endif
310 end do
311 j = min(j, this%lgmres)
312 !back substitution
313 do k = j, 1, -1
314 temp = this%gam(k)
315 do i = j, k+1, -1
316 temp = temp - this%h(k,i) * this%c(i)
317 enddo
318 this%c(k) = temp / this%h(k,k)
319 enddo
320 !sum up Arnoldi vectors
321 do i = 1, j
322 do k = 1, n
323 x%x(k,1,1,1) = x%x(k,1,1,1) + this%c(i) * this%z(k,i)
324 end do
325 end do
326 end do
327 call this%monitor_stop()
328 ksp_results%res_final = rnorm
329 ksp_results%iter = iter
330 ksp_results%converged = this%is_converged(iter, rnorm)
331 end function sx_gmres_solve
332
334 function sx_gmres_solve_coupled(this, Ax, x, y, z, fx, fy, fz, &
335 n, coef, blstx, blsty, blstz, gs_h, niter) result(ksp_results)
336 class(sx_gmres_t), intent(inout) :: this
337 class(ax_t), intent(in) :: ax
338 type(field_t), intent(inout) :: x
339 type(field_t), intent(inout) :: y
340 type(field_t), intent(inout) :: z
341 integer, intent(in) :: n
342 real(kind=rp), dimension(n), intent(in) :: fx
343 real(kind=rp), dimension(n), intent(in) :: fy
344 real(kind=rp), dimension(n), intent(in) :: fz
345 type(coef_t), intent(inout) :: coef
346 type(bc_list_t), intent(inout) :: blstx
347 type(bc_list_t), intent(inout) :: blsty
348 type(bc_list_t), intent(inout) :: blstz
349 type(gs_t), intent(inout) :: gs_h
350 type(ksp_monitor_t), dimension(3) :: ksp_results
351 integer, optional, intent(in) :: niter
352
353 ksp_results(1) = this%solve(ax, x, fx, n, coef, blstx, gs_h, niter)
354 ksp_results(2) = this%solve(ax, y, fy, n, coef, blsty, gs_h, niter)
355 ksp_results(3) = this%solve(ax, z, fz, n, coef, blstz, gs_h, niter)
356
357 end function sx_gmres_solve_coupled
358
359end module gmres_sx
360
361
Defines a Matrix-vector product.
Definition ax.f90:34
Defines a list of bc_t.
Definition bc_list.f90:34
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_comm) neko_comm
MPI communicator.
Definition comm.F90:38
type(mpi_datatype) mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:46
Defines a field.
Definition field.f90:34
Gather-scatter.
Defines various GMRES methods.
Definition gmres_sx.f90:34
subroutine sx_gmres_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a standard GMRES solver.
Definition gmres_sx.f90:74
type(ksp_monitor_t) function, dimension(3) sx_gmres_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, blstx, blsty, blstz, gs_h, niter)
Standard GMRES coupled solve.
Definition gmres_sx.f90:336
subroutine sx_gmres_free(this)
Deallocate a standard GMRES solver.
Definition gmres_sx.f90:126
type(ksp_monitor_t) function sx_gmres_solve(this, ax, x, f, n, coef, blst, gs_h, niter)
Standard PCG solve.
Definition gmres_sx.f90:180
Implements the base abstract type for Krylov solvers plus helper types.
Definition krylov.f90:34
Definition math.f90:60
subroutine, public cmult2(a, b, c, n)
Multiplication by constant c .
Definition math.f90:700
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
Definition math.f90:894
subroutine, public rone(a, n)
Set all elements to one.
Definition math.f90:227
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:728
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:238
subroutine, public col3(a, b, c, n)
Vector multiplication with 3 vectors .
Definition math.f90:741
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:194
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
Definition math.f90:672
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Krylov preconditioner.
Definition precon.f90:34
Base type for a matrix-vector product providing .
Definition ax.f90:43
A list of allocatable `bc_t`. Follows the standard interface of lists.
Definition bc_list.f90:47
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:55
Standard preconditioned generalized minimal residual method (SX version)
Definition gmres_sx.f90:49
Type for storing initial and final residuals in a Krylov solver.
Definition krylov.f90:56
Base abstract type for a canonical Krylov method, solving .
Definition krylov.f90:68
Defines a canonical Krylov preconditioner.
Definition precon.f90:40