74 subroutine sx_gmres_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
75 class(
sx_gmres_t),
target,
intent(inout) :: this
76 integer,
intent(in) :: n
77 integer,
intent(in) :: max_iter
78 class(
pc_t),
optional,
intent(in),
target :: M
79 real(kind=
rp),
optional,
intent(in) :: rel_tol
80 real(kind=
rp),
optional,
intent(in) :: abs_tol
81 logical,
optional,
intent(in) :: monitor
95 allocate(this%c(this%lgmres))
96 allocate(this%s(this%lgmres))
97 allocate(this%gam(this%lgmres + 1))
99 allocate(this%z(n,this%lgmres))
100 allocate(this%v(n,this%lgmres))
102 allocate(this%h(this%lgmres,this%lgmres))
105 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
106 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
107 else if (
present(rel_tol) .and.
present(abs_tol))
then
108 call this%ksp_init(max_iter, rel_tol, abs_tol)
109 else if (
present(monitor) .and.
present(abs_tol))
then
110 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
111 else if (
present(rel_tol) .and.
present(monitor))
then
112 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
113 else if (
present(rel_tol))
then
114 call this%ksp_init(max_iter, rel_tol = rel_tol)
115 else if (
present(abs_tol))
then
116 call this%ksp_init(max_iter, abs_tol = abs_tol)
117 else if (
present(monitor))
then
118 call this%ksp_init(max_iter, monitor = monitor)
120 call this%ksp_init(max_iter)
180 function sx_gmres_solve(this, Ax, x, f, n, coef, blst, gs_h, niter)
result(ksp_results)
182 class(
ax_t),
intent(in) :: ax
183 type(
field_t),
intent(inout) :: x
184 integer,
intent(in) :: n
185 real(kind=
rp),
dimension(n),
intent(in) :: f
186 type(
coef_t),
intent(inout) :: coef
188 type(
gs_t),
intent(inout) :: gs_h
190 integer,
optional,
intent(in) :: niter
191 integer :: iter, max_iter, glb_n
192 integer :: i, j, k, ierr
193 real(kind=
rp),
parameter :: one = 1.0
194 real(kind=
rp) :: rnorm
195 real(kind=
rp) :: alpha, temp, l
196 real(kind=
rp) :: ratio, div0, norm_fac
203 glb_n = n / x%msh%nelv * x%msh%glb_nelv
205 if (
present(niter))
then
208 max_iter = this%max_iter
211 call rone(this%ml, n)
212 call rone(this%mu, n)
213 norm_fac = one / sqrt(coef%volume)
215 call rzero(this%gam, this%lgmres + 1)
216 call rone(this%s, this%lgmres)
217 call rone(this%c, this%lgmres)
218 call rzero(this%h, this%lgmres * this%lgmres)
220 call this%monitor_start(
'GMRES')
221 do while (.not. conv .and. iter .lt. max_iter)
225 call col3(this%r,this%ml,f,n)
228 call copy (this%r,f,n)
229 call ax%compute(this%w, x%x, coef, x%msh, x%Xh)
230 call gs_h%op(this%w, n, gs_op_add)
231 call blst%apply(this%w, n)
232 call add2s2(this%r,this%w,-one,n)
233 call col2(this%r,this%ml,n)
235 this%gam(1) = sqrt(
glsc3(this%r, this%r, coef%mult, n))
237 div0 = this%gam(1) * norm_fac
238 ksp_results%res_start = div0
241 if (
abscmp(this%gam(1), 0.0_rp))
exit
244 temp = one / this%gam(1)
245 call cmult2(this%v(1,1), this%r, temp, n)
246 do j = 1, this%lgmres
248 call col3(this%w, this%mu, this%v(1,j), n)
251 call this%M%solve(this%z(1,j), this%w, n)
253 call ax%compute(this%w, this%z(1,j), coef, x%msh, x%Xh)
254 call gs_h%op(this%w, n, gs_op_add)
255 call blst%apply(this%w, n)
256 call col2(this%w, this%ml, n)
261 this%h(i,j) = this%h(i,j) + &
262 this%w(k) * this%v(k,i) * coef%mult(k,1,1,1)
267 call mpi_allreduce(this%h(1,j), this%wk1, j, &
269 call copy(this%h(1,j), this%wk1, j)
273 this%w(k) = this%w(k) - this%h(i,j) * this%v(k,i)
280 this%h(i ,j) = this%c(i)*temp + this%s(i)*this%h(i+1,j)
281 this%h(i+1,j) = -this%s(i)*temp + this%c(i)*this%h(i+1,j)
284 alpha = sqrt(
glsc3(this%w, this%w, coef%mult, n))
286 if(
abscmp(alpha, 0.0_rp))
then
290 l = sqrt(this%h(j,j) * this%h(j,j) + alpha**2)
292 this%c(j) = this%h(j,j) * temp
293 this%s(j) = alpha * temp
295 this%gam(j+1) = -this%s(j) * this%gam(j)
296 this%gam(j) = this%c(j) * this%gam(j)
298 rnorm = abs(this%gam(j+1)) * norm_fac
299 call this%monitor_iter(iter, rnorm)
301 if (rnorm .lt. this%abs_tol)
then
306 if (iter + 1 .gt. max_iter)
exit
308 if( j .lt. this%lgmres)
then
310 call cmult2(this%v(1,j+1), this%w, temp, n)
313 j = min(j, this%lgmres)
318 temp = temp - this%h(k,i) * this%c(i)
320 this%c(k) = temp / this%h(k,k)
325 x%x(k,1,1,1) = x%x(k,1,1,1) + this%c(i) * this%z(k,i)
329 call this%monitor_stop()
330 ksp_results%res_final = rnorm
331 ksp_results%iter = iter
332 ksp_results%converged = this%is_converged(iter, rnorm)
337 n, coef, blstx, blsty, blstz, gs_h, niter)
result(ksp_results)
339 class(
ax_t),
intent(in) :: ax
340 type(
field_t),
intent(inout) :: x
341 type(
field_t),
intent(inout) :: y
342 type(
field_t),
intent(inout) :: z
343 integer,
intent(in) :: n
344 real(kind=
rp),
dimension(n),
intent(in) :: fx
345 real(kind=
rp),
dimension(n),
intent(in) :: fy
346 real(kind=
rp),
dimension(n),
intent(in) :: fz
347 type(
coef_t),
intent(inout) :: coef
351 type(
gs_t),
intent(inout) :: gs_h
353 integer,
optional,
intent(in) :: niter
355 ksp_results(1) = this%solve(ax, x, fx, n, coef, blstx, gs_h, niter)
356 ksp_results(2) = this%solve(ax, y, fy, n, coef, blsty, gs_h, niter)
357 ksp_results(3) = this%solve(ax, z, fz, n, coef, blstz, gs_h, niter)
type(ksp_monitor_t) function, dimension(3) sx_gmres_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, blstx, blsty, blstz, gs_h, niter)
Standard GMRES coupled solve.