93 subroutine bicgstab_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
94 class(
bicgstab_t),
target,
intent(inout) :: this
95 class(
pc_t),
optional,
intent(in),
target :: M
96 integer,
intent(in) :: n
97 integer,
intent(in) :: max_iter
98 real(kind=
rp),
optional,
intent(in) :: rel_tol
99 real(kind=
rp),
optional,
intent(in) :: abs_tol
100 logical,
optional,
intent(in) :: monitor
109 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
110 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
111 else if (
present(rel_tol) .and.
present(abs_tol))
then
112 call this%ksp_init(max_iter, rel_tol, abs_tol)
113 else if (
present(monitor) .and.
present(abs_tol))
then
114 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
115 else if (
present(rel_tol) .and.
present(monitor))
then
116 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
117 else if (
present(rel_tol))
then
118 call this%ksp_init(max_iter, rel_tol = rel_tol)
119 else if (
present(abs_tol))
then
120 call this%ksp_init(max_iter, abs_tol = abs_tol)
121 else if (
present(monitor))
then
122 call this%ksp_init(max_iter, monitor = monitor)
124 call this%ksp_init(max_iter)
156 class(
ax_t),
intent(in) :: ax
157 type(
field_t),
intent(inout) :: x
158 integer,
intent(in) :: n
159 real(kind=
rp),
dimension(n),
intent(in) :: f
160 type(
coef_t),
intent(inout) :: coef
162 type(
gs_t),
intent(inout) :: gs_h
164 integer,
optional,
intent(in) :: niter
165 integer :: iter, max_iter, i, ierr
166 real(kind=
rp) :: rnorm, rtr, norm_fac, gamma
167 real(kind=
rp) :: r_norm, s_norm, shadow_norm, t_norm, v_norm
169 real(kind=
rp) :: sts, ftv, vtv, stt, ttt
170 real(kind=
rp) :: beta, alpha, omega, rho_1, rho_2
172 real(kind=
xp) :: res_sum
173 integer :: temp_indices(6)
175 if (
present(niter))
then
178 max_iter = this%max_iter
180 norm_fac = 1.0_rp / sqrt(coef%volume)
189 associate(p => this%p, p_hat => this%p_hat, r => this%r, &
190 s_hat => this%s_hat, t => this%t, v => this%v)
195 x%x(i,1,1,1) = 0.0_rp
197 res_sum = res_sum + (r(i) * coef%mult(i,1,1,1) * r(i))
201 call mpi_allreduce(mpi_in_place, res_sum, 1, &
209 rnorm = r_norm * norm_fac
210 gamma = rnorm * this%rel_tol
211 ksp_results%res_start = rnorm
212 ksp_results%res_final = rnorm
218 if (r_norm .le. 0.0_rp .or. rnorm .lt. this%abs_tol .or. &
219 rnorm .lt. gamma)
then
220 ksp_results%converged = .true.
221 nullify(this%p, this%p_hat, this%r, this%s_hat, this%t, this%v)
226 call this%monitor_start(
'BiCGStab')
227 do iter = 1, max_iter
229 rho_1 =
glsc3(f, coef%mult, r, n)
238 if (iter .eq. 1)
then
241 beta = (rho_1 / rho_2) * (alpha / omega)
242 if (.not. ieee_is_finite(beta))
then
243 call neko_error(
'BiCGStab failure: non-finite beta')
245 call p_update(p, r, v, beta, omega, n)
248 call this%M%solve(p_hat, p, n)
249 call ax%compute(v, p_hat, coef, x%msh, x%Xh)
250 call gs_h%op(v, n, gs_op_add)
251 call bc_projector%apply(v, n)
259 v_norm,
'alpha denominator')
261 if (.not. ieee_is_finite(alpha))
then
262 call neko_error(
'BiCGStab failure: non-finite alpha')
270 r(i) = r(i) - alpha * v(i)
271 res_sum = res_sum + r(i) * coef%mult(i,1,1,1) * r(i)
275 call mpi_allreduce(mpi_in_place, res_sum, 1, &
280 rnorm = s_norm * norm_fac
281 if (rnorm .lt. this%abs_tol .or. rnorm .lt. gamma)
then
282 call add2s2(x%x, p_hat, alpha, n)
283 call this%monitor_iter(iter, rnorm)
287 call this%M%solve(s_hat, r, n)
288 call ax%compute(t, s_hat, coef, x%msh, x%Xh)
289 call gs_h%op(t, n, gs_op_add)
290 call bc_projector%apply(t, n)
294 if (t_norm .le. 0.0_rp)
then
295 call neko_error(
'BiCGStab breakdown: zero omega denominator')
297 if (.not. ieee_is_finite(stt))
then
298 call neko_error(
'BiCGStab failure: non-finite omega numerator')
301 if (.not. ieee_is_finite(omega))
then
302 call neko_error(
'BiCGStab failure: non-finite omega')
308 x%x(i,1,1,1) = x%x(i,1,1,1) + alpha * p_hat(i) + omega * s_hat(i)
309 r(i) = r(i) - omega * t(i)
310 res_sum = res_sum + r(i) * coef%mult(i,1,1,1) * r(i)
314 call mpi_allreduce(mpi_in_place, res_sum, 1, &
319 rnorm = r_norm * norm_fac
320 call this%monitor_iter(iter, rnorm)
321 if (rnorm .lt. this%abs_tol .or. rnorm .lt. gamma)
then
333 call this%monitor_stop()
334 ksp_results%res_final = rnorm
335 ksp_results%iter = iter
336 ksp_results%converged = this%is_converged(iter, rnorm)
338 nullify(this%p, this%p_hat, this%r, this%s_hat, this%t, this%v)
447 n, coef, bc_projector, gs_h, niter)
result(ksp_results)
449 class(ax_t),
intent(in) :: ax
450 type(field_t),
intent(inout) :: x
451 type(field_t),
intent(inout) :: y
452 type(field_t),
intent(inout) :: z
453 integer,
intent(in) :: n
454 real(kind=rp),
dimension(n),
intent(in) :: fx
455 real(kind=rp),
dimension(n),
intent(in) :: fy
456 real(kind=rp),
dimension(n),
intent(in) :: fz
457 type(coef_t),
intent(inout) :: coef
458 class(vector_bc_projector_t),
intent(inout) :: bc_projector
459 type(gs_t),
intent(inout) :: gs_h
460 type(ksp_monitor_t),
dimension(3) :: ksp_results
461 integer,
optional,
intent(in) :: niter
462 type(scalar_bc_projector_t),
pointer :: bc_x, bc_y, bc_z
464 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
465 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
466 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
467 ksp_results(3) = this%solve(ax, z, fz, n, coef, bc_z, gs_h, niter)