Neko 1.99.9
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
45 use identity, only : ident_t
48 use logger, only : neko_log, log_size
49 implicit none
50 private
51
52 integer, public, parameter :: ksp_max_iter = 1e3
53 real(kind=rp), public, parameter :: ksp_abs_tol = 1d-9
54 real(kind=rp), public, parameter :: ksp_rel_tol = 1d-9
55
57 type, public :: ksp_monitor_t
59 character(len=18) :: name = ""
61 integer :: iter
63 real(kind=rp) :: res_start
65 real(kind=rp) :: res_final
67 logical :: converged = .false.
68 contains
69 procedure, pass(this) :: print_header => krylov_monitor_print_header
70 procedure, pass(this) :: print_result => krylov_monitor_print_result
71 end type ksp_monitor_t
72
74 type, public, abstract :: ksp_t
75 class(pc_t), pointer :: m => null()
76 real(kind=rp) :: rel_tol
77 real(kind=rp) :: abs_tol
78 integer :: max_iter
79 class(pc_t), allocatable :: m_ident
80 logical :: monitor
81 contains
83 procedure(ksp_init_intrf), deferred, pass(this) :: init
85 procedure, pass(this) :: ksp_init => krylov_init
87 procedure, pass(this) :: ksp_free => krylov_free
89 procedure, pass(this) :: set_pc => krylov_set_pc
91 procedure(ksp_method), pass(this), deferred :: solve
93 procedure(ksp_method_coupled), pass(this), deferred :: solve_coupled
95 procedure, pass(this) :: monitor_start => krylov_monitor_start
97 procedure, pass(this) :: monitor_stop => krylov_monitor_stop
99 procedure, pass(this) :: monitor_iter => krylov_monitor_iter
101 procedure, pass(this) :: is_converged => krylov_is_converged
103 procedure(ksp_t_free), pass(this), deferred :: free
104 end type ksp_t
105
113 abstract interface
114 subroutine ksp_init_intrf(this, n, max_iter, M, rel_tol, abs_tol, monitor)
115 import :: pc_t, ksp_t, rp
116 implicit none
117 class(ksp_t), target, intent(inout) :: this
118 integer, intent(in) :: max_iter
119 class(pc_t), optional, intent(in), target :: M
120 integer, intent(in) :: n
121 real(kind=rp), optional, intent(in) :: rel_tol
122 real(kind=rp), optional, intent(in) :: abs_tol
123 logical, optional, intent(in) :: monitor
124 end subroutine ksp_init_intrf
125 end interface
126
136 abstract interface
137 function ksp_method(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
138 result(ksp_results)
139 import :: scalar_bc_projector_t
140 import :: field_t
141 import :: ksp_t
142 import :: coef_t
143 import :: gs_t
144 import :: ax_t
145 import :: ksp_monitor_t
146 import rp
147 implicit none
148 class(ksp_t), intent(inout) :: this
149 class(ax_t), intent(in) :: ax
150 type(field_t), intent(inout) :: x
151 integer, intent(in) :: n
152 real(kind=rp), dimension(n), intent(in) :: f
153 type(coef_t), intent(inout) :: coef
154 class(scalar_bc_projector_t), intent(inout) :: bc_projector
155 type(gs_t), intent(inout) :: gs_h
156 integer, optional, intent(in) :: niter
157 type(ksp_monitor_t) :: ksp_results
158 end function ksp_method
159 end interface
160
174 abstract interface
175 function ksp_method_coupled(this, Ax, x, y, z, fx, fy, fz, &
176 n, coef, bc_projector, gs_h, niter) result(ksp_results)
177 import :: vector_bc_projector_t
178 import :: field_t
179 import :: ksp_t
180 import :: coef_t
181 import :: gs_t
182 import :: ax_t
183 import :: ksp_monitor_t
184 import rp
185 implicit none
186 class(ksp_t), intent(inout) :: this
187 class(ax_t), intent(in) :: ax
188 type(field_t), intent(inout) :: x
189 type(field_t), intent(inout) :: y
190 type(field_t), intent(inout) :: z
191 integer, intent(in) :: n
192 real(kind=rp), dimension(n), intent(in) :: fx
193 real(kind=rp), dimension(n), intent(in) :: fy
194 real(kind=rp), dimension(n), intent(in) :: fz
195 type(coef_t), intent(inout) :: coef
196 class(vector_bc_projector_t), intent(inout) :: bc_projector
197 type(gs_t), intent(inout) :: gs_h
198 integer, optional, intent(in) :: niter
199 type(ksp_monitor_t), dimension(3) :: ksp_results
200 end function ksp_method_coupled
201 end interface
202
204 abstract interface
205 subroutine ksp_t_free(this)
206 import :: ksp_t
207 class(ksp_t), intent(inout) :: this
208 end subroutine ksp_t_free
209 end interface
210
211 interface
212
220 module subroutine krylov_solver_factory(object, n, type_name, &
221 max_iter, abstol, m, monitor)
222 class(ksp_t), allocatable, intent(inout) :: object
223 integer, intent(in), value :: n
224 character(len=*), intent(in) :: type_name
225 integer, intent(in) :: max_iter
226 real(kind=rp), optional :: abstol
227 class(pc_t), optional, intent(in), target :: m
228 logical, optional, intent(in) :: monitor
229 end subroutine krylov_solver_factory
230
231 end interface
232
233 interface
234
237 module subroutine krylov_solver_allocator(object, type_name)
238 class(ksp_t), allocatable, intent(inout) :: object
239 character(len=*), intent(in) :: type_name
240 end subroutine krylov_solver_allocator
241 end interface
242
243 !
244 ! Machinery for injecting user-defined types
245 !
246
250 abstract interface
251 subroutine krylov_allocate(obj)
252 import ksp_t
253 class(ksp_t), allocatable, intent(inout) :: obj
254 end subroutine krylov_allocate
255 end interface
256
257 interface
258
259 module subroutine register_krylov(type_name, allocator)
260 character(len=*), intent(in) :: type_name
261 procedure(krylov_allocate), pointer, intent(in) :: allocator
262 end subroutine register_krylov
263 end interface
264
266 type krylov_allocator_entry
267 character(len=20) :: type_name
268 procedure(krylov_allocate), pointer, nopass :: allocator
269 end type krylov_allocator_entry
270
272 type(krylov_allocator_entry), allocatable :: krylov_registry(:)
273
275 integer :: krylov_registry_size = 0
276
277 public :: krylov_solver_factory, krylov_solver_allocator, register_krylov, &
278 krylov_allocate
279contains
280
286 subroutine krylov_init(this, max_iter, rel_tol, abs_tol, M, monitor)
287 class(ksp_t), target, intent(inout) :: this
288 integer, intent(in) :: max_iter
289 real(kind=rp), optional, intent(in) :: rel_tol
290 real(kind=rp), optional, intent(in) :: abs_tol
291 class(pc_t), optional, target, intent(in) :: m
292 logical, optional, intent(in) :: monitor
293
294 call krylov_free(this)
295
296 if (present(rel_tol)) then
297 this%rel_tol = rel_tol
298 else
299 this%rel_tol = ksp_rel_tol
300 end if
301
302 if (present(abs_tol)) then
303 this%abs_tol = abs_tol
304 else
305 this%abs_tol = ksp_abs_tol
306 end if
307
308 this%max_iter = max_iter
309
310 if (present(m)) then
311 this%M => m
312 else
313 if (.not. associated(this%M)) then
314 if (neko_bcknd_device .eq. 1) then
315 allocate(device_ident_t::this%M_ident)
316 else
317 allocate(ident_t::this%M_ident)
318 end if
319 this%M => this%M_ident
320 end if
321 end if
322
323 if (present(monitor)) then
324 this%monitor = monitor
325 else
326 this%monitor = .false.
327 end if
328
329 end subroutine krylov_init
330
332 subroutine krylov_free(this)
333 class(ksp_t), intent(inout) :: this
334
336
337 end subroutine krylov_free
338
341 subroutine krylov_set_pc(this, M)
342 class(ksp_t), intent(inout) :: this
343 class(pc_t), target, intent(in) :: M
344
345 if (associated(this%M)) then
346 select type (pc => this%M)
347 type is (ident_t)
348 type is (device_ident_t)
349 class default
350 call neko_error('Preconditioner already defined')
351 end select
352 end if
353
354 this%M => m
355
356 end subroutine krylov_set_pc
357
359 subroutine krylov_monitor_start(this, name)
360 class(ksp_t), intent(in) :: this
361 character(len=*) :: name
362 character(len=LOG_SIZE) :: log_buf
363
364 if (this%monitor) then
365 write(log_buf, '(A)') 'Krylov monitor (' // trim(name) // ')'
366 call neko_log%section(trim(log_buf))
367 call neko_log%newline()
368 call neko_log%begin()
369 write(log_buf, '(A)') ' Iter. Residual'
370 call neko_log%message(log_buf)
371 write(log_buf, '(A)') '-------------------------'
372 call neko_log%message(log_buf)
373 end if
374 end subroutine krylov_monitor_start
375
377 subroutine krylov_monitor_stop(this)
378 class(ksp_t), intent(in) :: this
379
380 if (this%monitor) then
381 call neko_log%end()
382 call neko_log%end_section()
383 call neko_log%newline()
384 end if
385 end subroutine krylov_monitor_stop
386
387
389 subroutine krylov_monitor_iter(this, iter, rnorm)
390 class(ksp_t), intent(in) :: this
391 integer, intent(in) :: iter
392 real(kind=rp), intent(in) :: rnorm
393 character(len=LOG_SIZE) :: log_buf
394
395 if (this%monitor) then
396 write(log_buf, '(I6,E18.9)') iter, rnorm
397 call neko_log%message(log_buf)
398 end if
399
400 end subroutine krylov_monitor_iter
401
410 pure function krylov_is_converged(this, iter, residual) result(converged)
411 class(ksp_t), intent(in) :: this
412 integer, intent(in) :: iter
413 real(kind=rp), intent(in) :: residual
414 logical :: converged
415
416 converged = .true.
417 if (iter .ge. this%max_iter) converged = .false.
418 if (residual .gt. this%abs_tol) converged = .false.
419
420 end function krylov_is_converged
421
423 subroutine krylov_monitor_print_header(this)
424 class(ksp_monitor_t), intent(in) :: this
425 character(len=LOG_SIZE) :: log_buf
426
427 write(log_buf, '(A10,2x,A3,(A5,13x),1x,A6,3x,A15,3x,A15)') &
428 'KSP solver', ' | ', 'Field:', 'Iters:', &
429 'Start residual:', 'Final residual:'
430 call neko_log%message(log_buf)
431
432 end subroutine krylov_monitor_print_header
433
435 subroutine krylov_monitor_print_result(this, step)
436 class(ksp_monitor_t), intent(in) :: this
437 integer, intent(in) :: step
438 character(len=LOG_SIZE) :: log_buf
439 character(len=12) :: step_str
440 character(len=:), allocatable :: output_format
441
442 if (this%name .eq. "") call neko_error('Krylov solver name is not set')
443
444 ! Define the output format
445 output_format = '(A12,A3,A18,1x,I6,3x,E15.9,3x,E15.9)'
446 write(step_str, '(I12)') step
447 step_str = adjustl(step_str)
448
449 write(log_buf, output_format) &
450 step_str, ' | ' , adjustl(this%name), this%iter, &
451 this%res_start, this%res_final
452 call neko_log%message(log_buf)
453
454 end subroutine krylov_monitor_print_result
455
456end 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:114
Abstract interface for a Krylov method's coupled solve routine.
Definition krylov.f90:175
Abstract interface for a Krylov method's solve routine.
Definition krylov.f90:137
Abstract interface for deallocating a Krylov method.
Definition krylov.f90:205
Defines a Matrix-vector product.
Definition ax.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:54
real(kind=rp), parameter, public ksp_abs_tol
Absolut tolerance.
Definition krylov.f90:53
subroutine krylov_free(this)
Deallocate a Krylov solver.
Definition krylov.f90:333
integer, parameter, public ksp_max_iter
Maximum number of iters.
Definition krylov.f90:52
subroutine krylov_monitor_iter(this, iter, rnorm)
Monitor iteration.
Definition krylov.f90:390
subroutine krylov_init(this, max_iter, rel_tol, abs_tol, m, monitor)
Constructor for the base type.
Definition krylov.f90:287
subroutine krylov_monitor_print_header(this)
Print the Krylov solver's result header.
Definition krylov.f90:424
subroutine krylov_monitor_start(this, name)
Monitor start.
Definition krylov.f90:360
pure logical function krylov_is_converged(this, iter, residual)
Check for convergence.
Definition krylov.f90:411
subroutine krylov_set_pc(this, m)
Setup a Krylov solver's preconditioner.
Definition krylov.f90:342
subroutine krylov_monitor_stop(this)
Monitor stop.
Definition krylov.f90:378
subroutine krylov_monitor_print_result(this, step)
Print the Krylov solver's result.
Definition krylov.f90:436
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:15
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Krylov preconditioner.
Definition precon.f90:34
Implements scalar_projector_t.
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:398
Implements boundary condition projectors for vector fields. Two types concrete types are provided: se...
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
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: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.