164 function pipecg_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
166 class(
pipecg_t),
intent(inout) :: this
167 class(
ax_t),
intent(in) :: ax
168 type(
field_t),
intent(inout) :: x
169 integer,
intent(in) :: n
170 real(kind=
rp),
dimension(n),
intent(in) :: f
171 type(
coef_t),
intent(inout) :: coef
173 type(
gs_t),
intent(inout) :: gs_h
175 integer,
optional,
intent(in) :: niter
176 integer :: iter, max_iter, i, j, k, ierr, p_cur, p_prev, u_prev
177 real(kind=
rp) :: rnorm, rtr, reduction(3), norm_fac
179 real(kind=
rp) :: gamma1, gamma2, delta
181 type(mpi_request) :: request
182 type(mpi_status) :: status
184 if (
present(niter))
then
187 max_iter = this%max_iter
189 norm_fac = 1.0_rp / sqrt(coef%volume)
191 associate(p => this%p, q => this%q, r => this%r, s => this%s, &
192 u => this%u, w => this%w, z => this%z, mi => this%mi, ni => this%ni)
199 x%x(i,1,1,1) = 0.0_rp
207 call this%M%solve(u(1,u_prev), r, n)
208 call ax%compute(w, u(1,u_prev), coef, x%msh, x%Xh)
209 call gs_h%op(w, n, gs_op_add)
210 call bc_projector%apply(w, n)
212 rtr =
glsc3(r, coef%mult, r, n)
213 rnorm = sqrt(rtr)*norm_fac
214 ksp_results%res_start = rnorm
215 ksp_results%res_final = rnorm
218 if(
abscmp(rnorm, 0.0_rp))
then
219 ksp_results%converged = .true.
229 tmp1 = tmp1 + r(i) * coef%mult(i,1,1,1) * u(i,u_prev)
230 tmp2 = tmp2 + w(i) * coef%mult(i,1,1,1) * u(i,u_prev)
231 tmp3 = tmp3 + r(i) * coef%mult(i,1,1,1) * r(i)
238 call this%monitor_start(
'PipeCG')
239 do iter = 1, max_iter
240 call mpi_iallreduce(mpi_in_place, reduction, 3, &
243 call this%M%solve(mi, w, n)
244 call ax%compute(ni, mi, coef, x%msh, x%Xh)
245 call gs_h%op(ni, n, gs_op_add)
246 call bc_projector%apply(ni, n)
248 call mpi_wait(request, status, ierr)
250 gamma1 = reduction(1)
254 rnorm = sqrt(rtr)*norm_fac
255 call this%monitor_iter(iter, rnorm)
256 if (rnorm .lt. this%abs_tol)
exit
258 if (iter .gt. 1)
then
259 beta(p_cur) = gamma1 / gamma2
260 alpha(p_cur) = gamma1 / (delta - (beta(p_cur) * gamma1/alpha(p_prev)))
263 alpha(p_cur) = gamma1/delta
274 z(i+k) = beta(p_cur) * z(i+k) + ni(i+k)
275 q(i+k) = beta(p_cur) * q(i+k) + mi(i+k)
276 s(i+k) = beta(p_cur) * s(i+k) + w(i+k)
277 r(i+k) = r(i+k) - alpha(p_cur) * s(i+k)
278 u(i+k,p_cur) = u(i+k,u_prev) - alpha(p_cur) * q(i+k)
279 w(i+k) = w(i+k) - alpha(p_cur) * z(i+k)
280 tmp1 = tmp1 + r(i+k) * coef%mult(i+k,1,1,1) * u(i+k,p_cur)
281 tmp2 = tmp2 + w(i+k) * coef%mult(i+k,1,1,1) * u(i+k,p_cur)
282 tmp3 = tmp3 + r(i+k) * coef%mult(i+k,1,1,1) * r(i+k)
286 z(i+k) = beta(p_cur) * z(i+k) + ni(i+k)
287 q(i+k) = beta(p_cur) * q(i+k) + mi(i+k)
288 s(i+k) = beta(p_cur) * s(i+k) + w(i+k)
289 r(i+k) = r(i+k) - alpha(p_cur) * s(i+k)
290 u(i+k,p_cur) = u(i+k,u_prev) - alpha(p_cur) * q(i+k)
291 w(i+k) = w(i+k) - alpha(p_cur) * z(i+k)
292 tmp1 = tmp1 + r(i+k) * coef%mult(i+k,1,1,1) * u(i+k,p_cur)
293 tmp2 = tmp2 + w(i+k) * coef%mult(i+k,1,1,1) * u(i+k,p_cur)
294 tmp3 = tmp3 + r(i+k) * coef%mult(i+k,1,1,1) * r(i+k)
315 p(i+k) = beta(j) * p(i+k) + u(i+k,p_prev)
316 x_plus(k) = x_plus(k) + alpha(j) * p(i+k)
322 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
332 p(i+k) = beta(j) * p(i+k) + u(i+k,p_prev)
333 x_plus(k) = x_plus(k) + alpha(j) * p(i+k)
338 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
346 alpha(1) = alpha(p_cur)
347 beta(1) = beta(p_cur)
356 if ( p_cur .ne. 1)
then
368 p(i+k) = beta(j) * p(i+k) + u(i+k,p_prev)
369 x_plus(k) = x_plus(k) + alpha(j) * p(i+k)
375 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
385 p(i+k) = beta(j) * p(i+k) + u(i+k,p_prev)
386 x_plus(k) = x_plus(k) + alpha(j) * p(i+k)
391 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
398 call this%monitor_stop()
399 ksp_results%res_final = rnorm
400 ksp_results%iter = iter
401 ksp_results%converged = this%is_converged(iter, rnorm)
409 n, coef, bc_projector, gs_h, niter)
result(ksp_results)
410 class(
pipecg_t),
intent(inout) :: this
411 class(ax_t),
intent(in) :: ax
412 type(field_t),
intent(inout) :: x
413 type(field_t),
intent(inout) :: y
414 type(field_t),
intent(inout) :: z
415 integer,
intent(in) :: n
416 real(kind=rp),
dimension(n),
intent(in) :: fx
417 real(kind=rp),
dimension(n),
intent(in) :: fy
418 real(kind=rp),
dimension(n),
intent(in) :: fz
419 type(coef_t),
intent(inout) :: coef
420 class(vector_bc_projector_t),
intent(inout) :: bc_projector
421 type(gs_t),
intent(inout) :: gs_h
422 type(ksp_monitor_t),
dimension(3) :: ksp_results
423 integer,
optional,
intent(in) :: niter
424 type(scalar_bc_projector_t),
pointer :: bc_x, bc_y, bc_z
426 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
427 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
428 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
429 ksp_results(3) = this%solve(ax, z, fz, n, coef, bc_z, gs_h, niter)