56 real(kind=
rp),
allocatable :: d(:)
57 real(kind=
rp),
allocatable :: w(:)
58 real(kind=
rp),
allocatable :: r(:)
59 real(kind=
rp) :: tha, dlt
60 integer :: power_its = 150
62 integer :: power_its_refresh = 20
64 logical :: warm_start_eigs = .false.
66 logical :: eigs_computed = .false.
68 real(kind=
rp),
allocatable :: ev(:)
69 logical :: recompute_eigs = .true.
70 logical :: zero_initial_guess = .false.
82 subroutine cheby_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
83 class(
cheby_t),
intent(inout),
target :: this
84 integer,
intent(in) :: max_iter
85 class(
pc_t),
optional,
intent(in),
target :: M
86 integer,
intent(in) :: n
87 real(kind=
rp),
optional,
intent(in) :: rel_tol
88 real(kind=
rp),
optional,
intent(in) :: abs_tol
89 logical,
optional,
intent(in) :: monitor
100 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
101 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
102 else if (
present(rel_tol) .and.
present(abs_tol))
then
103 call this%ksp_init(max_iter, rel_tol, abs_tol)
104 else if (
present(monitor) .and.
present(abs_tol))
then
105 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
106 else if (
present(rel_tol) .and.
present(monitor))
then
107 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
108 else if (
present(rel_tol))
then
109 call this%ksp_init(max_iter, rel_tol = rel_tol)
110 else if (
present(abs_tol))
then
111 call this%ksp_init(max_iter, abs_tol = abs_tol)
112 else if (
present(monitor))
then
113 call this%ksp_init(max_iter, monitor = monitor)
115 call this%ksp_init(max_iter)
121 class(
cheby_t),
intent(inout) :: this
122 if (
allocated(this%d))
then
126 if (
allocated(this%w))
then
130 if (
allocated(this%r))
then
133 if (
allocated(this%ev))
then
139 class(
cheby_t),
intent(inout) :: this
140 class(
ax_t),
intent(in) :: Ax
141 type(
field_t),
intent(inout) :: x
142 integer,
intent(in) :: n
143 type(
coef_t),
intent(inout) :: coef
145 type(
gs_t),
intent(inout) :: gs_h
146 real(kind=
rp) :: lam, b, a, rn
147 real(kind=
rp) :: boost = 1.1_rp
148 real(kind=
rp) :: lam_factor = 30.0_rp
149 real(kind=
rp) :: wtw, dtw, dtd
150 integer,
allocatable :: fixed_seed(:), saved_seed(:)
151 integer :: i, rnd_n, its
155 warm = this%warm_start_eigs .and. this%eigs_computed .and. &
157 associate(w => this%w, d => this%d, r => this%r)
160 its = this%power_its_refresh
161 call copy(d, this%ev, n)
166 call random_seed(
size = rnd_n)
167 allocate(saved_seed(rnd_n))
168 allocate(fixed_seed(rnd_n))
170 call random_seed(get = saved_seed)
171 call random_seed(put = fixed_seed)
174 call random_number(rn)
179 call random_seed(put = saved_seed)
181 call gs_h%op(d, n, gs_op_add)
182 call bc_projector%apply(d, n)
187 call ax%compute(w, d, coef, x%msh, x%Xh)
188 call gs_h%op(w, n, gs_op_add)
189 call bc_projector%apply(w, n)
190 if (
associated(this%schwarz))
then
191 call this%schwarz%compute(r, w)
194 call this%M%solve(r, w, n)
198 wtw =
glsc3(w, coef%mult, w, n)
199 call cmult2(d, w, 1.0_rp/sqrt(wtw), n)
200 call bc_projector%apply(d, n)
203 call ax%compute(w, d, coef, x%msh, x%Xh)
204 call gs_h%op(w, n, gs_op_add)
205 call bc_projector%apply(w, n)
206 if (
associated(this%schwarz))
then
207 call this%schwarz%compute(r, w)
210 call this%M%solve(r, w, n)
214 dtw =
glsc3(d, coef%mult, w, n)
215 dtd =
glsc3(d, coef%mult, d, n)
219 this%tha = (b+a)/2.0_rp
220 this%dlt = (b-a)/2.0_rp
222 if (this%warm_start_eigs)
then
223 if (.not.
allocated(this%ev))
then
224 allocate(this%ev(
size(this%d)))
226 call copy(this%ev, d, n)
228 this%eigs_computed = .true.
230 this%recompute_eigs = .false.
236 function cheby_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
238 class(
cheby_t),
intent(inout) :: this
239 class(ax_t),
intent(in) :: ax
240 type(field_t),
intent(inout) :: x
241 integer,
intent(in) :: n
242 real(kind=rp),
dimension(n),
intent(in) :: f
243 type(coef_t),
intent(inout) :: coef
244 class(scalar_bc_projector_t),
intent(inout) :: bc_projector
245 type(gs_t),
intent(inout) :: gs_h
246 type(ksp_monitor_t) :: ksp_results
247 integer,
optional,
intent(in) :: niter
248 integer :: iter, max_iter
249 real(kind=rp) :: a, b, rtr, rnorm, norm_fac
251 if (this%recompute_eigs)
then
252 call cheby_power(this, ax, x, n, coef, bc_projector, gs_h)
255 if (
present(niter))
then
258 max_iter = this%max_iter
260 norm_fac = 1.0_rp / sqrt(coef%volume)
262 associate( w => this%w, r => this%r, d => this%d)
265 call ax%compute(w, x%x, coef, x%msh, x%Xh)
266 call gs_h%op(w, n, gs_op_add)
267 call bc_projector%apply(w, n)
270 rtr = glsc3(r, coef%mult, r, n)
271 rnorm = sqrt(rtr) * norm_fac
272 ksp_results%res_start = rnorm
273 ksp_results%res_final = rnorm
277 call this%M%solve(w, r, n)
279 a = 2.0_rp / this%tha
280 call add2s2(x%x, d, a, n)
283 do iter = 2, max_iter
286 call ax%compute(w, x%x, coef, x%msh, x%Xh)
287 call gs_h%op(w, n, gs_op_add)
288 call bc_projector%apply(w, n)
291 call this%M%solve(w, r, n)
293 if (iter .eq. 2)
then
294 b = 0.5_rp * (this%dlt * a)**2
296 b = (this%dlt * a / 2.0_rp)**2
298 a = 1.0_rp/(this%tha - b/a)
299 call add2s1(d, w, b, n)
301 call add2s2(x%x, d, a, n)
306 call ax%compute(w, x%x, coef, x%msh, x%Xh)
307 call gs_h%op(w, n, gs_op_add)
308 call bc_projector%apply(w, n)
310 rtr = glsc3(r, coef%mult, r, n)
311 rnorm = sqrt(rtr) * norm_fac
312 ksp_results%res_final = rnorm
313 ksp_results%iter = iter
314 ksp_results%converged = this%is_converged(iter, rnorm)
319 function cheby_impl(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
321 class(
cheby_t),
intent(inout) :: this
322 class(ax_t),
intent(in) :: ax
323 type(field_t),
intent(inout) :: x
324 integer,
intent(in) :: n
325 real(kind=rp),
dimension(n),
intent(in) :: f
326 type(coef_t),
intent(inout) :: coef
327 class(scalar_bc_projector_t),
intent(inout) :: bc_projector
328 type(gs_t),
intent(inout) :: gs_h
329 type(ksp_monitor_t) :: ksp_results
330 integer,
optional,
intent(in) :: niter
331 integer :: iter, max_iter, i
332 real(kind=rp) :: a, b, rtr, rnorm, norm_fac
333 real(kind=rp) :: rhok, rhokp1, sig1, tmp1, tmp2, inv_tha
335 if (this%recompute_eigs)
then
336 call cheby_power(this, ax, x, n, coef, bc_projector, gs_h)
339 if (
present(niter))
then
342 max_iter = this%max_iter
344 norm_fac = 1.0_rp / sqrt(coef%volume)
346 associate( w => this%w, r => this%r, d => this%d)
348 if (.not.this%zero_initial_guess)
then
349 call ax%compute(w, x%x, coef, x%msh, x%Xh)
350 call gs_h%op(w, n, gs_op_add)
351 call bc_projector%apply(w, n)
352 call sub3(r, f, w, n)
355 this%zero_initial_guess = .false.
359 if (
associated(this%schwarz))
then
360 call this%schwarz%compute(d, r)
362 call this%M%solve(d, r, n)
365 inv_tha = 1.0_rp / this%tha
372 d(i) = inv_tha * d(i)
373 x%x(i,1,1,1) = x%x(i,1,1,1) + d(i)
377 sig1 = this%tha / this%dlt
381 do iter = 2, max_iter
382 rhokp1 = 1.0_rp / (2.0_rp * sig1 - rhok)
384 tmp2 = 2.0_rp * rhokp1 / this%dlt
387 call ax%compute(w, x%x, coef, x%msh, x%Xh)
388 call gs_h%op(w, n, gs_op_add)
389 call bc_projector%apply(w, n)
390 call sub3(r, f, w, n)
392 if (
associated(this%schwarz))
then
393 call this%schwarz%compute(w, r)
395 call this%M%solve(w, r, n)
403 d(i) = tmp1 * d(i) + tmp2 * w(i)
404 x%x(i,1,1,1) = x%x(i,1,1,1) + d(i)
414 n, coef, bc_projector, gs_h, niter)
result(ksp_results)
415 class(
cheby_t),
intent(inout) :: this
416 class(ax_t),
intent(in) :: ax
417 type(field_t),
intent(inout) :: x
418 type(field_t),
intent(inout) :: y
419 type(field_t),
intent(inout) :: z
420 integer,
intent(in) :: n
421 real(kind=rp),
dimension(n),
intent(in) :: fx
422 real(kind=rp),
dimension(n),
intent(in) :: fy
423 real(kind=rp),
dimension(n),
intent(in) :: fz
424 type(coef_t),
intent(inout) :: coef
425 class(vector_bc_projector_t),
intent(inout) :: bc_projector
426 type(gs_t),
intent(inout) :: gs_h
427 type(ksp_monitor_t),
dimension(3) :: ksp_results
428 integer,
optional,
intent(in) :: niter
429 type(scalar_bc_projector_t),
pointer :: bc_x, bc_y, bc_z
431 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
432 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
433 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
434 ksp_results(3) = this%solve(ax, z, fz, n, coef, bc_z, gs_h, niter)
__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.
Chebyshev preconditioner.
type(ksp_monitor_t) function cheby_solve(this, ax, x, f, n, coef, bc_projector, gs_h, niter)
A chebyshev preconditioner.
subroutine cheby_free(this)
type(ksp_monitor_t) function cheby_impl(this, ax, x, f, n, coef, bc_projector, gs_h, niter)
A chebyshev preconditioner.
subroutine cheby_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a standard solver.
type(ksp_monitor_t) function, dimension(3) cheby_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, bc_projector, gs_h, niter)
Standard Chebyshev coupled solve.
subroutine cheby_power(this, ax, x, n, coef, bc_projector, gs_h)
Implements the base abstract type for Krylov solvers plus helper types.
subroutine, public cmult(a, c, n)
Multiplication by constant c .
subroutine, public cmult2(a, b, c, n)
Multiplication by constant c .
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
subroutine, public add2s1(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on first argument)
real(kind=rp) function, public glsc2(a, b, n)
Weighted inner product .
subroutine, public rone(a, n)
Set all elements to one.
subroutine, public sub3(a, b, c, n)
Vector subtraction .
subroutine, public add2(a, b, n)
Vector addition .
subroutine, public copy(a, b, n)
Copy a vector .
subroutine, public rzero(a, n)
Zero a real vector.
subroutine, public sub2(a, b, n)
Vector substraction .
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
integer, parameter, public rp
Global precision used in computations.
subroutine, public profiler_start_region(name, region_id)
Started a named (name) profiler region.
subroutine, public profiler_end_region(name, region_id)
End the most recently started profiler region.
Implements scalar_projector_t.
Overlapping schwarz solves.
Defines a function space.
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 .
Defines a Chebyshev preconditioner.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Type for storing initial and final residuals in a Krylov solver.
Base abstract type for a canonical Krylov method, solving .
Defines a canonical Krylov preconditioner.
Projector for scalar boundary conditions.
The function space for the SEM solution fields.
Abstract type for resolving vector boundary conditions.