Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
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
45 use math, only : glsc3, rzero, rone, copy, cmult2, col2, col3, add2s2, abscmp
47 use mpi_f08
48 implicit none
49 private
50
52 type, public, extends(ksp_t) :: sx_gmres_t
53 integer :: lgmres = 30
54 real(kind=rp), allocatable :: w(:)
55 real(kind=rp), allocatable :: c(:)
56 real(kind=rp), allocatable :: r(:)
57 real(kind=rp), allocatable :: z(:,:)
58 real(kind=rp), allocatable :: h(:,:)
59 real(kind=rp), allocatable :: ml(:)
60 real(kind=rp), allocatable :: v(:,:)
61 real(kind=rp), allocatable :: s(:)
62 real(kind=rp), allocatable :: mu(:)
63 real(kind=rp), allocatable :: gam(:)
64 real(kind=rp), allocatable :: wk1(:)
65 real(kind=rp) :: rnorm
66 contains
67 procedure, pass(this) :: init => sx_gmres_init
68 procedure, pass(this) :: free => sx_gmres_free
69 procedure, pass(this) :: solve => sx_gmres_solve
70 procedure, pass(this) :: solve_coupled => sx_gmres_solve_coupled
71 end type sx_gmres_t
72
73contains
74
76 subroutine sx_gmres_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
77 class(sx_gmres_t), target, intent(inout) :: this
78 integer, intent(in) :: n
79 integer, intent(in) :: max_iter
80 class(pc_t), optional, intent(in), target :: M
81 real(kind=rp), optional, intent(in) :: rel_tol
82 real(kind=rp), optional, intent(in) :: abs_tol
83 logical, optional, intent(in) :: monitor
84
85 call this%free()
86
87 if (present(m)) then
88 this%M => m
89 end if
90
91 allocate(this%w(n))
92 allocate(this%r(n))
93 allocate(this%ml(n))
94 allocate(this%mu(n))
95 allocate(this%wk1(n))
96
97 allocate(this%c(this%lgmres))
98 allocate(this%s(this%lgmres))
99 allocate(this%gam(this%lgmres + 1))
100
101 allocate(this%z(n, this%lgmres))
102 allocate(this%v(n, this%lgmres))
103
104 allocate(this%h(this%lgmres, this%lgmres))
105
106
107 if (present(rel_tol) .and. present(abs_tol) .and. present(monitor)) then
108 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
109 else if (present(rel_tol) .and. present(abs_tol)) then
110 call this%ksp_init(max_iter, rel_tol, abs_tol)
111 else if (present(monitor) .and. present(abs_tol)) then
112 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
113 else if (present(rel_tol) .and. present(monitor)) then
114 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
115 else if (present(rel_tol)) then
116 call this%ksp_init(max_iter, rel_tol = rel_tol)
117 else if (present(abs_tol)) then
118 call this%ksp_init(max_iter, abs_tol = abs_tol)
119 else if (present(monitor)) then
120 call this%ksp_init(max_iter, monitor = monitor)
121 else
122 call this%ksp_init(max_iter)
123 end if
124
125 end subroutine sx_gmres_init
126
128 subroutine sx_gmres_free(this)
129 class(sx_gmres_t), intent(inout) :: this
130
131 call this%ksp_free()
132
133 if (allocated(this%w)) then
134 deallocate(this%w)
135 end if
136
137 if (allocated(this%c)) then
138 deallocate(this%c)
139 end if
140
141 if (allocated(this%r)) then
142 deallocate(this%r)
143 end if
144
145 if (allocated(this%z)) then
146 deallocate(this%z)
147 end if
148
149 if (allocated(this%h)) then
150 deallocate(this%h)
151 end if
152
153 if (allocated(this%ml)) then
154 deallocate(this%ml)
155 end if
156
157 if (allocated(this%v)) then
158 deallocate(this%v)
159 end if
160
161 if (allocated(this%s)) then
162 deallocate(this%s)
163 end if
164
165 if (allocated(this%mu)) then
166 deallocate(this%mu)
167 end if
168
169 if (allocated(this%gam)) then
170 deallocate(this%gam)
171 end if
172
173 if (allocated(this%wk1)) then
174 deallocate(this%wk1)
175 end if
176
177 nullify(this%M)
178
179 end subroutine sx_gmres_free
180
182 function sx_gmres_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
183 result(ksp_results)
184 class(sx_gmres_t), intent(inout) :: this
185 class(ax_t), intent(in) :: ax
186 type(field_t), intent(inout) :: x
187 integer, intent(in) :: n
188 real(kind=rp), dimension(n), intent(in) :: f
189 type(coef_t), intent(inout) :: coef
190 class(scalar_bc_projector_t), intent(inout) :: bc_projector
191 type(gs_t), intent(inout) :: gs_h
192 type(ksp_monitor_t) :: ksp_results
193 integer, optional, intent(in) :: niter
194 integer :: iter, max_iter, glb_n
195 integer :: i, j, k, ierr
196 real(kind=rp), parameter :: one = 1.0
197 real(kind=rp) :: rnorm
198 real(kind=rp) :: alpha, temp, l
199 real(kind=rp) :: ratio, div0, norm_fac
200 logical :: conv
201 integer outer
202
203 conv = .false.
204 iter = 0
205 rnorm = 0.0_rp
206 glb_n = n / x%msh%nelv * x%msh%glb_nelv
207
208 if (present(niter)) then
209 max_iter = niter
210 else
211 max_iter = this%max_iter
212 end if
213
214 call rone(this%ml, n)
215 call rone(this%mu, n)
216 norm_fac = one / sqrt(coef%volume)
217 call rzero(x%x, n)
218 call rzero(this%gam, this%lgmres + 1)
219 call rone(this%s, this%lgmres)
220 call rone(this%c, this%lgmres)
221 call rzero(this%h, this%lgmres * this%lgmres)
222 outer = 0
223 call this%monitor_start('GMRES')
224 do while (.not. conv .and. iter .lt. max_iter)
225 outer = outer + 1
226
227 if (iter .eq. 0) then
228 call col3(this%r, this%ml, f, n)
229 else
230 !update residual
231 call copy (this%r,f,n)
232 call ax%compute(this%w, x%x, coef, x%msh, x%Xh)
233 call gs_h%op(this%w, n, gs_op_add)
234 call bc_projector%apply(this%w, n)
235 call add2s2(this%r, this%w, -one, n)
236 call col2(this%r, this%ml, n)
237 end if
238 this%gam(1) = sqrt(glsc3(this%r, this%r, coef%mult, n))
239 if (iter .eq. 0) then
240 div0 = this%gam(1) * norm_fac
241 ksp_results%res_start = div0
242 end if
243
244 if (abscmp(this%gam(1), 0.0_rp)) exit
245
246 rnorm = 0.0_rp
247 temp = one / this%gam(1)
248 call cmult2(this%v(1,1), this%r, temp, n)
249 do j = 1, this%lgmres
250 iter = iter+1
251 call col3(this%w, this%mu, this%v(1,j), n)
252
253 !Apply precond
254 call this%M%solve(this%z(1,j), this%w, n)
255
256 call ax%compute(this%w, this%z(1,j), coef, x%msh, x%Xh)
257 call gs_h%op(this%w, n, gs_op_add)
258 call bc_projector%apply(this%w, n)
259 call col2(this%w, this%ml, n)
260
261 do i = 1, j
262 this%h(i,j) = 0.0_rp
263 do k = 1, n
264 this%h(i,j) = this%h(i,j) + &
265 this%w(k) * this%v(k,i) * coef%mult(k,1,1,1)
266 end do
267 end do
268
269 !Could probably be done inplace...
270 call mpi_allreduce(this%h(1,j), this%wk1, j, &
271 mpi_real_precision, mpi_sum, neko_comm, ierr)
272 call copy(this%h(1,j), this%wk1, j)
273
274 do i = 1, j
275 do k = 1, n
276 this%w(k) = this%w(k) - this%h(i,j) * this%v(k,i)
277 end do
278 end do
279
280 !apply Givens rotations to new column
281 do i = 1, j-1
282 temp = this%h(i,j)
283 this%h(i ,j) = this%c(i)*temp + this%s(i)*this%h(i+1,j)
284 this%h(i+1,j) = -this%s(i)*temp + this%c(i)*this%h(i+1,j)
285 end do
286
287 alpha = sqrt(glsc3(this%w, this%w, coef%mult, n))
288 rnorm = 0.0_rp
289 if (abscmp(alpha, 0.0_rp)) then
290 conv = .true.
291 exit
292 end if
293 l = sqrt(this%h(j,j) * this%h(j,j) + alpha**2)
294 temp = one / l
295 this%c(j) = this%h(j,j) * temp
296 this%s(j) = alpha * temp
297 this%h(j,j) = l
298 this%gam(j+1) = -this%s(j) * this%gam(j)
299 this%gam(j) = this%c(j) * this%gam(j)
300
301 rnorm = abs(this%gam(j+1)) * norm_fac
302 call this%monitor_iter(iter, rnorm)
303 ratio = rnorm / div0
304 if (rnorm .lt. this%abs_tol) then
305 conv = .true.
306 exit
307 end if
308
309 if (iter + 1 .gt. max_iter) exit
310
311 if (j .lt. this%lgmres) then
312 temp = one / alpha
313 call cmult2(this%v(1,j+1), this%w, temp, n)
314 end if
315 end do
316 j = min(j, this%lgmres)
317 !back substitution
318 do k = j, 1, -1
319 temp = this%gam(k)
320 do i = j, k+1, -1
321 temp = temp - this%h(k,i) * this%c(i)
322 end do
323 this%c(k) = temp / this%h(k,k)
324 end do
325 !sum up Arnoldi vectors
326 do i = 1, j
327 do k = 1, n
328 x%x(k,1,1,1) = x%x(k,1,1,1) + this%c(i) * this%z(k,i)
329 end do
330 end do
331 end do
332 call this%monitor_stop()
333 ksp_results%res_final = rnorm
334 ksp_results%iter = iter
335 ksp_results%converged = this%is_converged(iter, rnorm)
336 end function sx_gmres_solve
337
339 function sx_gmres_solve_coupled(this, Ax, x, y, z, fx, fy, fz, &
340 n, coef, bc_projector, gs_h, niter) result(ksp_results)
341 class(sx_gmres_t), intent(inout) :: this
342 class(ax_t), intent(in) :: ax
343 type(field_t), intent(inout) :: x
344 type(field_t), intent(inout) :: y
345 type(field_t), intent(inout) :: z
346 integer, intent(in) :: n
347 real(kind=rp), dimension(n), intent(in) :: fx
348 real(kind=rp), dimension(n), intent(in) :: fy
349 real(kind=rp), dimension(n), intent(in) :: fz
350 type(coef_t), intent(inout) :: coef
351 class(vector_bc_projector_t), intent(inout) :: bc_projector
352 type(gs_t), intent(inout) :: gs_h
353 type(ksp_monitor_t), dimension(3) :: ksp_results
354 integer, optional, intent(in) :: niter
355 type(scalar_bc_projector_t), pointer :: bc_x, bc_y, bc_z
356
357 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
358 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
359 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
360 ksp_results(3) = this%solve(ax, z, fz, n, coef, bc_z, gs_h, niter)
361
362 end function sx_gmres_solve_coupled
363
364end module gmres_sx
__device__ T solve(const T u, const T y, const T guess, const T nu, const T kappa, const T B)
Defines a Matrix-vector product.
Definition ax.f90:34
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:54
type(mpi_comm), public neko_comm
MPI communicator.
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:77
subroutine sx_gmres_free(this)
Deallocate a standard GMRES solver.
Definition gmres_sx.f90:129
type(ksp_monitor_t) function sx_gmres_solve(this, ax, x, f, n, coef, bc_projector, gs_h, niter)
Standard PCG solve.
Definition gmres_sx.f90:184
type(ksp_monitor_t) function, dimension(3) sx_gmres_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, bc_projector, gs_h, niter)
Standard GMRES coupled solve.
Definition gmres_sx.f90:341
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:522
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
Definition math.f90:1290
subroutine, public rone(a, n)
Set all elements to one.
Definition math.f90:280
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:1049
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:294
subroutine, public col3(a, b, c, n)
Vector multiplication with 3 vectors .
Definition math.f90:1064
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:238
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
Definition math.f90:1001
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Krylov preconditioner.
Definition precon.f90:34
Implements scalar_projector_t.
Implements boundary condition projectors for vector fields. Two types concrete types are provided: se...
subroutine, public vector_bc_projector_components(this, x, y, z)
Access the component scalar projectors from a segregated vector projector.
Base type for a matrix-vector product providing .
Definition ax.f90:43
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
Gather-scatter kernel.
Standard preconditioned generalized minimal residual method (SX version)
Definition gmres_sx.f90:52
Type for storing initial and final residuals in a Krylov solver.
Definition krylov.f90:57
Base abstract type for a canonical Krylov method, solving .
Definition krylov.f90:74
Defines a canonical Krylov preconditioner.
Definition precon.f90:40
Projector for scalar boundary conditions.
Abstract type for resolving vector boundary conditions.