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
45 use identity, only : ident_t
48 use logger, only : neko_log, log_size
49 use json_module, only : json_file
52 implicit none
53 private
54
55 integer, public, parameter :: ksp_max_iter = 1e3
56 real(kind=rp), public, parameter :: ksp_abs_tol = 1d-9
57 real(kind=rp), public, parameter :: ksp_rel_tol = 1d-9
58
60 type, public :: ksp_monitor_t
62 character(len=18) :: name = ""
64 integer :: iter
66 real(kind=rp) :: res_start
68 real(kind=rp) :: res_final
70 logical :: converged = .false.
71 contains
72 procedure, pass(this) :: print_header => krylov_monitor_print_header
73 procedure, pass(this) :: print_result => krylov_monitor_print_result
74 end type ksp_monitor_t
75
77 type, public, abstract :: ksp_t
78 class(pc_t), pointer :: m => null()
79 real(kind=rp) :: rel_tol
80 real(kind=rp) :: abs_tol
81 integer :: max_iter
82 class(pc_t), allocatable :: m_ident
83 logical :: monitor
84 contains
86 procedure(ksp_init_intrf), deferred, pass(this) :: init
88 procedure, pass(this) :: init_from_json => krylov_init_from_json
90 procedure, pass(this) :: ksp_init => krylov_init
93 procedure, pass(this) :: ksp_init_from_json => krylov_init_from_json
95 procedure, pass(this) :: ksp_free => krylov_free
97 procedure, pass(this) :: set_pc => krylov_set_pc
99 procedure(ksp_method), pass(this), deferred :: solve
101 procedure(ksp_method_coupled), pass(this), deferred :: solve_coupled
103 procedure, pass(this) :: monitor_start => krylov_monitor_start
105 procedure, pass(this) :: monitor_stop => krylov_monitor_stop
107 procedure, pass(this) :: monitor_iter => krylov_monitor_iter
109 procedure, pass(this) :: is_converged => krylov_is_converged
111 procedure(ksp_t_free), pass(this), deferred :: free
112 end type ksp_t
113
121 abstract interface
122 subroutine ksp_init_intrf(this, n, max_iter, M, rel_tol, abs_tol, monitor)
123 import :: pc_t, ksp_t, rp
124 implicit none
125 class(ksp_t), target, intent(inout) :: this
126 integer, intent(in) :: max_iter
127 class(pc_t), optional, intent(in), target :: M
128 integer, intent(in) :: n
129 real(kind=rp), optional, intent(in) :: rel_tol
130 real(kind=rp), optional, intent(in) :: abs_tol
131 logical, optional, intent(in) :: monitor
132 end subroutine ksp_init_intrf
133 end interface
134
144 abstract interface
145 function ksp_method(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
146 result(ksp_results)
147 import :: scalar_bc_projector_t
148 import :: field_t
149 import :: ksp_t
150 import :: coef_t
151 import :: gs_t
152 import :: ax_t
153 import :: ksp_monitor_t
154 import rp
155 implicit none
156 class(ksp_t), intent(inout) :: this
157 class(ax_t), intent(in) :: ax
158 type(field_t), intent(inout) :: x
159 integer, intent(in) :: n
160 real(kind=rp), dimension(n), intent(in) :: f
161 type(coef_t), intent(inout) :: coef
162 class(scalar_bc_projector_t), intent(inout) :: bc_projector
163 type(gs_t), intent(inout) :: gs_h
164 integer, optional, intent(in) :: niter
165 type(ksp_monitor_t) :: ksp_results
166 end function ksp_method
167 end interface
168
182 abstract interface
183 function ksp_method_coupled(this, Ax, x, y, z, fx, fy, fz, &
184 n, coef, bc_projector, gs_h, niter) result(ksp_results)
185 import :: vector_bc_projector_t
186 import :: field_t
187 import :: ksp_t
188 import :: coef_t
189 import :: gs_t
190 import :: ax_t
191 import :: ksp_monitor_t
192 import rp
193 implicit none
194 class(ksp_t), intent(inout) :: this
195 class(ax_t), intent(in) :: ax
196 type(field_t), intent(inout) :: x
197 type(field_t), intent(inout) :: y
198 type(field_t), intent(inout) :: z
199 integer, intent(in) :: n
200 real(kind=rp), dimension(n), intent(in) :: fx
201 real(kind=rp), dimension(n), intent(in) :: fy
202 real(kind=rp), dimension(n), intent(in) :: fz
203 type(coef_t), intent(inout) :: coef
204 class(vector_bc_projector_t), intent(inout) :: bc_projector
205 type(gs_t), intent(inout) :: gs_h
206 integer, optional, intent(in) :: niter
207 type(ksp_monitor_t), dimension(3) :: ksp_results
208 end function ksp_method_coupled
209 end interface
210
212 abstract interface
213 subroutine ksp_t_free(this)
214 import :: ksp_t
215 class(ksp_t), intent(inout) :: this
216 end subroutine ksp_t_free
217 end interface
218
230 module subroutine krylov_solver_factory_components(object, n, type_name, &
231 max_iter, abstol, m, monitor)
232 class(ksp_t), allocatable, intent(inout) :: object
233 integer, intent(in), value :: n
234 character(len=*), intent(in) :: type_name
235 integer, intent(in) :: max_iter
236 real(kind=rp), optional :: abstol
237 class(pc_t), optional, intent(in), target :: M
238 logical, optional, intent(in) :: monitor
239 end subroutine krylov_solver_factory_components
240
247 module subroutine krylov_solver_factory_json(object, n, json, m)
248 class(ksp_t), allocatable, intent(inout) :: object
249 integer, intent(in), value :: n
250 type(json_file), intent(inout) :: json
251 class(pc_t), optional, intent(in), target :: M
252 end subroutine krylov_solver_factory_json
253 end interface krylov_solver_factory
254
255 interface
256
259 module subroutine krylov_solver_allocator(object, type_name)
260 class(ksp_t), allocatable, intent(inout) :: object
261 character(len=*), intent(in) :: type_name
262 end subroutine krylov_solver_allocator
263 end interface
264
265 !
266 ! Machinery for injecting user-defined types
267 !
268
272 abstract interface
273 subroutine krylov_allocate(obj)
274 import ksp_t
275 class(ksp_t), allocatable, intent(inout) :: obj
276 end subroutine krylov_allocate
277 end interface
278
279 interface
280
281 module subroutine register_krylov(type_name, allocator)
282 character(len=*), intent(in) :: type_name
283 procedure(krylov_allocate), pointer, intent(in) :: allocator
284 end subroutine register_krylov
285 end interface
286
288 type krylov_allocator_entry
289 character(len=NEKO_TYPENAME_LEN) :: type_name
290 procedure(krylov_allocate), pointer, nopass :: allocator
291 end type krylov_allocator_entry
292
294 type(krylov_allocator_entry), allocatable :: krylov_registry(:)
295
297 integer :: krylov_registry_size = 0
298
299 public :: krylov_solver_factory, krylov_solver_allocator, register_krylov, &
300 krylov_allocate
301contains
302
308 subroutine krylov_init(this, max_iter, rel_tol, abs_tol, M, monitor)
309 class(ksp_t), target, intent(inout) :: this
310 integer, intent(in) :: max_iter
311 real(kind=rp), optional, intent(in) :: rel_tol
312 real(kind=rp), optional, intent(in) :: abs_tol
313 class(pc_t), optional, target, intent(in) :: m
314 logical, optional, intent(in) :: monitor
315
316 call krylov_free(this)
317
318 if (present(rel_tol)) then
319 this%rel_tol = rel_tol
320 else
321 this%rel_tol = ksp_rel_tol
322 end if
323
324 if (present(abs_tol)) then
325 this%abs_tol = abs_tol
326 else
327 this%abs_tol = ksp_abs_tol
328 end if
329
330 this%max_iter = max_iter
331
332 if (present(m)) then
333 this%M => m
334 else
335 if (.not. associated(this%M)) then
336 if (neko_bcknd_device .eq. 1) then
337 allocate(device_ident_t::this%M_ident)
338 else
339 allocate(ident_t::this%M_ident)
340 end if
341 this%M => this%M_ident
342 end if
343 end if
344
345 if (present(monitor)) then
346 this%monitor = monitor
347 else
348 this%monitor = .false.
349 end if
350
351 end subroutine krylov_init
352
360 subroutine krylov_init_from_json(this, n, json, M)
361 class(ksp_t), target, intent(inout) :: this
362 integer, intent(in) :: n
363 type(json_file), intent(inout) :: json
364 class(pc_t), optional, intent(in), target :: M
365 integer :: max_iter
366 real(kind=rp) :: abs_tol
367 logical :: monitor
368
369 call json_get_or_lookup_or_default(json, 'max_iterations', max_iter, &
370 ksp_max_iter)
371 call json_get_or_lookup(json, 'absolute_tolerance', abs_tol)
372 call json_get_or_default(json, 'monitor', monitor, .false.)
373
374 call this%init(n, max_iter, m = m, abs_tol = abs_tol, monitor = monitor)
375
376 end subroutine krylov_init_from_json
377
379 subroutine krylov_free(this)
380 class(ksp_t), intent(inout) :: this
381
383
384 end subroutine krylov_free
385
388 subroutine krylov_set_pc(this, M)
389 class(ksp_t), intent(inout) :: this
390 class(pc_t), target, intent(in) :: M
391
392 if (associated(this%M)) then
393 select type (pc => this%M)
394 type is (ident_t)
395 type is (device_ident_t)
396 class default
397 call neko_error('Preconditioner already defined')
398 end select
399 end if
400
401 this%M => m
402
403 end subroutine krylov_set_pc
404
406 subroutine krylov_monitor_start(this, name)
407 class(ksp_t), intent(in) :: this
408 character(len=*) :: name
409 character(len=LOG_SIZE) :: log_buf
410
411 if (this%monitor) then
412 write(log_buf, '(A)') 'Krylov monitor (' // trim(name) // ')'
413 call neko_log%section(trim(log_buf))
414 call neko_log%newline()
415 call neko_log%begin()
416 write(log_buf, '(A)') ' Iter. Residual'
417 call neko_log%message(log_buf)
418 write(log_buf, '(A)') '-------------------------'
419 call neko_log%message(log_buf)
420 end if
421 end subroutine krylov_monitor_start
422
424 subroutine krylov_monitor_stop(this)
425 class(ksp_t), intent(in) :: this
426
427 if (this%monitor) then
428 call neko_log%end()
429 call neko_log%end_section()
430 call neko_log%newline()
431 end if
432 end subroutine krylov_monitor_stop
433
434
436 subroutine krylov_monitor_iter(this, iter, rnorm)
437 class(ksp_t), intent(in) :: this
438 integer, intent(in) :: iter
439 real(kind=rp), intent(in) :: rnorm
440 character(len=LOG_SIZE) :: log_buf
441
442 if (this%monitor) then
443 write(log_buf, '(I6,E18.9)') iter, rnorm
444 call neko_log%message(log_buf)
445 end if
446
447 end subroutine krylov_monitor_iter
448
457 pure function krylov_is_converged(this, iter, residual) result(converged)
458 class(ksp_t), intent(in) :: this
459 integer, intent(in) :: iter
460 real(kind=rp), intent(in) :: residual
461 logical :: converged
462
463 converged = .true.
464 if (iter .ge. this%max_iter) converged = .false.
465 if (residual .gt. this%abs_tol) converged = .false.
466
467 end function krylov_is_converged
468
470 subroutine krylov_monitor_print_header(this)
471 class(ksp_monitor_t), intent(in) :: this
472 character(len=LOG_SIZE) :: log_buf
473
474 write(log_buf, '(A10,2x,A3,(A5,13x),1x,A6,3x,A15,3x,A15)') &
475 'KSP solver', ' | ', 'Field:', 'Iters:', &
476 'Start residual:', 'Final residual:'
477 call neko_log%message(log_buf)
478
479 end subroutine krylov_monitor_print_header
480
482 subroutine krylov_monitor_print_result(this, step)
483 class(ksp_monitor_t), intent(in) :: this
484 integer, intent(in) :: step
485 character(len=LOG_SIZE) :: log_buf
486 character(len=12) :: step_str
487 character(len=:), allocatable :: output_format
488
489 if (this%name .eq. "") call neko_error('Krylov solver name is not set')
490
491 ! Define the output format
492 output_format = '(A12,A3,A18,1x,I6,3x,E15.9,3x,E15.9)'
493 write(step_str, '(I12)') step
494 step_str = adjustl(step_str)
495
496 write(log_buf, output_format) &
497 step_str, ' | ' , adjustl(this%name), this%iter, &
498 this%res_start, this%res_final
499 call neko_log%message(log_buf)
500
501 end subroutine krylov_monitor_print_result
502
503end module krylov
__device__ T solve(const T u, const T y, const T guess, const T nu, const T kappa, const T B)
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Factory for Krylov solvers. Both creates and initializes the object, either from its parameters or fr...
Definition krylov.f90:221
Abstract interface for a Krylov method's constructor.
Definition krylov.f90:122
Abstract interface for a Krylov method's coupled solve routine.
Definition krylov.f90:183
Abstract interface for a Krylov method's solve routine.
Definition krylov.f90:145
Abstract interface for deallocating a Krylov method.
Definition krylov.f90:213
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)
Utilities for retrieving parameters from the case files.
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:57
real(kind=rp), parameter, public ksp_abs_tol
Absolut tolerance.
Definition krylov.f90:56
subroutine krylov_free(this)
Deallocate a Krylov solver.
Definition krylov.f90:380
subroutine krylov_init_from_json(this, n, json, m)
Constructor from a JSON solver block. Reads max_iterations (default KSP_MAX_ITER),...
Definition krylov.f90:361
integer, parameter, public ksp_max_iter
Maximum number of iters.
Definition krylov.f90:55
subroutine krylov_monitor_iter(this, iter, rnorm)
Monitor iteration.
Definition krylov.f90:437
subroutine krylov_init(this, max_iter, rel_tol, abs_tol, m, monitor)
Constructor for the base type.
Definition krylov.f90:309
subroutine krylov_monitor_print_header(this)
Print the Krylov solver's result header.
Definition krylov.f90:471
subroutine krylov_monitor_start(this, name)
Monitor start.
Definition krylov.f90:407
pure logical function krylov_is_converged(this, iter, residual)
Check for convergence.
Definition krylov.f90:458
subroutine krylov_set_pc(this, m)
Setup a Krylov solver's preconditioner.
Definition krylov.f90:389
subroutine krylov_monitor_stop(this)
Monitor stop.
Definition krylov.f90:425
subroutine krylov_monitor_print_result(this, step)
Print the Krylov solver's result.
Definition krylov.f90:483
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:92
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:454
integer, parameter, public neko_typename_len
Definition utils.f90:44
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:44
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:136
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:60
Base abstract type for a canonical Krylov method, solving .
Definition krylov.f90:77
Defines a canonical Krylov preconditioner.
Definition precon.f90:44
Projector for scalar boundary conditions.
Abstract type for resolving vector boundary conditions.