94 subroutine bicgstab_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
95 class(
bicgstab_t),
target,
intent(inout) :: this
96 class(
pc_t),
optional,
intent(in),
target :: M
97 integer,
intent(in) :: n
98 integer,
intent(in) :: max_iter
99 real(kind=
rp),
optional,
intent(in) :: rel_tol
100 real(kind=
rp),
optional,
intent(in) :: abs_tol
101 logical,
optional,
intent(in) :: monitor
107 allocate(this%p_hat(n))
110 allocate(this%s_hat(n))
117 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
118 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
119 else if (
present(rel_tol) .and.
present(abs_tol))
then
120 call this%ksp_init(max_iter, rel_tol, abs_tol)
121 else if (
present(monitor) .and.
present(abs_tol))
then
122 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
123 else if (
present(rel_tol) .and.
present(monitor))
then
124 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
125 else if (
present(rel_tol))
then
126 call this%ksp_init(max_iter, rel_tol = rel_tol)
127 else if (
present(abs_tol))
then
128 call this%ksp_init(max_iter, abs_tol = abs_tol)
129 else if (
present(monitor))
then
130 call this%ksp_init(max_iter, monitor = monitor)
132 call this%ksp_init(max_iter)
192 class(
ax_t),
intent(in) :: ax
193 type(
field_t),
intent(inout) :: x
194 integer,
intent(in) :: n
195 real(kind=
rp),
dimension(n),
intent(in) :: f
196 type(
coef_t),
intent(inout) :: coef
198 type(
gs_t),
intent(inout) :: gs_h
200 integer,
optional,
intent(in) :: niter
201 integer :: iter, max_iter, i, ierr
202 real(kind=
rp) :: rnorm, rtr, norm_fac, gamma
203 real(kind=
rp) :: r_norm, s_norm, shadow_norm, t_norm, v_norm
205 real(kind=
rp) :: sts, ftv, vtv, stt, ttt
206 real(kind=
rp) :: beta, alpha, omega, rho_1, rho_2
208 real(kind=
xp) :: res_sum
210 if (
present(niter))
then
213 max_iter = this%max_iter
215 norm_fac = 1.0_rp / sqrt(coef%volume)
217 associate(r => this%r, t => this%t, s => this%s, v => this%v, &
218 p => this%p, s_hat => this%s_hat, p_hat => this%p_hat)
223 x%x(i,1,1,1) = 0.0_rp
225 res_sum = res_sum + (r(i) * coef%mult(i,1,1,1) * r(i))
229 call mpi_allreduce(mpi_in_place, res_sum, 1, &
237 rnorm = r_norm * norm_fac
238 gamma = rnorm * this%rel_tol
239 ksp_results%res_start = rnorm
240 ksp_results%res_final = rnorm
246 if (r_norm .le. 0.0_rp .or. rnorm .lt. this%abs_tol .or. &
247 rnorm .lt. gamma)
then
248 ksp_results%converged = .true.
252 call this%monitor_start(
'BiCGStab')
253 do iter = 1, max_iter
255 rho_1 =
glsc3(f, coef%mult, r, n)
264 if (iter .eq. 1)
then
267 beta = (rho_1 / rho_2) * (alpha / omega)
268 if (.not. ieee_is_finite(beta))
then
269 call neko_error(
'BiCGStab failure: non-finite beta')
271 call p_update(p, r, v, beta, omega, n)
274 call this%M%solve(p_hat, p, n)
275 call ax%compute(v, p_hat, coef, x%msh, x%Xh)
276 call gs_h%op(v, n, gs_op_add)
277 call bc_projector%apply(v, n)
285 v_norm,
'alpha denominator')
287 if (.not. ieee_is_finite(alpha))
then
288 call neko_error(
'BiCGStab failure: non-finite alpha')
294 s(i) = r(i) - alpha * v(i)
295 res_sum = res_sum + s(i) * coef%mult(i,1,1,1) * s(i)
299 call mpi_allreduce(mpi_in_place, res_sum, 1, &
304 rnorm = s_norm * norm_fac
305 if (rnorm .lt. this%abs_tol .or. rnorm .lt. gamma)
then
306 call add2s2(x%x, p_hat, alpha, n)
307 call this%monitor_iter(iter, rnorm)
311 call this%M%solve(s_hat, s, n)
312 call ax%compute(t, s_hat, coef, x%msh, x%Xh)
313 call gs_h%op(t, n, gs_op_add)
314 call bc_projector%apply(t, n)
318 if (t_norm .le. 0.0_rp)
then
319 call neko_error(
'BiCGStab breakdown: zero omega denominator')
321 if (.not. ieee_is_finite(stt))
then
322 call neko_error(
'BiCGStab failure: non-finite omega numerator')
325 if (.not. ieee_is_finite(omega))
then
326 call neko_error(
'BiCGStab failure: non-finite omega')
332 x%x(i,1,1,1) = x%x(i,1,1,1) + alpha * p_hat(i) + omega * s_hat(i)
333 r(i) = s(i) - omega * t(i)
334 res_sum = res_sum + r(i) * coef%mult(i,1,1,1) * r(i)
338 call mpi_allreduce(mpi_in_place, res_sum, 1, &
343 rnorm = r_norm * norm_fac
344 call this%monitor_iter(iter, rnorm)
345 if (rnorm .lt. this%abs_tol .or. rnorm .lt. gamma)
then
358 call this%monitor_stop()
359 ksp_results%res_final = rnorm
360 ksp_results%iter = iter
361 ksp_results%converged = this%is_converged(iter, rnorm)
404 integer,
intent(in) :: n
405 real(kind=rp),
intent(out) :: product
406 real(kind=rp),
intent(out) :: norm_squared
407 real(kind=rp),
dimension(n),
intent(in) :: a
408 real(kind=rp),
dimension(n),
intent(in) :: b
409 real(kind=rp),
dimension(n),
intent(in) :: mult
410 real(kind=xp) :: product_sum, norm_sum
411 real(kind=xp) :: reductions(2)
418 product_sum = product_sum + a(i) * mult(i) * b(i)
419 norm_sum = norm_sum + b(i) * mult(i) * b(i)
423 reductions(1) = product_sum
424 reductions(2) = norm_sum
425 call mpi_allreduce(mpi_in_place, reductions, 2, mpi_extra_precision, &
426 mpi_sum, neko_comm, ierr)
427 product = reductions(1)
428 norm_squared = reductions(2)
469 n, coef, bc_projector, gs_h, niter)
result(ksp_results)
471 class(ax_t),
intent(in) :: ax
472 type(field_t),
intent(inout) :: x
473 type(field_t),
intent(inout) :: y
474 type(field_t),
intent(inout) :: z
475 integer,
intent(in) :: n
476 real(kind=rp),
dimension(n),
intent(in) :: fx
477 real(kind=rp),
dimension(n),
intent(in) :: fy
478 real(kind=rp),
dimension(n),
intent(in) :: fz
479 type(coef_t),
intent(inout) :: coef
480 class(vector_bc_projector_t),
intent(inout) :: bc_projector
481 type(gs_t),
intent(inout) :: gs_h
482 type(ksp_monitor_t),
dimension(3) :: ksp_results
483 integer,
optional,
intent(in) :: niter
484 type(scalar_bc_projector_t),
pointer :: bc_x, bc_y, bc_z
486 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
487 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
488 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
489 ksp_results(3) = this%solve(ax, z, fz, n, coef, bc_z, gs_h, niter)
type(ksp_monitor_t) function, dimension(3) bicgstab_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, bc_projector, gs_h, niter)
Solve three independent systems with the CPU BiCGStab method.