78 subroutine pipecg_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
79 class(
pipecg_t),
target,
intent(inout) :: this
80 integer,
intent(in) :: max_iter
81 class(
pc_t),
optional,
intent(in),
target :: M
82 integer,
intent(in) :: n
83 real(kind=
rp),
optional,
intent(in) :: rel_tol
84 real(kind=
rp),
optional,
intent(in) :: abs_tol
85 logical,
optional,
intent(in) :: monitor
102 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
103 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
104 else if (
present(rel_tol) .and.
present(abs_tol))
then
105 call this%ksp_init(max_iter, rel_tol, abs_tol)
106 else if (
present(monitor) .and.
present(abs_tol))
then
107 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
108 else if (
present(rel_tol) .and.
present(monitor))
then
109 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
110 else if (
present(rel_tol))
then
111 call this%ksp_init(max_iter, rel_tol = rel_tol)
112 else if (
present(abs_tol))
then
113 call this%ksp_init(max_iter, abs_tol = abs_tol)
114 else if (
present(monitor))
then
115 call this%ksp_init(max_iter, monitor = monitor)
117 call this%ksp_init(max_iter)
162 function pipecg_solve(this, Ax, x, f, n, coef, blst, gs_h, niter)
result(ksp_results)
163 class(
pipecg_t),
intent(inout) :: this
164 class(
ax_t),
intent(in) :: ax
165 type(
field_t),
intent(inout) :: x
166 integer,
intent(in) :: n
167 real(kind=
rp),
dimension(n),
intent(in) :: f
168 type(
coef_t),
intent(inout) :: coef
170 type(
gs_t),
intent(inout) :: gs_h
172 integer,
optional,
intent(in) :: niter
173 integer :: iter, max_iter, i, j, k, ierr, p_cur, p_prev, u_prev
174 real(kind=
rp) :: rnorm, rtr, reduction(3), norm_fac
176 real(kind=
rp) :: gamma1, gamma2, delta
178 type(mpi_request) :: request
179 type(mpi_status) :: status
181 if (
present(niter))
then
184 max_iter = this%max_iter
186 norm_fac = 1.0_rp / sqrt(coef%volume)
188 associate(p => this%p, q => this%q, r => this%r, s => this%s, &
189 u => this%u, w => this%w, z => this%z, mi => this%mi, ni => this%ni)
200 call this%M%solve(u(1,u_prev), r, n)
201 call ax%compute(w, u(1,u_prev), coef, x%msh, x%Xh)
202 call gs_h%op(w, n, gs_op_add)
203 call blst%apply(w, n)
205 rtr =
glsc3(r, coef%mult, r, n)
206 rnorm = sqrt(rtr)*norm_fac
207 ksp_results%res_start = rnorm
208 ksp_results%res_final = rnorm
211 if(
abscmp(rnorm, 0.0_rp))
then
212 ksp_results%converged = .true.
222 tmp1 = tmp1 + r(i) * coef%mult(i,1,1,1) * u(i,u_prev)
223 tmp2 = tmp2 + w(i) * coef%mult(i,1,1,1) * u(i,u_prev)
224 tmp3 = tmp3 + r(i) * coef%mult(i,1,1,1) * r(i)
231 call this%monitor_start(
'PipeCG')
232 do iter = 1, max_iter
233 call mpi_iallreduce(mpi_in_place, reduction, 3, &
236 call this%M%solve(mi, w, n)
237 call ax%compute(ni, mi, coef, x%msh, x%Xh)
238 call gs_h%op(ni, n, gs_op_add)
239 call blst%apply(ni, n)
241 call mpi_wait(request, status, ierr)
243 gamma1 = reduction(1)
247 rnorm = sqrt(rtr)*norm_fac
248 call this%monitor_iter(iter, rnorm)
249 if (rnorm .lt. this%abs_tol)
exit
251 if (iter .gt. 1)
then
252 beta(p_cur) = gamma1 / gamma2
253 alpha(p_cur) = gamma1 / (delta - (beta(p_cur) * gamma1/alpha(p_prev)))
256 alpha(p_cur) = gamma1/delta
265 z(i+k) = beta(p_cur) * z(i+k) + ni(i+k)
266 q(i+k) = beta(p_cur) * q(i+k) + mi(i+k)
267 s(i+k) = beta(p_cur) * s(i+k) + w(i+k)
268 r(i+k) = r(i+k) - alpha(p_cur) * s(i+k)
269 u(i+k,p_cur) = u(i+k,u_prev) - alpha(p_cur) * q(i+k)
270 w(i+k) = w(i+k) - alpha(p_cur) * z(i+k)
271 tmp1 = tmp1 + r(i+k) * coef%mult(i+k,1,1,1) * u(i+k,p_cur)
272 tmp2 = tmp2 + w(i+k) * coef%mult(i+k,1,1,1) * u(i+k,p_cur)
273 tmp3 = tmp3 + r(i+k) * coef%mult(i+k,1,1,1) * r(i+k)
290 p(i+k) = beta(j) * p(i+k) + u(i+k,p_prev)
291 x_plus(k) = x_plus(k) + alpha(j) * p(i+k)
296 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
303 alpha(1) = alpha(p_cur)
304 beta(1) = beta(p_cur)
313 if ( p_cur .ne. 1)
then
322 p(i+k) = beta(j) * p(i+k) + u(i+k,p_prev)
323 x_plus(k) = x_plus(k) + alpha(j) * p(i+k)
328 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
334 call this%monitor_stop()
335 ksp_results%res_final = rnorm
336 ksp_results%iter = iter
337 ksp_results%converged = this%is_converged(iter, rnorm)
345 n, coef, blstx, blsty, blstz, gs_h, niter)
result(ksp_results)
346 class(
pipecg_t),
intent(inout) :: this
347 class(ax_t),
intent(in) :: ax
348 type(field_t),
intent(inout) :: x
349 type(field_t),
intent(inout) :: y
350 type(field_t),
intent(inout) :: z
351 integer,
intent(in) :: n
352 real(kind=rp),
dimension(n),
intent(in) :: fx
353 real(kind=rp),
dimension(n),
intent(in) :: fy
354 real(kind=rp),
dimension(n),
intent(in) :: fz
355 type(coef_t),
intent(inout) :: coef
356 type(bc_list_t),
intent(inout) :: blstx
357 type(bc_list_t),
intent(inout) :: blsty
358 type(bc_list_t),
intent(inout) :: blstz
359 type(gs_t),
intent(inout) :: gs_h
360 type(ksp_monitor_t),
dimension(3) :: ksp_results
361 integer,
optional,
intent(in) :: niter
363 ksp_results(1) = this%solve(ax, x, fx, n, coef, blstx, gs_h, niter)
364 ksp_results(2) = this%solve(ax, y, fy, n, coef, blsty, gs_h, niter)
365 ksp_results(3) = this%solve(ax, z, fz, n, coef, blstz, gs_h, niter)
type(ksp_monitor_t) function, dimension(3) pipecg_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, blstx, blsty, blstz, gs_h, niter)
Pipelined PCG coupled solve.