Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
cg.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2026, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
34module cg
35 use neko_config, only : neko_blk_size
36 use num_types, only : rp, xp
38 use precon, only : pc_t
39 use ax_product, only : ax_t
40 use field, only : field_t
41 use coefs, only : coef_t
42 use gather_scatter, only : gs_t, gs_op_add
46 use math, only : glsc3, abscmp
48 use mpi_f08, only : mpi_allreduce, mpi_in_place, mpi_sum
49 implicit none
50 private
51
52 integer, parameter :: cg_p_space = 7
53
55 type, public, extends(ksp_t) :: cg_t
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(:)
61 contains
62 procedure, pass(this) :: init => cg_init
63 procedure, pass(this) :: free => cg_free
64 procedure, pass(this) :: solve => cg_solve
65 procedure, pass(this) :: solve_coupled => cg_solve_coupled
66 end type cg_t
67
68contains
69
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
79
80 call this%free()
81
82 allocate(this%w(n))
83 allocate(this%r(n))
84 allocate(this%p(n, cg_p_space))
85 allocate(this%z(n))
86 allocate(this%alpha(cg_p_space))
87
88 if (present(m)) then
89 this%M => m
90 end if
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)
105 else
106 call this%ksp_init(max_iter)
107 end if
108
109 end subroutine cg_init
110
112 subroutine cg_free(this)
113 class(cg_t), intent(inout) :: this
114
115 call this%ksp_free()
116
117 if (allocated(this%w)) then
118 deallocate(this%w)
119 end if
120
121 if (allocated(this%r)) then
122 deallocate(this%r)
123 end if
124
125 if (allocated(this%p)) then
126 deallocate(this%p)
127 end if
128
129 if (allocated(this%z)) then
130 deallocate(this%z)
131 end if
132
133 if (allocated(this%alpha)) then
134 deallocate(this%alpha)
135 end if
136
137 nullify(this%M)
138
139 end subroutine cg_free
140
142 function cg_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
143 result(ksp_results)
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
150 class(scalar_bc_projector_t), intent(inout) :: bc_projector
151 type(gs_t), intent(inout) :: gs_h
152 type(ksp_monitor_t) :: ksp_results
153 integer, optional, intent(in) :: niter
154 integer :: iter, max_iter, i, j, k, p_cur, p_prev, ierr
155 real(kind=rp) :: rnorm, rtr, rtz2, rtz1, x_plus(neko_blk_size)
156 real(kind=rp) :: beta, pap, norm_fac, tmp
157
158 if (present(niter)) then
159 max_iter = niter
160 else
161 max_iter = this%max_iter
162 end if
163 norm_fac = 1.0_rp / sqrt(coef%volume)
164
165 associate(w => this%w, r => this%r, p => this%p, &
166 z => this%z, alpha => this%alpha)
167
168 rtz1 = 1.0_rp
169 rtr = 0.0_rp
170 !$omp parallel do reduction(+:rtr)
171 do i = 1, n
172 x%x(i,1,1,1) = 0.0_rp
173 p(i, cg_p_space) = 0.0_rp
174 r(i) = f(i)
175 rtr = rtr + (r(i) * coef%mult(i,1,1,1) * r(i))
176 end do
177 !$omp end parallel do
178
179 call mpi_allreduce(mpi_in_place, rtr, 1, &
180 mpi_real_precision, mpi_sum, neko_comm, ierr)
181
182 rnorm = sqrt(rtr) * norm_fac
183 ksp_results%res_start = rnorm
184 ksp_results%res_final = rnorm
185 ksp_results%iter = 0
186 if (abscmp(rnorm, 0.0_rp)) then
187 ksp_results%converged = .true.
188 return
189 end if
190
191 p_prev = cg_p_space
192 p_cur = 1
193 call this%monitor_start('CG')
194 do iter = 1, max_iter
195 call this%M%solve(z, r, n)
196 rtz2 = rtz1
197 rtz1 = glsc3(r, coef%mult, z, n)
198
199 beta = rtz1 / rtz2
200 if (iter .eq. 1) beta = 0.0_rp
201 !$omp parallel do
202 do i = 1, n
203 p(i, p_cur) = z(i) + beta * p(i, p_prev)
204 end do
205 !$omp end parallel do
206
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)
210
211 pap = glsc3(w, coef%mult, p(1, p_cur), n)
212
213 alpha(p_cur) = rtz1 / pap
214 call second_cg_part(rtr, r, coef%mult, w, alpha(p_cur), n)
215 rnorm = sqrt(rtr) * norm_fac
216 call this%monitor_iter(iter, rnorm)
217
218 if ((p_cur .eq. cg_p_space) .or. &
219 (rnorm .lt. this%abs_tol) .or. iter .eq. max_iter) then
220 !$omp parallel do private(j, k, x_plus, tmp)
221 do i = 0, n-1, neko_blk_size
222 if (i + neko_blk_size .le. n) then
223 !$omp simd
224 do k = 1, neko_blk_size
225 x_plus(k) = 0.0_rp
226 end do
227 do j = 1, p_cur
228 !$omp simd
229 do k = 1, neko_blk_size
230 x_plus(k) = x_plus(k) + alpha(j) * p(i+k,j)
231 end do
232 end do
233 !$omp simd
234 do k = 1, neko_blk_size
235 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
236 end do
237 else
238 do k = 1, n - i
239 tmp = 0.0_rp
240 do j = 1, p_cur
241 tmp = tmp + alpha(j) * p(i+k,j)
242 end do
243 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + tmp
244 end do
245 end if
246 end do
247 !$omp end parallel do
248 p_prev = p_cur
249 p_cur = 1
250 if (rnorm .lt. this%abs_tol) exit
251 else
252 p_prev = p_cur
253 p_cur = p_cur + 1
254 end if
255 end do
256 end associate
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)
261 end function cg_solve
262
263 subroutine second_cg_part(rtr, r, mult, w, alpha, n)
264 integer, intent(in) :: n
265 real(kind=rp), intent(inout) :: r(n), rtr
266 real(kind=xp) :: tmp
267 real(kind=rp), intent(in) ::mult(n), w(n), alpha
268 integer :: i, ierr
269
270 tmp = 0.0_xp
271 !$omp parallel do reduction(+:tmp)
272 do i = 1, n
273 r(i) = r(i) - alpha*w(i)
274 tmp = tmp + r(i) * r(i) * mult(i)
275 end do
276 !$omp end parallel do
277 call mpi_allreduce(mpi_in_place, tmp, 1, &
278 mpi_extra_precision, mpi_sum, neko_comm, ierr)
279 rtr = tmp
280
281 end subroutine second_cg_part
282
284 function cg_solve_coupled(this, Ax, x, y, z, fx, fy, fz, &
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
301
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)
306
307 end function cg_solve_coupled
308
309end module cg
__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.
Definition ax.f90:34
Defines various Conjugate Gradient methods.
Definition cg.f90:34
subroutine cg_free(this)
Deallocate a standard PCG solver.
Definition cg.f90:113
integer, parameter cg_p_space
Definition cg.f90:52
type(ksp_monitor_t) function cg_solve(this, ax, x, f, n, coef, bc_projector, gs_h, niter)
Standard PCG solve.
Definition cg.f90:144
subroutine cg_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a standard PCG solver.
Definition cg.f90:72
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.
Definition cg.f90:286
subroutine second_cg_part(rtr, r, mult, w, alpha, n)
Definition cg.f90:264
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:54
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
type(mpi_datatype), public mpi_extra_precision
Definition comm.F90:55
Defines a field.
Definition field.f90:34
Gather-scatter.
Implements the base abstract type for Krylov solvers plus helper types.
Definition krylov.f90:34
integer, parameter, public ksp_max_iter
Maximum number of iters.
Definition krylov.f90:52
Definition math.f90:60
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
Definition math.f90:1290
Build configurations.
integer, parameter neko_blk_size
integer, parameter, public xp
Definition num_types.f90:16
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Krylov preconditioner.
Definition precon.f90:34
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 .
Definition ax.f90:43
Standard preconditioned conjugate gradient method.
Definition cg.f90:55
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
Gather-scatter kernel.
Type for storing initial and final residuals in a Krylov solver.
Definition krylov.f90:57
Base abstract type for a canonical Krylov method, solving .
Definition krylov.f90:74
Defines a canonical Krylov preconditioner.
Definition precon.f90:40
Projector for scalar boundary conditions.
Abstract type for resolving vector boundary conditions.