104 subroutine gmres_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
105 class(
gmres_t),
target,
intent(inout) :: this
106 integer,
intent(in) :: n
107 integer,
intent(in) :: max_iter
108 class(
pc_t),
optional,
intent(in),
target :: M
109 real(kind=
rp),
optional,
intent(in) :: rel_tol
110 real(kind=
rp),
optional,
intent(in) :: abs_tol
111 logical,
optional,
intent(in) :: monitor
120 allocate(this%c(this%lgmres))
121 allocate(this%s(this%lgmres))
122 allocate(this%gam(this%lgmres + 1))
124 allocate(this%h(this%lgmres, this%lgmres))
128 allocate(this%hp(this%lgmres, nthrds))
130 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
131 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
132 else if (
present(rel_tol) .and.
present(abs_tol))
then
133 call this%ksp_init(max_iter, rel_tol, abs_tol)
134 else if (
present(monitor) .and.
present(abs_tol))
then
135 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
136 else if (
present(rel_tol) .and.
present(monitor))
then
137 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
138 else if (
present(rel_tol))
then
139 call this%ksp_init(max_iter, rel_tol = rel_tol)
140 else if (
present(abs_tol))
then
141 call this%ksp_init(max_iter, abs_tol = abs_tol)
142 else if (
present(monitor))
then
143 call this%ksp_init(max_iter, monitor = monitor)
145 call this%ksp_init(max_iter)
211 function gmres_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
213 class(
gmres_t),
intent(inout) :: this
214 class(
ax_t),
intent(in) :: ax
215 type(
field_t),
intent(inout) :: x
216 integer,
intent(in) :: n
217 real(kind=
rp),
dimension(n),
intent(in) :: f
218 type(
coef_t),
intent(inout) :: coef
220 type(
gs_t),
intent(inout) :: gs_h
222 integer,
optional,
intent(in) :: niter
223 integer :: iter, max_iter
224 integer :: i, j, k, l, ierr, tid, nthrds
226 real(kind=
xp) :: hl(this%lgmres)
227 real(kind=
xp) :: alpha, lr, alpha2, norm_fac, tmp, acc
228 real(kind=
rp) :: temp, rnorm
230 integer :: temp_indices(4)
236 if (
present(niter))
then
239 max_iter = this%max_iter
248 n, this%lgmres, .false.)
250 n, this%lgmres, .false.)
252 associate(w => this%w, c => this%c, r => this%r, z => this%z%x, &
253 h => this%h, v => this%v%x, s => this%s, gam => this%gam, &
256 norm_fac = 1.0_rp / sqrt(coef%volume)
262 call this%monitor_start(
'GMRES')
263 do while (.not. conv .and. iter .lt. max_iter)
265 if (iter .eq. 0)
then
269 call ax%compute(w, x%x, coef, x%msh, x%Xh)
270 call gs_h%op(w, n, gs_op_add)
271 call bc_projector%apply(w, n)
275 gam(1) = sqrt(
glsc3(r, r, coef%mult, n))
276 if (iter .eq. 0)
then
277 ksp_results%res_start = gam(1) * norm_fac
280 if (
abscmp(gam(1), 0.0_xp))
exit
283 temp = 1.0_rp / gam(1)
284 call cmult2(v(1,1), r, temp, n)
285 do j = 1, this%lgmres
288 call this%M%solve(z(1,j), v(1,j), n)
290 call ax%compute(w, z(1,j), coef, x%msh, x%Xh)
291 call gs_h%op(w, n, gs_op_add)
292 call bc_projector%apply(w, n)
312 w(i+k) * v(i+k,l) * coef%mult(i+k,1,1,1)
320 w(i+k) * v(i+k,l) * coef%mult(i+k,1,1,1)
334 hp(l,1) = hp(l,1) + hp(l,k)
337 call mpi_allreduce(mpi_in_place, hp(1,1), j, &
359 w_plus(k) = w_plus(k) - h(l,j) * v(i+k,l)
364 w(i+k) = w(i+k) + w_plus(k)
365 alpha2 = alpha2 + w(i+k)**2 * coef%mult(i+k,1,1,1)
371 tmp = tmp - h(l,j) * v(i+k,l)
373 w(i+k) = w(i+k) + tmp
374 alpha2 = alpha2 + w(i+k)**2 * coef%mult(i+k,1,1,1)
379 call mpi_allreduce(mpi_in_place, alpha2, 1, &
384 h(i,j) = c(i)*temp + s(i) * h(i+1,j)
385 h(i+1,j) = -s(i)*temp + c(i) * h(i+1,j)
389 if (
abscmp(alpha, 0.0_xp))
then
394 lr = sqrt(h(j,j) * h(j,j) + alpha2)
399 gam(j+1) = -s(j) * gam(j)
400 gam(j) = c(j) * gam(j)
401 rnorm = abs(gam(j+1)) * norm_fac
402 call this%monitor_iter(iter, rnorm)
403 if (rnorm .lt. this%abs_tol)
then
408 if (iter + 1 .gt. max_iter)
exit
410 if (j .lt. this%lgmres)
then
411 temp = 1.0_rp / alpha
412 call cmult2(v(1,j+1), w, temp, n)
417 j = min(j, this%lgmres)
421 temp = temp - h(k,i) * c(i)
436 x_plus(k) = x_plus(k) + c(l) * z(i+k,l)
441 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
447 tmp = tmp + c(l) * z(i+k,l)
449 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + tmp
457 nullify(this%w, this%r, this%z, this%v)
459 call this%monitor_stop()
460 ksp_results%res_final = rnorm
461 ksp_results%iter = iter
462 ksp_results%converged = this%is_converged(iter, rnorm)
468 n, coef, bc_projector, gs_h, niter)
result(ksp_results)
469 class(
gmres_t),
intent(inout) :: this
470 class(ax_t),
intent(in) :: ax
471 type(field_t),
intent(inout) :: x
472 type(field_t),
intent(inout) :: y
473 type(field_t),
intent(inout) :: z
474 integer,
intent(in) :: n
475 real(kind=rp),
dimension(n),
intent(in) :: fx
476 real(kind=rp),
dimension(n),
intent(in) :: fy
477 real(kind=rp),
dimension(n),
intent(in) :: fz
478 type(coef_t),
intent(inout) :: coef
479 class(vector_bc_projector_t),
intent(inout) :: bc_projector
480 type(gs_t),
intent(inout) :: gs_h
481 type(ksp_monitor_t),
dimension(3) :: ksp_results
482 integer,
optional,
intent(in) :: niter
483 type(scalar_bc_projector_t),
pointer :: bc_x, bc_y, bc_z
485 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
486 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
487 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
488 ksp_results(3) = this%solve(ax, z, fz, n, coef, bc_z, gs_h, niter)
type(ksp_monitor_t) function, dimension(3) gmres_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, bc_projector, gs_h, niter)
Solve three independent systems with the standard GMRES method.