46 use mpi_f08,
only : mpi_allreduce, mpi_in_place, mpi_sum
54 real(kind=
rp),
allocatable :: w(:)
55 real(kind=
rp),
allocatable :: r(:)
56 real(kind=
rp),
allocatable :: p(:,:)
57 real(kind=
rp),
allocatable :: z(:)
58 real(kind=
rp),
allocatable :: alpha(:)
69 subroutine cg_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
70 class(
cg_t),
intent(inout),
target :: this
71 integer,
intent(in) :: max_iter
72 class(
pc_t),
optional,
intent(in),
target :: M
73 integer,
intent(in) :: n
74 real(kind=
rp),
optional,
intent(in) :: rel_tol
75 real(kind=
rp),
optional,
intent(in) :: abs_tol
76 logical,
optional,
intent(in) :: monitor
89 if (
present(rel_tol) .and.
present(abs_tol) .and.
present(monitor))
then
90 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
91 else if (
present(rel_tol) .and.
present(abs_tol))
then
92 call this%ksp_init(max_iter, rel_tol, abs_tol)
93 else if (
present(monitor) .and.
present(abs_tol))
then
94 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
95 else if (
present(rel_tol) .and.
present(monitor))
then
96 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
97 else if (
present(rel_tol))
then
98 call this%ksp_init(max_iter, rel_tol = rel_tol)
99 else if (
present(abs_tol))
then
100 call this%ksp_init(max_iter, abs_tol = abs_tol)
101 else if (
present(monitor))
then
102 call this%ksp_init(max_iter, monitor = monitor)
104 call this%ksp_init(max_iter)
111 class(
cg_t),
intent(inout) :: this
115 if (
allocated(this%w))
then
119 if (
allocated(this%r))
then
123 if (
allocated(this%p))
then
127 if (
allocated(this%z))
then
131 if (
allocated(this%alpha))
then
132 deallocate(this%alpha)
140 function cg_solve(this, Ax, x, f, n, coef, blst, gs_h, niter)
result(ksp_results)
141 class(
cg_t),
intent(inout) :: this
142 class(
ax_t),
intent(in) :: ax
143 type(
field_t),
intent(inout) :: x
144 integer,
intent(in) :: n
145 real(kind=
rp),
dimension(n),
intent(in) :: f
146 type(
coef_t),
intent(inout) :: coef
148 type(
gs_t),
intent(inout) :: gs_h
150 integer,
optional,
intent(in) :: niter
151 integer :: iter, max_iter, i, j, k, p_cur, p_prev
153 real(kind=
rp) :: beta, pap, norm_fac
155 if (
present(niter))
then
158 max_iter = this%max_iter
160 norm_fac = 1.0_rp / sqrt(coef%volume)
162 associate(w => this%w, r => this%r, p => this%p, &
163 z => this%z, alpha => this%alpha)
170 rtr =
glsc3(r, coef%mult, r, n)
171 rnorm = sqrt(rtr) * norm_fac
172 ksp_results%res_start = rnorm
173 ksp_results%res_final = rnorm
175 if(
abscmp(rnorm, 0.0_rp))
then
176 ksp_results%converged = .true.
182 call this%monitor_start(
'CG')
183 do iter = 1, max_iter
184 call this%M%solve(z, r, n)
186 rtz1 =
glsc3(r, coef%mult, z, n)
189 if (iter .eq. 1) beta = 0.0_rp
191 p(i,p_cur) = z(i) + beta * p(i,p_prev)
194 call ax%compute(w, p(1,p_cur), coef, x%msh, x%Xh)
195 call gs_h%op(w, n, gs_op_add)
196 call blst%apply(w, n)
198 pap =
glsc3(w, coef%mult, p(1,p_cur), n)
200 alpha(p_cur) = rtz1 / pap
202 rnorm = sqrt(rtr) * norm_fac
203 call this%monitor_iter(iter, rnorm)
206 (rnorm .lt. this%abs_tol) .or. iter .eq. max_iter)
then
214 x_plus(k) = x_plus(k) + alpha(j) * p(i+k,j)
218 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
224 x_plus(1) = x_plus(1) + alpha(j) * p(i+k,j)
226 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(1)
232 if (rnorm .lt. this%abs_tol)
exit
239 call this%monitor_stop()
240 ksp_results%res_final = rnorm
241 ksp_results%iter = iter
242 ksp_results%converged = this%is_converged(iter, rnorm)
246 integer,
intent(in) :: n
247 real(kind=rp),
intent(inout) :: r(n), rtr
249 real(kind=rp),
intent(in) ::mult(n), w(n), alpha
254 r(i) = r(i) - alpha*w(i)
255 tmp = tmp + r(i) * r(i) * mult(i)
257 call mpi_allreduce(mpi_in_place, tmp, 1, &
258 mpi_extra_precision, mpi_sum, neko_comm, ierr)
265 n, coef, blstx, blsty, blstz, gs_h, niter)
result(ksp_results)
266 class(
cg_t),
intent(inout) :: this
267 class(ax_t),
intent(in) :: ax
268 type(field_t),
intent(inout) :: x
269 type(field_t),
intent(inout) :: y
270 type(field_t),
intent(inout) :: z
271 integer,
intent(in) :: n
272 real(kind=rp),
dimension(n),
intent(in) :: fx
273 real(kind=rp),
dimension(n),
intent(in) :: fy
274 real(kind=rp),
dimension(n),
intent(in) :: fz
275 type(coef_t),
intent(inout) :: coef
276 type(bc_list_t),
intent(inout) :: blstx
277 type(bc_list_t),
intent(inout) :: blsty
278 type(bc_list_t),
intent(inout) :: blstz
279 type(gs_t),
intent(inout) :: gs_h
280 type(ksp_monitor_t),
dimension(3) :: ksp_results
281 integer,
optional,
intent(in) :: niter
283 ksp_results(1) = this%solve(ax, x, fx, n, coef, blstx, gs_h, niter)
284 ksp_results(2) = this%solve(ax, y, fy, n, coef, blsty, gs_h, niter)
285 ksp_results(3) = this%solve(ax, z, fz, n, coef, blstz, 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, dimension(3) cg_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, blstx, blsty, blstz, gs_h, niter)
Standard PCG coupled solve.
subroutine cg_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a standard PCG solver.
subroutine second_cg_part(rtr, r, mult, w, alpha, n)
type(ksp_monitor_t) function cg_solve(this, ax, x, f, n, coef, blst, gs_h, niter)
Standard PCG solve.
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 .
subroutine, public copy(a, b, n)
Copy a vector .
subroutine, public rzero(a, n)
Zero a real vector.
integer, parameter neko_blk_size
integer, parameter, public xp
integer, parameter, public rp
Global precision used in computations.
Base type for a matrix-vector product providing .
A list of allocatable `bc_t`. Follows the standard interface of lists.
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.