Neko 1.99.5
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
cheby.f90
Go to the documentation of this file.
1! Copyright (c) 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!
34module cheby
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 mesh, only : mesh_t
42 use space, only : space_t
43 use gather_scatter, only : gs_t, gs_op_add
44 use bc_list, only : bc_list_t
45 use schwarz, only : schwarz_t
46 use math, only : glsc3, rzero, rone, copy, sub2, cmult2, abscmp, glsc2, &
48 implicit none
49 private
50
52 type, public, extends(ksp_t) :: cheby_t
53 real(kind=rp), allocatable :: d(:)
54 real(kind=rp), allocatable :: w(:)
55 real(kind=rp), allocatable :: r(:)
56 real(kind=rp) :: tha, dlt
57 integer :: power_its = 150
58 logical :: recompute_eigs = .true.
59 logical :: zero_initial_guess = .false.
60 type(schwarz_t), pointer :: schwarz => null()
61 contains
62 procedure, pass(this) :: init => cheby_init
63 procedure, pass(this) :: free => cheby_free
64 procedure, pass(this) :: solve => cheby_impl
65 procedure, pass(this) :: solve_coupled => cheby_solve_coupled
66 end type cheby_t
67
68contains
69
71 subroutine cheby_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
72 class(cheby_t), intent(inout), target :: this
73 integer, intent(in) :: max_iter
74 class(pc_t), optional, intent(in), target :: M
75 integer, intent(in) :: n
76 real(kind=rp), optional, intent(in) :: rel_tol
77 real(kind=rp), optional, intent(in) :: abs_tol
78 logical, optional, intent(in) :: monitor
79
80 call this%free()
81 allocate(this%d(n))
82 allocate(this%w(n))
83 allocate(this%r(n))
84
85 if (present(m)) then
86 this%M => m
87 end if
88
89 if (present(rel_tol) .and. present(abs_tol) .and. present(monitor)) then
90 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
91 else if (present(rel_tol) .and. present(abs_tol)) then
92 call this%ksp_init(max_iter, rel_tol, abs_tol)
93 else if (present(monitor) .and. present(abs_tol)) then
94 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
95 else if (present(rel_tol) .and. present(monitor)) then
96 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
97 else if (present(rel_tol)) then
98 call this%ksp_init(max_iter, rel_tol = rel_tol)
99 else if (present(abs_tol)) then
100 call this%ksp_init(max_iter, abs_tol = abs_tol)
101 else if (present(monitor)) then
102 call this%ksp_init(max_iter, monitor = monitor)
103 else
104 call this%ksp_init(max_iter)
105 end if
106
107 end subroutine cheby_init
108
109 subroutine cheby_free(this)
110 class(cheby_t), intent(inout) :: this
111 if (allocated(this%d)) then
112 deallocate(this%d)
113 end if
114
115 if (allocated(this%w)) then
116 deallocate(this%w)
117 end if
118
119 if (allocated(this%r)) then
120 deallocate(this%r)
121 end if
122 end subroutine cheby_free
123
124 subroutine cheby_power(this, Ax, x, n, coef, blst, gs_h)
125 class(cheby_t), intent(inout) :: this
126 class(ax_t), intent(in) :: Ax
127 type(field_t), intent(inout) :: x
128 integer, intent(in) :: n
129 type(coef_t), intent(inout) :: coef
130 type(bc_list_t), intent(inout) :: blst
131 type(gs_t), intent(inout) :: gs_h
132 real(kind=rp) :: lam, b, a, rn
133 real(kind=rp) :: boost = 1.1_rp
134 real(kind=rp) :: lam_factor = 30.0_rp
135 real(kind=rp) :: wtw, dtw, dtd
136 integer, allocatable :: fixed_seed(:), saved_seed(:)
137 integer :: i, rnd_n
138 associate(w => this%w, d => this%d, r => this%r)
139
140 ! Save current random seed and set a fixed seed
141 call random_seed( size=rnd_n )
142 allocate(saved_seed(rnd_n))
143 allocate(fixed_seed(rnd_n))
144 fixed_seed = 3901
145 call random_seed( get=saved_seed )
146 call random_seed( put=fixed_seed )
147
148 do i = 1, n
149 call random_number(rn)
150 d(i) = rn + 10.0_rp
151 end do
152
153 ! Restore saved random seed
154 call random_seed( put=saved_seed )
155
156 call gs_h%op(d, n, gs_op_add)
157 call blst%apply(d, n)
158
159 !Power method to get lamba max
160 do i = 1, this%power_its
161 call ax%compute(w, d, coef, x%msh, x%Xh)
162 call gs_h%op(w, n, gs_op_add)
163 call blst%apply(w, n)
164 if (associated(this%schwarz)) then
165 call this%schwarz%compute(r, w)
166 call copy(w, r, n)
167 else
168 call this%M%solve(r, w, n)
169 call copy(w, r, n)
170 end if
171
172 wtw = glsc3(w, coef%mult, w, n)
173 call cmult2(d, w, 1.0_rp/sqrt(wtw), n)
174 call blst%apply(d, n)
175 end do
176
177 call ax%compute(w, d, coef, x%msh, x%Xh)
178 call gs_h%op(w, n, gs_op_add)
179 call blst%apply(w, n)
180 if (associated(this%schwarz)) then
181 call this%schwarz%compute(r, w)
182 call copy(w, r, n)
183 else
184 call this%M%solve(r, w, n)
185 call copy(w, r, n)
186 end if
187
188 dtw = glsc3(d, coef%mult, w, n)
189 dtd = glsc3(d, coef%mult, d, n)
190 lam = dtw / dtd
191 b = lam * boost
192 a = lam / lam_factor
193 this%tha = (b+a)/2.0_rp
194 this%dlt = (b-a)/2.0_rp
195
196 this%recompute_eigs = .false.
197 end associate
198 end subroutine cheby_power
199
201 function cheby_solve(this, Ax, x, f, n, coef, blst, gs_h, niter) &
202 result(ksp_results)
203 class(cheby_t), intent(inout) :: this
204 class(ax_t), intent(in) :: ax
205 type(field_t), intent(inout) :: x
206 integer, intent(in) :: n
207 real(kind=rp), dimension(n), intent(in) :: f
208 type(coef_t), intent(inout) :: coef
209 type(bc_list_t), intent(inout) :: blst
210 type(gs_t), intent(inout) :: gs_h
211 type(ksp_monitor_t) :: ksp_results
212 integer, optional, intent(in) :: niter
213 integer :: iter, max_iter
214 real(kind=rp) :: a, b, rtr, rnorm, norm_fac
215
216 if (this%recompute_eigs) then
217 call cheby_power(this, ax, x, n, coef, blst, gs_h)
218 end if
219
220 if (present(niter)) then
221 max_iter = niter
222 else
223 max_iter = this%max_iter
224 end if
225 norm_fac = 1.0_rp / sqrt(coef%volume)
226
227 associate( w => this%w, r => this%r, d => this%d)
228 ! calculate residual
229 call copy(r, f, n)
230 call ax%compute(w, x%x, coef, x%msh, x%Xh)
231 call gs_h%op(w, n, gs_op_add)
232 call blst%apply(w, n)
233 call sub2(r, w, n)
234
235 rtr = glsc3(r, coef%mult, r, n)
236 rnorm = sqrt(rtr) * norm_fac
237 ksp_results%res_start = rnorm
238 ksp_results%res_final = rnorm
239 ksp_results%iter = 0
240
241 ! First iteration
242 call this%M%solve(w, r, n)
243 call copy(d, w, n)
244 a = 2.0_rp / this%tha
245 call add2s2(x%x, d, a, n)! x = x + a*d
246
247 ! Rest of the iterations
248 do iter = 2, max_iter
249 ! calculate residual
250 call copy(r, f, n)
251 call ax%compute(w, x%x, coef, x%msh, x%Xh)
252 call gs_h%op(w, n, gs_op_add)
253 call blst%apply(w, n)
254 call sub2(r, w, n)
255
256 call this%M%solve(w, r, n)
257
258 if (iter .eq. 2) then
259 b = 0.5_rp * (this%dlt * a)**2
260 else
261 b = (this%dlt * a / 2.0_rp)**2
262 end if
263 a = 1.0_rp/(this%tha - b/a)
264 call add2s1(d, w, b, n)! d = w + b*d
265
266 call add2s2(x%x, d, a, n)! x = x + a*d
267 end do
268
269 ! calculate residual
270 call copy(r, f, n)
271 call ax%compute(w, x%x, coef, x%msh, x%Xh)
272 call gs_h%op(w, n, gs_op_add)
273 call blst%apply(w, n)
274 call sub2(r, w, n)
275 rtr = glsc3(r, coef%mult, r, n)
276 rnorm = sqrt(rtr) * norm_fac
277 ksp_results%res_final = rnorm
278 ksp_results%iter = iter
279 ksp_results%converged = this%is_converged(iter, rnorm)
280 end associate
281 end function cheby_solve
282
284 function cheby_impl(this, Ax, x, f, n, coef, blst, gs_h, niter) &
285 result(ksp_results)
286 class(cheby_t), intent(inout) :: this
287 class(ax_t), intent(in) :: ax
288 type(field_t), intent(inout) :: x
289 integer, intent(in) :: n
290 real(kind=rp), dimension(n), intent(in) :: f
291 type(coef_t), intent(inout) :: coef
292 type(bc_list_t), intent(inout) :: blst
293 type(gs_t), intent(inout) :: gs_h
294 type(ksp_monitor_t) :: ksp_results
295 integer, optional, intent(in) :: niter
296 integer :: iter, max_iter, i
297 real(kind=rp) :: a, b, rtr, rnorm, norm_fac
298 real(kind=rp) :: rhok, rhokp1, sig1, tmp1, tmp2
299
300 if (this%recompute_eigs) then
301 call cheby_power(this, ax, x, n, coef, blst, gs_h)
302 end if
303
304 if (present(niter)) then
305 max_iter = niter
306 else
307 max_iter = this%max_iter
308 end if
309 norm_fac = 1.0_rp / sqrt(coef%volume)
310
311 associate( w => this%w, r => this%r, d => this%d)
312 ! calculate residual
313 if (.not.this%zero_initial_guess) then
314 call ax%compute(w, x%x, coef, x%msh, x%Xh)
315 call gs_h%op(w, n, gs_op_add)
316 call blst%apply(w, n)
317 call sub3(r, f, w, n)
318 else
319 call copy(r, f, n)
320 this%zero_initial_guess = .false.
321 end if
322
323 ! First iteration
324 if (associated(this%schwarz)) then
325 call this%schwarz%compute(d, r)
326 else
327 call this%M%solve(d, r, n)
328 end if
329
330 do concurrent(i = 1:n)
331 d(i) = 1.0_rp/this%tha * d(i)
332 x%x(i,1,1,1) = x%x(i,1,1,1) + d(i)
333 end do
334
335 sig1 = this%tha / this%dlt
336 rhok = 1.0_rp / sig1
337
338 ! Rest of the iterations
339 do iter = 2, max_iter
340 rhokp1 = 1.0_rp / (2.0_rp * sig1 - rhok)
341 tmp1 = rhokp1 * rhok
342 tmp2 = 2.0_rp * rhokp1 / this%dlt
343 rhok = rhokp1
344 ! calculate residual
345 call ax%compute(w, x%x, coef, x%msh, x%Xh)
346 call gs_h%op(w, n, gs_op_add)
347 call blst%apply(w, n)
348 call sub3(r, f, w, n)
349
350 if (associated(this%schwarz)) then
351 call this%schwarz%compute(w, r)
352 else
353 call this%M%solve(w, r, n)
354 end if
355 do concurrent(i = 1:n)
356 d(i) = tmp1 * d(i) + tmp2 * w(i)
357 x%x(i,1,1,1) = x%x(i,1,1,1) + d(i)
358 end do
359 end do
360
361 end associate
362 end function cheby_impl
363
365 function cheby_solve_coupled(this, Ax, x, y, z, fx, fy, fz, &
366 n, coef, blstx, blsty, blstz, gs_h, niter) result(ksp_results)
367 class(cheby_t), intent(inout) :: this
368 class(ax_t), intent(in) :: ax
369 type(field_t), intent(inout) :: x
370 type(field_t), intent(inout) :: y
371 type(field_t), intent(inout) :: z
372 integer, intent(in) :: n
373 real(kind=rp), dimension(n), intent(in) :: fx
374 real(kind=rp), dimension(n), intent(in) :: fy
375 real(kind=rp), dimension(n), intent(in) :: fz
376 type(coef_t), intent(inout) :: coef
377 type(bc_list_t), intent(inout) :: blstx
378 type(bc_list_t), intent(inout) :: blsty
379 type(bc_list_t), intent(inout) :: blstz
380 type(gs_t), intent(inout) :: gs_h
381 type(ksp_monitor_t), dimension(3) :: ksp_results
382 integer, optional, intent(in) :: niter
383
384 ksp_results(1) = this%solve(ax, x, fx, n, coef, blstx, gs_h, niter)
385 ksp_results(2) = this%solve(ax, y, fy, n, coef, blsty, gs_h, niter)
386 ksp_results(3) = this%solve(ax, z, fz, n, coef, blstz, gs_h, niter)
387
388 end function cheby_solve_coupled
389
390end module cheby
__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
Defines a list of bc_t.
Definition bc_list.f90:34
Chebyshev preconditioner.
Definition cheby.f90:34
type(ksp_monitor_t) function cheby_impl(this, ax, x, f, n, coef, blst, gs_h, niter)
A chebyshev preconditioner.
Definition cheby.f90:286
subroutine cheby_free(this)
Definition cheby.f90:110
type(ksp_monitor_t) function, dimension(3) cheby_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, blstx, blsty, blstz, gs_h, niter)
Standard Chebyshev coupled solve.
Definition cheby.f90:367
subroutine cheby_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a standard solver.
Definition cheby.f90:72
subroutine cheby_power(this, ax, x, n, coef, blst, gs_h)
Definition cheby.f90:125
type(ksp_monitor_t) function cheby_solve(this, ax, x, f, n, coef, blst, gs_h, niter)
A chebyshev preconditioner.
Definition cheby.f90:203
Coefficients.
Definition coef.f90:34
Defines a field.
Definition field.f90:34
Gather-scatter.
Implements the base abstract type for Krylov solvers plus helper types.
Definition krylov.f90:34
Definition math.f90:60
subroutine, public cmult(a, c, n)
Multiplication by constant c .
Definition math.f90:504
subroutine, public cmult2(a, b, c, n)
Multiplication by constant c .
Definition math.f90:519
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
Definition math.f90:1287
subroutine, public add2s1(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on first argument)
Definition math.f90:981
real(kind=rp) function, public glsc2(a, b, n)
Weighted inner product .
Definition math.f90:1266
subroutine, public rone(a, n)
Set all elements to one.
Definition math.f90:277
subroutine, public sub3(a, b, c, n)
Vector subtraction .
Definition math.f90:963
subroutine, public add2(a, b, n)
Vector addition .
Definition math.f90:900
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:291
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:235
subroutine, public sub2(a, b, n)
Vector substraction .
Definition math.f90:948
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
Definition math.f90:998
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Krylov preconditioner.
Definition precon.f90:34
Overlapping schwarz solves.
Definition schwarz.f90:61
Defines a function space.
Definition space.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:49
Defines a Chebyshev preconditioner.
Definition cheby.f90:52
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:62
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
The function space for the SEM solution fields.
Definition space.f90:63