48 use mpi_f08,
only : mpi_allreduce, mpi_in_place, mpi_sum
56 real(kind=
rp),
allocatable :: w(:)
57 real(kind=
rp),
allocatable :: r(:)
58 real(kind=
rp),
allocatable :: p(:,:)
59 real(kind=
rp),
allocatable :: z(:)
60 real(kind=
rp),
allocatable :: alpha(:)
71 subroutine cg_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
72 class(
cg_t),
intent(inout),
target :: this
73 integer,
intent(in) :: max_iter
74 class(
pc_t),
optional,
intent(in),
target :: M
75 integer,
intent(in) :: n
76 real(kind=
rp),
optional,
intent(in) :: rel_tol
77 real(kind=
rp),
optional,
intent(in) :: abs_tol
78 logical,
optional,
intent(in) :: monitor
91 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
92 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
93 else if (
present(rel_tol) .and.
present(abs_tol))
then
94 call this%ksp_init(max_iter, rel_tol, abs_tol)
95 else if (
present(monitor) .and.
present(abs_tol))
then
96 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
97 else if (
present(rel_tol) .and.
present(monitor))
then
98 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
99 else if (
present(rel_tol))
then
100 call this%ksp_init(max_iter, rel_tol = rel_tol)
101 else if (
present(abs_tol))
then
102 call this%ksp_init(max_iter, abs_tol = abs_tol)
103 else if (
present(monitor))
then
104 call this%ksp_init(max_iter, monitor = monitor)
106 call this%ksp_init(max_iter)
113 class(
cg_t),
intent(inout) :: this
117 if (
allocated(this%w))
then
121 if (
allocated(this%r))
then
125 if (
allocated(this%p))
then
129 if (
allocated(this%z))
then
133 if (
allocated(this%alpha))
then
134 deallocate(this%alpha)
142 function cg_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
144 class(
cg_t),
intent(inout) :: this
145 class(
ax_t),
intent(in) :: ax
146 type(
field_t),
intent(inout) :: x
147 integer,
intent(in) :: n
148 real(kind=
rp),
dimension(n),
intent(in) :: f
149 type(
coef_t),
intent(inout) :: coef
151 type(
gs_t),
intent(inout) :: gs_h
153 integer,
optional,
intent(in) :: niter
154 integer :: iter, max_iter, i, j, k, p_cur, p_prev, ierr
156 real(kind=
rp) :: beta, pap, norm_fac, tmp
158 if (
present(niter))
then
161 max_iter = this%max_iter
163 norm_fac = 1.0_rp / sqrt(coef%volume)
165 associate(w => this%w, r => this%r, p => this%p, &
166 z => this%z, alpha => this%alpha)
172 x%x(i,1,1,1) = 0.0_rp
175 rtr = rtr + (r(i) * coef%mult(i,1,1,1) * r(i))
179 call mpi_allreduce(mpi_in_place, rtr, 1, &
182 rnorm = sqrt(rtr) * norm_fac
183 ksp_results%res_start = rnorm
184 ksp_results%res_final = rnorm
186 if (
abscmp(rnorm, 0.0_rp))
then
187 ksp_results%converged = .true.
193 call this%monitor_start(
'CG')
194 do iter = 1, max_iter
195 call this%M%solve(z, r, n)
197 rtz1 =
glsc3(r, coef%mult, z, n)
200 if (iter .eq. 1) beta = 0.0_rp
203 p(i, p_cur) = z(i) + beta * p(i, p_prev)
207 call ax%compute(w, p(1, p_cur), coef, x%msh, x%Xh)
208 call gs_h%op(w, n, gs_op_add)
209 call bc_projector%apply(w, n)
211 pap =
glsc3(w, coef%mult, p(1, p_cur), n)
213 alpha(p_cur) = rtz1 / pap
215 rnorm = sqrt(rtr) * norm_fac
216 call this%monitor_iter(iter, rnorm)
219 (rnorm .lt. this%abs_tol) .or. iter .eq. max_iter)
then
230 x_plus(k) = x_plus(k) + alpha(j) * p(i+k,j)
235 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
241 tmp = tmp + alpha(j) * p(i+k,j)
243 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + tmp
250 if (rnorm .lt. this%abs_tol)
exit
257 call this%monitor_stop()
258 ksp_results%res_final = rnorm
259 ksp_results%iter = iter
260 ksp_results%converged = this%is_converged(iter, rnorm)
264 integer,
intent(in) :: n
265 real(kind=rp),
intent(inout) :: r(n), rtr
267 real(kind=rp),
intent(in) ::mult(n), w(n), alpha
273 r(i) = r(i) - alpha*w(i)
274 tmp = tmp + r(i) * r(i) * mult(i)
277 call mpi_allreduce(mpi_in_place, tmp, 1, &
278 mpi_extra_precision, mpi_sum, neko_comm, ierr)
285 n, coef, bc_projector, gs_h, niter)
result(ksp_results)
286 class(
cg_t),
intent(inout) :: this
287 class(ax_t),
intent(in) :: ax
288 type(field_t),
intent(inout) :: x
289 type(field_t),
intent(inout) :: y
290 type(field_t),
intent(inout) :: z
291 integer,
intent(in) :: n
292 real(kind=rp),
dimension(n),
intent(in) :: fx
293 real(kind=rp),
dimension(n),
intent(in) :: fy
294 real(kind=rp),
dimension(n),
intent(in) :: fz
295 type(coef_t),
intent(inout) :: coef
296 class(vector_bc_projector_t),
intent(inout) :: bc_projector
297 type(gs_t),
intent(inout) :: gs_h
298 type(ksp_monitor_t),
dimension(3) :: ksp_results
299 integer,
optional,
intent(in) :: niter
300 type(scalar_bc_projector_t),
pointer :: bc_x, bc_y, bc_z
302 call vector_bc_projector_components(bc_projector, bc_x, bc_y, bc_z)
303 ksp_results(1) = this%solve(ax, x, fx, n, coef, bc_x, gs_h, niter)
304 ksp_results(2) = this%solve(ax, y, fy, n, coef, bc_y, gs_h, niter)
305 ksp_results(3) = this%solve(ax, z, fz, n, coef, bc_z, gs_h, niter)
__device__ T solve(const T u, const T y, const T guess, const T nu, const T kappa, const T B)
Defines a Matrix-vector product.
Defines various Conjugate Gradient methods.
subroutine cg_free(this)
Deallocate a standard PCG solver.
integer, parameter cg_p_space
type(ksp_monitor_t) function cg_solve(this, ax, x, f, n, coef, bc_projector, gs_h, niter)
Standard PCG solve.
subroutine cg_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a standard PCG solver.
type(ksp_monitor_t) function, dimension(3) cg_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, bc_projector, gs_h, niter)
Standard PCG coupled solve.
subroutine second_cg_part(rtr, r, mult, w, alpha, n)
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
type(mpi_comm), public neko_comm
MPI communicator.
type(mpi_datatype), public mpi_extra_precision
Implements the base abstract type for Krylov solvers plus helper types.
integer, parameter, public ksp_max_iter
Maximum number of iters.
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
integer, parameter neko_blk_size
integer, parameter, public xp
integer, parameter, public rp
Global precision used in computations.
Implements scalar_projector_t.
Implements boundary condition projectors for vector fields. Two types concrete types are provided: se...
subroutine, public vector_bc_projector_components(this, x, y, z)
Access the component scalar projectors from a segregated vector projector.
Base type for a matrix-vector product providing .
Standard preconditioned conjugate gradient method.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Type for storing initial and final residuals in a Krylov solver.
Base abstract type for a canonical Krylov method, solving .
Defines a canonical Krylov preconditioner.
Projector for scalar boundary conditions.
Abstract type for resolving vector boundary conditions.