95 subroutine gmres_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
96 class(
gmres_t),
target,
intent(inout) :: this
97 integer,
intent(in) :: n
98 integer,
intent(in) :: max_iter
99 class(
pc_t),
optional,
intent(in),
target :: M
100 real(kind=
rp),
optional,
intent(in) :: rel_tol
101 real(kind=
rp),
optional,
intent(in) :: abs_tol
102 logical,
optional,
intent(in) :: monitor
111 allocate(this%c(this%lgmres))
112 allocate(this%s(this%lgmres))
113 allocate(this%gam(this%lgmres + 1))
115 allocate(this%h(this%lgmres, this%lgmres))
119 allocate(this%hp(this%lgmres, nthrds))
121 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
122 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
123 else if (
present(rel_tol) .and.
present(abs_tol))
then
124 call this%ksp_init(max_iter, rel_tol, abs_tol)
125 else if (
present(monitor) .and.
present(abs_tol))
then
126 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
127 else if (
present(rel_tol) .and.
present(monitor))
then
128 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
129 else if (
present(rel_tol))
then
130 call this%ksp_init(max_iter, rel_tol = rel_tol)
131 else if (
present(abs_tol))
then
132 call this%ksp_init(max_iter, abs_tol = abs_tol)
133 else if (
present(monitor))
then
134 call this%ksp_init(max_iter, monitor = monitor)
136 call this%ksp_init(max_iter)
180 function gmres_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
182 class(
gmres_t),
intent(inout) :: this
183 class(
ax_t),
intent(in) :: ax
184 type(
field_t),
intent(inout) :: x
185 integer,
intent(in) :: n
186 real(kind=
rp),
dimension(n),
intent(in) :: f
187 type(
coef_t),
intent(inout) :: coef
189 type(
gs_t),
intent(inout) :: gs_h
191 integer,
optional,
intent(in) :: niter
192 integer :: iter, max_iter
193 integer :: i, j, k, l, ierr, tid, nthrds
195 real(kind=
xp) :: hl(this%lgmres)
196 real(kind=
xp) :: alpha, lr, alpha2, norm_fac, tmp, acc
197 real(kind=
rp) :: temp, rnorm
199 integer :: temp_indices(4)
205 if (
present(niter))
then
208 max_iter = this%max_iter
217 n, this%lgmres, .false.)
219 n, this%lgmres, .false.)
221 associate(w => this%w, c => this%c, r => this%r, z => this%z%x, &
222 h => this%h, v => this%v%x, s => this%s, gam => this%gam, &
225 norm_fac = 1.0_rp / sqrt(coef%volume)
231 call this%monitor_start(
'GMRES')
232 do while (.not. conv .and. iter .lt. max_iter)
234 if (iter .eq. 0)
then
238 call ax%compute(w, x%x, coef, x%msh, x%Xh)
239 call gs_h%op(w, n, gs_op_add)
240 call bc_projector%apply(w, n)
244 gam(1) = sqrt(
glsc3(r, r, coef%mult, n))
245 if (iter .eq. 0)
then
246 ksp_results%res_start = gam(1) * norm_fac
249 if (
abscmp(gam(1), 0.0_xp))
exit
252 temp = 1.0_rp / gam(1)
253 call cmult2(v(1,1), r, temp, n)
254 do j = 1, this%lgmres
257 call this%M%solve(z(1,j), v(1,j), n)
259 call ax%compute(w, z(1,j), coef, x%msh, x%Xh)
260 call gs_h%op(w, n, gs_op_add)
261 call bc_projector%apply(w, n)
281 w(i+k) * v(i+k,l) * coef%mult(i+k,1,1,1)
289 w(i+k) * v(i+k,l) * coef%mult(i+k,1,1,1)
303 hp(l,1) = hp(l,1) + hp(l,k)
306 call mpi_allreduce(mpi_in_place, hp(1,1), j, &
328 w_plus(k) = w_plus(k) - h(l,j) * v(i+k,l)
333 w(i+k) = w(i+k) + w_plus(k)
334 alpha2 = alpha2 + w(i+k)**2 * coef%mult(i+k,1,1,1)
340 tmp = tmp - h(l,j) * v(i+k,l)
342 w(i+k) = w(i+k) + tmp
343 alpha2 = alpha2 + w(i+k)**2 * coef%mult(i+k,1,1,1)
348 call mpi_allreduce(mpi_in_place, alpha2, 1, &
353 h(i,j) = c(i)*temp + s(i) * h(i+1,j)
354 h(i+1,j) = -s(i)*temp + c(i) * h(i+1,j)
358 if (
abscmp(alpha, 0.0_xp))
then
363 lr = sqrt(h(j,j) * h(j,j) + alpha2)
368 gam(j+1) = -s(j) * gam(j)
369 gam(j) = c(j) * gam(j)
370 rnorm = abs(gam(j+1)) * norm_fac
371 call this%monitor_iter(iter, rnorm)
372 if (rnorm .lt. this%abs_tol)
then
377 if (iter + 1 .gt. max_iter)
exit
379 if (j .lt. this%lgmres)
then
380 temp = 1.0_rp / alpha
381 call cmult2(v(1,j+1), w, temp, n)
386 j = min(j, this%lgmres)
390 temp = temp - h(k,i) * c(i)
405 x_plus(k) = x_plus(k) + c(l) * z(i+k,l)
410 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
416 tmp = tmp + c(l) * z(i+k,l)
418 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + tmp
426 nullify(this%w, this%r, this%z, this%v)
428 call this%monitor_stop()
429 ksp_results%res_final = rnorm
430 ksp_results%iter = iter
431 ksp_results%converged = this%is_converged(iter, rnorm)
437 n, coef, bc_projector, gs_h, niter)
result(ksp_results)
438 class(
gmres_t),
intent(inout) :: this
439 class(ax_t),
intent(in) :: ax
440 type(field_t),
intent(inout) :: x
441 type(field_t),
intent(inout) :: y
442 type(field_t),
intent(inout) :: z
443 integer,
intent(in) :: n
444 real(kind=rp),
dimension(n),
intent(in) :: fx
445 real(kind=rp),
dimension(n),
intent(in) :: fy
446 real(kind=rp),
dimension(n),
intent(in) :: fz
447 type(coef_t),
intent(inout) :: coef
448 class(vector_bc_projector_t),
intent(inout) :: bc_projector
449 type(gs_t),
intent(inout) :: gs_h
450 type(ksp_monitor_t),
dimension(3) :: ksp_results
451 integer,
optional,
intent(in) :: niter
452 type(scalar_bc_projector_t),
pointer :: bc_x, bc_y, bc_z
454 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
455 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
456 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
457 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.