Neko 1.99.7
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
krylov.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2023, 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!
34module krylov
35 use gather_scatter, only : gs_t, gs_op_add
36 use ax_product, only : ax_t
37 use num_types, only: rp, c_rp
38 use precon, only : pc_t
39 use coefs, only : coef_t
40 use mesh, only : mesh_t
41 use field, only : field_t
42 use utils, only : neko_error, neko_warning
43 use bc_list, only : bc_list_t
44 use identity, only : ident_t
47 use logger, only : neko_log, log_size
48 implicit none
49 private
50
51 integer, public, parameter :: ksp_max_iter = 1e3
52 real(kind=rp), public, parameter :: ksp_abs_tol = 1d-9
53 real(kind=rp), public, parameter :: ksp_rel_tol = 1d-9
54
56 type, public :: ksp_monitor_t
58 character(len=18) :: name = ""
60 integer :: iter
62 real(kind=rp) :: res_start
64 real(kind=rp) :: res_final
66 logical :: converged = .false.
67 contains
68 procedure, pass(this) :: print_header => krylov_monitor_print_header
69 procedure, pass(this) :: print_result => krylov_monitor_print_result
70 end type ksp_monitor_t
71
73 type, public, abstract :: ksp_t
74 class(pc_t), pointer :: m => null()
75 real(kind=rp) :: rel_tol
76 real(kind=rp) :: abs_tol
77 integer :: max_iter
78 class(pc_t), allocatable :: m_ident
79 logical :: monitor
80 contains
82 procedure(ksp_init_intrf), deferred, pass(this) :: init
84 procedure, pass(this) :: ksp_init => krylov_init
86 procedure, pass(this) :: ksp_free => krylov_free
88 procedure, pass(this) :: set_pc => krylov_set_pc
90 procedure(ksp_method), pass(this), deferred :: solve
92 procedure(ksp_method_coupled), pass(this), deferred :: solve_coupled
94 procedure, pass(this) :: monitor_start => krylov_monitor_start
96 procedure, pass(this) :: monitor_stop => krylov_monitor_stop
98 procedure, pass(this) :: monitor_iter => krylov_monitor_iter
100 procedure, pass(this) :: is_converged => krylov_is_converged
102 procedure(ksp_t_free), pass(this), deferred :: free
103 end type ksp_t
104
112 abstract interface
113 subroutine ksp_init_intrf(this, n, max_iter, M, rel_tol, abs_tol, monitor)
114 import :: pc_t, ksp_t, rp
115 implicit none
116 class(ksp_t), target, intent(inout) :: this
117 integer, intent(in) :: max_iter
118 class(pc_t), optional, intent(in), target :: M
119 integer, intent(in) :: n
120 real(kind=rp), optional, intent(in) :: rel_tol
121 real(kind=rp), optional, intent(in) :: abs_tol
122 logical, optional, intent(in) :: monitor
123 end subroutine ksp_init_intrf
124 end interface
125
135 abstract interface
136 function ksp_method(this, Ax, x, f, n, coef, blst, gs_h, niter) &
137 result(ksp_results)
138 import :: bc_list_t
139 import :: field_t
140 import :: ksp_t
141 import :: coef_t
142 import :: gs_t
143 import :: ax_t
144 import :: ksp_monitor_t
145 import rp
146 implicit none
147 class(ksp_t), intent(inout) :: this
148 class(ax_t), intent(in) :: ax
149 type(field_t), intent(inout) :: x
150 integer, intent(in) :: n
151 real(kind=rp), dimension(n), intent(in) :: f
152 type(coef_t), intent(inout) :: coef
153 type(bc_list_t), intent(inout) :: blst
154 type(gs_t), intent(inout) :: gs_h
155 integer, optional, intent(in) :: niter
156 type(ksp_monitor_t) :: ksp_results
157 end function ksp_method
158 end interface
159
173 abstract interface
174 function ksp_method_coupled(this, Ax, x, y, z, fx, fy, fz, &
175 n, coef, blstx, blsty, blstz, gs_h, niter) result(ksp_results)
176 import :: bc_list_t
177 import :: field_t
178 import :: ksp_t
179 import :: coef_t
180 import :: gs_t
181 import :: ax_t
182 import :: ksp_monitor_t
183 import rp
184 implicit none
185 class(ksp_t), intent(inout) :: this
186 class(ax_t), intent(in) :: ax
187 type(field_t), intent(inout) :: x
188 type(field_t), intent(inout) :: y
189 type(field_t), intent(inout) :: z
190 integer, intent(in) :: n
191 real(kind=rp), dimension(n), intent(in) :: fx
192 real(kind=rp), dimension(n), intent(in) :: fy
193 real(kind=rp), dimension(n), intent(in) :: fz
194 type(coef_t), intent(inout) :: coef
195 type(bc_list_t), intent(inout) :: blstx
196 type(bc_list_t), intent(inout) :: blsty
197 type(bc_list_t), intent(inout) :: blstz
198 type(gs_t), intent(inout) :: gs_h
199 integer, optional, intent(in) :: niter
200 type(ksp_monitor_t), dimension(3) :: ksp_results
201 end function ksp_method_coupled
202 end interface
203
205 abstract interface
206 subroutine ksp_t_free(this)
207 import :: ksp_t
208 class(ksp_t), intent(inout) :: this
209 end subroutine ksp_t_free
210 end interface
211
212 interface
213
221 module subroutine krylov_solver_factory(object, n, type_name, &
222 max_iter, abstol, m, monitor)
223 class(ksp_t), allocatable, intent(inout) :: object
224 integer, intent(in), value :: n
225 character(len=*), intent(in) :: type_name
226 integer, intent(in) :: max_iter
227 real(kind=rp), optional :: abstol
228 class(pc_t), optional, intent(in), target :: m
229 logical, optional, intent(in) :: monitor
230 end subroutine krylov_solver_factory
231
232 end interface
233
234 interface
235
238 module subroutine krylov_solver_allocator(object, type_name)
239 class(ksp_t), allocatable, intent(inout) :: object
240 character(len=*), intent(in) :: type_name
241 end subroutine krylov_solver_allocator
242 end interface
243
244 !
245 ! Machinery for injecting user-defined types
246 !
247
251 abstract interface
252 subroutine krylov_allocate(obj)
253 import ksp_t
254 class(ksp_t), allocatable, intent(inout) :: obj
255 end subroutine krylov_allocate
256 end interface
257
258 interface
259
260 module subroutine register_krylov(type_name, allocator)
261 character(len=*), intent(in) :: type_name
262 procedure(krylov_allocate), pointer, intent(in) :: allocator
263 end subroutine register_krylov
264 end interface
265
267 type krylov_allocator_entry
268 character(len=20) :: type_name
269 procedure(krylov_allocate), pointer, nopass :: allocator
270 end type krylov_allocator_entry
271
273 type(krylov_allocator_entry), allocatable :: krylov_registry(:)
274
276 integer :: krylov_registry_size = 0
277
278 public :: krylov_solver_factory, krylov_solver_allocator, register_krylov, &
279 krylov_allocate
280contains
281
287 subroutine krylov_init(this, max_iter, rel_tol, abs_tol, M, monitor)
288 class(ksp_t), target, intent(inout) :: this
289 integer, intent(in) :: max_iter
290 real(kind=rp), optional, intent(in) :: rel_tol
291 real(kind=rp), optional, intent(in) :: abs_tol
292 class(pc_t), optional, target, intent(in) :: m
293 logical, optional, intent(in) :: monitor
294
295 call krylov_free(this)
296
297 if (present(rel_tol)) then
298 this%rel_tol = rel_tol
299 else
300 this%rel_tol = ksp_rel_tol
301 end if
302
303 if (present(abs_tol)) then
304 this%abs_tol = abs_tol
305 else
306 this%abs_tol = ksp_abs_tol
307 end if
308
309 this%max_iter = max_iter
310
311 if (present(m)) then
312 this%M => m
313 else
314 if (.not. associated(this%M)) then
315 if (neko_bcknd_device .eq. 1) then
316 allocate(device_ident_t::this%M_ident)
317 else
318 allocate(ident_t::this%M_ident)
319 end if
320 this%M => this%M_ident
321 end if
322 end if
323
324 if (present(monitor)) then
325 this%monitor = monitor
326 else
327 this%monitor = .false.
328 end if
329
330 end subroutine krylov_init
331
333 subroutine krylov_free(this)
334 class(ksp_t), intent(inout) :: this
335
337
338 end subroutine krylov_free
339
342 subroutine krylov_set_pc(this, M)
343 class(ksp_t), intent(inout) :: this
344 class(pc_t), target, intent(in) :: M
345
346 if (associated(this%M)) then
347 select type (pc => this%M)
348 type is (ident_t)
349 type is (device_ident_t)
350 class default
351 call neko_error('Preconditioner already defined')
352 end select
353 end if
354
355 this%M => m
356
357 end subroutine krylov_set_pc
358
360 subroutine krylov_monitor_start(this, name)
361 class(ksp_t), intent(in) :: this
362 character(len=*) :: name
363 character(len=LOG_SIZE) :: log_buf
364
365 if (this%monitor) then
366 write(log_buf, '(A)') 'Krylov monitor (' // trim(name) // ')'
367 call neko_log%section(trim(log_buf))
368 call neko_log%newline()
369 call neko_log%begin()
370 write(log_buf, '(A)') ' Iter. Residual'
371 call neko_log%message(log_buf)
372 write(log_buf, '(A)') '-------------------------'
373 call neko_log%message(log_buf)
374 end if
375 end subroutine krylov_monitor_start
376
378 subroutine krylov_monitor_stop(this)
379 class(ksp_t), intent(in) :: this
380
381 if (this%monitor) then
382 call neko_log%end()
383 call neko_log%end_section()
384 call neko_log%newline()
385 end if
386 end subroutine krylov_monitor_stop
387
388
390 subroutine krylov_monitor_iter(this, iter, rnorm)
391 class(ksp_t), intent(in) :: this
392 integer, intent(in) :: iter
393 real(kind=rp), intent(in) :: rnorm
394 character(len=LOG_SIZE) :: log_buf
395
396 if (this%monitor) then
397 write(log_buf, '(I6,E18.9)') iter, rnorm
398 call neko_log%message(log_buf)
399 end if
400
401 end subroutine krylov_monitor_iter
402
411 pure function krylov_is_converged(this, iter, residual) result(converged)
412 class(ksp_t), intent(in) :: this
413 integer, intent(in) :: iter
414 real(kind=rp), intent(in) :: residual
415 logical :: converged
416
417 converged = .true.
418 if (iter .ge. this%max_iter) converged = .false.
419 if (residual .gt. this%abs_tol) converged = .false.
420
421 end function krylov_is_converged
422
424 subroutine krylov_monitor_print_header(this)
425 class(ksp_monitor_t), intent(in) :: this
426 character(len=LOG_SIZE) :: log_buf
427
428 write(log_buf, '(A10,2x,A3,(A5,13x),1x,A6,3x,A15,3x,A15)') &
429 'KSP solver', ' | ', 'Field:', 'Iters:', &
430 'Start residual:', 'Final residual:'
431 call neko_log%message(log_buf)
432
433 end subroutine krylov_monitor_print_header
434
436 subroutine krylov_monitor_print_result(this, step)
437 class(ksp_monitor_t), intent(in) :: this
438 integer, intent(in) :: step
439 character(len=LOG_SIZE) :: log_buf
440 character(len=12) :: step_str
441 character(len=:), allocatable :: output_format
442
443 if (this%name .eq. "") call neko_error('Krylov solver name is not set')
444
445 ! Define the output format
446 output_format = '(A12,A3,A18,1x,I6,3x,E15.9,3x,E15.9)'
447 write(step_str, '(I12)') step
448 step_str = adjustl(step_str)
449
450 write(log_buf, output_format) &
451 step_str, ' | ' , adjustl(this%name), this%iter, &
452 this%res_start, this%res_final
453 call neko_log%message(log_buf)
454
455 end subroutine krylov_monitor_print_result
456
457end module krylov
__device__ T solve(const T u, const T y, const T guess, const T nu, const T kappa, const T B)
Abstract interface for a Krylov method's constructor.
Definition krylov.f90:113
Abstract interface for a Krylov method's coupled solve routine.
Definition krylov.f90:174
Abstract interface for a Krylov method's solve routine.
Definition krylov.f90:136
Abstract interface for deallocating a Krylov method.
Definition krylov.f90:206
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
Identity Krylov preconditioner for accelerators.
Defines a field.
Definition field.f90:34
Gather-scatter.
Krylov preconditioner (identity)
Implements the base abstract type for Krylov solvers plus helper types.
Definition krylov.f90:34
real(kind=rp), parameter, public ksp_rel_tol
Relative tolerance.
Definition krylov.f90:53
real(kind=rp), parameter, public ksp_abs_tol
Absolut tolerance.
Definition krylov.f90:52
subroutine krylov_free(this)
Deallocate a Krylov solver.
Definition krylov.f90:334
integer, parameter, public ksp_max_iter
Maximum number of iters.
Definition krylov.f90:51
subroutine krylov_monitor_iter(this, iter, rnorm)
Monitor iteration.
Definition krylov.f90:391
subroutine krylov_init(this, max_iter, rel_tol, abs_tol, m, monitor)
Constructor for the base type.
Definition krylov.f90:288
subroutine krylov_monitor_print_header(this)
Print the Krylov solver's result header.
Definition krylov.f90:425
subroutine krylov_monitor_start(this, name)
Monitor start.
Definition krylov.f90:361
pure logical function krylov_is_converged(this, iter, residual)
Check for convergence.
Definition krylov.f90:412
subroutine krylov_set_pc(this, m)
Setup a Krylov solver's preconditioner.
Definition krylov.f90:343
subroutine krylov_monitor_stop(this)
Monitor stop.
Definition krylov.f90:379
subroutine krylov_monitor_print_result(this, step)
Print the Krylov solver's result.
Definition krylov.f90:437
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public c_rp
Definition num_types.f90:13
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Krylov preconditioner.
Definition precon.f90:34
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:398
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:49
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
Defines a canonical Krylov preconditioner for accelerators.
Gather-scatter kernel.
Defines a canonical Krylov preconditioner.
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:73
Defines a canonical Krylov preconditioner.
Definition precon.f90:40