136 function cacg_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
138 class(
cacg_t),
intent(inout) :: this
139 class(
ax_t),
intent(in) :: ax
140 type(
field_t),
intent(inout) :: x
141 integer,
intent(in) :: n
142 real(kind=
rp),
dimension(n),
intent(in) :: f
143 type(
coef_t),
intent(inout) :: coef
145 type(
gs_t),
intent(inout) :: gs_h
147 integer,
optional,
intent(in) :: niter
148 integer :: i, j, k, l, iter, max_iter, s, ierr, it
149 real(kind=
rp) :: rnorm, rtr, rtz1, tmp
150 real(kind=
rp) :: beta(this%s+1), alpha(this%s+1), alpha1, alpha2, norm_fac
151 real(kind=
rp),
dimension(4*this%s+1,4*this%s+1) :: tt, g, gtt, temp, temp2
152 real(kind=
rp) :: p_c(4*this%s+1,this%s+1)
153 real(kind=
rp) :: r_c(4*this%s+1,this%s+1)
154 real(kind=
rp) :: z_c(4*this%s+1,this%s+1)
155 real(kind=
rp) :: x_c(4*this%s+1,this%s+1)
157 associate(pr => this%PR, r => this%r, p => this%p)
159 if (
present(niter))
then
162 max_iter = this%max_iter
164 norm_fac = 1.0_rp / sqrt(coef%volume)
169 call this%M%solve(p, r, n)
171 rtr =
glsc3(r, coef%mult, r, n)
172 rnorm = sqrt(rtr)*norm_fac
173 ksp_results%res_start = rnorm
174 ksp_results%res_final = rnorm
177 if (
abscmp(rnorm, 0.0_rp))
then
178 ksp_results%converged = .true.
180 call this%monitor_start(
'CACG')
181 do while (iter < max_iter)
184 call copy(pr(1,2*s+2), r, n)
188 if (mod(i,2) .eq. 0)
then
189 call ax%compute(pr(1,i), pr(1,i-1), coef, x%msh, x%Xh)
190 call gs_h%gs_op_vector(pr(1,i), n, gs_op_add)
191 call bc_projector%apply(pr(1,i), n)
193 call this%M%solve(pr(1,i), pr(1,i-1), n)
198 if (mod(i,2) == 0)
then
199 call this%M%solve(pr(1,i+1), pr(1,i), n)
201 call ax%compute(pr(1,i+1), pr(1,i), coef, x%msh, x%Xh)
202 call gs_h%gs_op_vector(pr(1,i+1), n, gs_op_add)
203 call bc_projector%apply(pr(1,1+i), n)
208 call rzero(p_c, (4*s+1) * (s+1))
210 call rzero(r_c, (4*s+1) * (s+1))
211 r_c(2*s+2,1) = 1.0_rp
212 call mxm(tt, 4*s+1, r_c, 4*s+1, z_c,s+1)
213 call rzero(x_c, (4*s+1) * (s+1))
214 call rzero(temp, (4*s+1)**2)
223 temp(it,1) = temp(it,1) &
224 + pr(i+k,j) * pr(i+k,l) * coef%mult(i+k,1,1,1)
233 temp(it,1) = temp(it,1) &
234 + pr(i+k,j) * pr(i+k,l) * coef%mult(i+k,1,1,1)
241 call mpi_allreduce(temp, temp2, it, &
252 call mxm(g,4*s+1, tt, 4*s+1,gtt,4*s+1)
257 call mxm(g, 4*s+1, r_c(1,j), 4*s+1,temp, 1)
258 call mxm(gtt, 4*s+1, p_c(1,j), 4*s+1,temp2, 1)
262 alpha1 = alpha1 + temp(i,1) * z_c(i,j)
263 alpha2 = alpha2 + temp2(i,1) * p_c(i,j)
265 alpha(j) = alpha1/alpha2
268 x_c(i,j+1) = x_c(i,j) + alpha(j) * p_c(i,j)
271 tmp = tmp + tt(i,k) * p_c(k,j)
273 r_c(i,j+1) = r_c(i,j) - alpha(j)*tmp
276 tmp = tmp + tt(i,k)*r_c(k,j+1)
281 call mxm(g,4*s+1,r_c(1,j+1),4*s+1,temp2,1)
284 alpha2 = alpha2 + temp2(i,1)*z_c(i,j+1)
286 beta(j) = alpha2 / alpha1
288 p_c(i,j+1) = z_c(i,j+1) + beta(j)*p_c(i,j)
299 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + pr(i+k,j) * x_c(j,s+1)
300 p(i+k) = p(i+k) + pr(i+k,j) * p_c(j,s+1)
301 tmp = pr(i+k,j) * r_c(j,s+1)
302 r(i+k) = r(i+k) + tmp
306 rtr = rtr + r(i+k)**2 * coef%mult(i+k,1,1,1)
311 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + pr(i+k,j) * x_c(j,s+1)
312 p(i+k) = p(i+k) + pr(i+k,j) * p_c(j,s+1)
313 tmp = pr(i+k,j) * r_c(j,s+1)
314 r(i+k) = r(i+k) + tmp
318 rtr = rtr + r(i+k)**2 * coef%mult(i+k,1,1,1)
323 call mpi_allreduce(rtr, tmp, 1, &
325 rnorm = norm_fac*sqrt(tmp)
326 call this%monitor_iter(iter, rnorm)
327 if (rnorm <= this%abs_tol)
exit
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)
355 n, coef, bc_projector, gs_h, niter)
result(ksp_results)
356 class(
cacg_t),
intent(inout) :: this
357 class(ax_t),
intent(in) :: ax
358 type(field_t),
intent(inout) :: x
359 type(field_t),
intent(inout) :: y
360 type(field_t),
intent(inout) :: z
361 integer,
intent(in) :: n
362 real(kind=rp),
dimension(n),
intent(in) :: fx
363 real(kind=rp),
dimension(n),
intent(in) :: fy
364 real(kind=rp),
dimension(n),
intent(in) :: fz
365 type(coef_t),
intent(inout) :: coef
366 class(vector_bc_projector_t),
intent(inout) :: bc_projector
367 type(gs_t),
intent(inout) :: gs_h
368 type(ksp_monitor_t),
dimension(3) :: ksp_results
369 integer,
optional,
intent(in) :: niter
370 type(scalar_bc_projector_t),
pointer :: bc_x, bc_y, bc_z
372 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
373 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
374 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
375 ksp_results(3) = this%solve(ax, z, fz, n, coef, bc_z, gs_h, niter)