Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
cacg.f90
Go to the documentation of this file.
1! Copyright (c) 2021-2025, 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 cacg
35 use num_types, only : rp
36 use neko_config, only : neko_blk_size
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, rzero, copy, x_update, abscmp
47 use utils, only : neko_warning
49 use mpi_f08, only : mpi_allreduce, mpi_sum
50 use mxm_wrapper
51 implicit none
52 private
53
55 type, public, extends(ksp_t) :: cacg_t
56 real(kind=rp), allocatable :: r(:)
57 real(kind=rp), allocatable :: p(:)
58 real(kind=rp), allocatable :: pr(:,:)
59 integer :: s = 4
60 contains
61 procedure, pass(this) :: init => cacg_init
62 procedure, pass(this) :: free => cacg_free
63 procedure, pass(this) :: solve => cacg_solve
64 procedure, pass(this) :: solve_coupled => cacg_solve_coupled
65 end type cacg_t
66
67contains
68
70 subroutine cacg_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
71 class(cacg_t), target, intent(inout) :: this
72 class(pc_t), optional, intent(in), target :: M
73 integer, intent(in) :: n
74 integer, intent(in) :: max_iter
75 real(kind=rp), optional, intent(in) :: rel_tol
76 real(kind=rp), optional, intent(in) :: abs_tol
77 logical, optional, intent(in) :: monitor
78 call this%free()
79
80 if (pe_rank .eq. 0) then
81 call neko_warning("Communication Avoiding CG chosen,&
82 & be aware of potential instabilities")
83 end if
84
85 allocate(this%r(n))
86 allocate(this%p(n))
87 allocate(this%PR(n,4*this%s+1))
88 if (present(m)) then
89 this%M => m
90 end if
91
92 if (present(rel_tol) .and. present(abs_tol) .and. present(monitor)) then
93 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
94 else if (present(rel_tol) .and. present(abs_tol)) then
95 call this%ksp_init(max_iter, rel_tol, abs_tol)
96 else if (present(monitor) .and. present(abs_tol)) then
97 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
98 else if (present(rel_tol) .and. present(monitor)) then
99 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
100 else if (present(rel_tol)) then
101 call this%ksp_init(max_iter, rel_tol = rel_tol)
102 else if (present(abs_tol)) then
103 call this%ksp_init(max_iter, abs_tol = abs_tol)
104 else if (present(monitor)) then
105 call this%ksp_init(max_iter, monitor = monitor)
106 else
107 call this%ksp_init(max_iter)
108 end if
109
110 end subroutine cacg_init
111
113 subroutine cacg_free(this)
114 class(cacg_t), intent(inout) :: this
115
116 call this%ksp_free()
117
118 if (allocated(this%PR)) then
119 deallocate(this%PR)
120 end if
121
122 if (allocated(this%r)) then
123 deallocate(this%r)
124 end if
125
126 if (allocated(this%p)) then
127 deallocate(this%p)
128 end if
129
130 nullify(this%M)
131
132
133 end subroutine cacg_free
134
136 function cacg_solve(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
137 result(ksp_results)
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
144 class(scalar_bc_projector_t), intent(inout) :: bc_projector
145 type(gs_t), intent(inout) :: gs_h
146 type(ksp_monitor_t) :: ksp_results
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)
156
157 associate(pr => this%PR, r => this%r, p => this%p)
158 s = this%s
159 if (present(niter)) then
160 max_iter = niter
161 else
162 max_iter = this%max_iter
163 end if
164 norm_fac = 1.0_rp / sqrt(coef%volume)
165
166 rtz1 = 1.0_rp
167 call rzero(x%x, n)
168 call copy(r, f, n)
169 call this%M%solve(p, r, n)
170
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
175 ksp_results%iter = 0
176 iter = 0
177 if (abscmp(rnorm, 0.0_rp)) then
178 ksp_results%converged = .true.
179 end if
180 call this%monitor_start('CACG')
181 do while (iter < max_iter)
182
183 call copy(pr,p, n)
184 call copy(pr(1,2*s+2), r, n)
185
186 !Here we have hardcoded a monomial basis atm.
187 do i = 2, 2*s + 1
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)
192 else
193 call this%M%solve(pr(1,i), pr(1,i-1), n)
194 end if
195 end do
196
197 do i = 2*s+2, 4*s
198 if (mod(i,2) == 0) then
199 call this%M%solve(pr(1,i+1), pr(1,i), n)
200 else
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)
204 end if
205 end do
206
207 call construct_basis_matrix(tt, s)
208 call rzero(p_c, (4*s+1) * (s+1))
209 p_c(1,1) = 1.0_rp
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)
215
216 do i = 0, n, neko_blk_size
217 it = 0
218 if (i + neko_blk_size .le. n) then
219 do j = 1, 4*s+1
220 do l = 1, j
221 it = it + 1
222 do k = 1, neko_blk_size
223 temp(it,1) = temp(it,1) &
224 + pr(i+k,j) * pr(i+k,l) * coef%mult(i+k,1,1,1)
225 end do
226 end do
227 end do
228 else
229 do j = 1, 4*s+1
230 do l = 1, j
231 it = it + 1
232 do k = 1, n-i
233 temp(it,1) = temp(it,1) &
234 + pr(i+k,j) * pr(i+k,l) * coef%mult(i+k,1,1,1)
235 end do
236 end do
237 end do
238 end if
239 end do
240
241 call mpi_allreduce(temp, temp2, it, &
242 mpi_real_precision, mpi_sum, neko_comm, ierr)
243 it = 0
244 do j = 1, 4*s+1
245 do k = 1, j
246 it = it + 1
247 g(j,k) = temp2(it,1)
248 g(k,j) = temp2(it,1)
249 end do
250 end do
251
252 call mxm(g,4*s+1, tt, 4*s+1,gtt,4*s+1)
253
254 do j = 1, s
255 iter = iter + 1
256
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)
259 alpha1 = 0.0_rp
260 alpha2 = 0.0_rp
261 do i = 1,4*s+1
262 alpha1 = alpha1 + temp(i,1) * z_c(i,j)
263 alpha2 = alpha2 + temp2(i,1) * p_c(i,j)
264 end do
265 alpha(j) = alpha1/alpha2
266
267 do i = 1, 4*s+1
268 x_c(i,j+1) = x_c(i,j) + alpha(j) * p_c(i,j)
269 tmp = 0.0_rp
270 do k = 1, 4*s+1
271 tmp = tmp + tt(i,k) * p_c(k,j)
272 end do
273 r_c(i,j+1) = r_c(i,j) - alpha(j)*tmp
274 tmp = 0.0_rp
275 do k = 1, 4*s+1
276 tmp = tmp + tt(i,k)*r_c(k,j+1)
277 end do
278 z_c(i,j+1) = tmp
279 end do
280
281 call mxm(g,4*s+1,r_c(1,j+1),4*s+1,temp2,1)
282 alpha2 = 0.0_rp
283 do i = 1,4*s+1
284 alpha2 = alpha2 + temp2(i,1)*z_c(i,j+1)
285 end do
286 beta(j) = alpha2 / alpha1
287 do i = 1,4*s+1
288 p_c(i,j+1) = z_c(i,j+1) + beta(j)*p_c(i,j)
289 end do
290 end do
291
292 call rzero(p, n)
293 call rzero(r, n)
294 rtr = 0.0_rp
295 do i = 0, n, neko_blk_size
296 if (i + neko_blk_size .le. n) then
297 do j = 1, 4*s + 1
298 do k = 1, neko_blk_size
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
303 end do
304 end do
305 do k = 1, neko_blk_size
306 rtr = rtr + r(i+k)**2 * coef%mult(i+k,1,1,1)
307 end do
308 else
309 do j = 1,4*s+1
310 do k = 1, n-i
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
315 end do
316 end do
317 do k = 1, n-i
318 rtr = rtr + r(i+k)**2 * coef%mult(i+k,1,1,1)
319 end do
320 end if
321 end do
322
323 call mpi_allreduce(rtr, tmp, 1, &
324 mpi_real_precision, mpi_sum, neko_comm, ierr)
325 rnorm = norm_fac*sqrt(tmp)
326 call this%monitor_iter(iter, rnorm)
327 if (rnorm <= this%abs_tol) exit
328 end do
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)
333
334 end associate
335
336 end function cacg_solve
337
339 subroutine construct_basis_matrix(Tt, s)
340 integer, intent(in) :: s
341 real(kind=rp), intent(inout) :: tt(4*s+1,4*s+1)
342 integer :: mlen, i
343 mlen = (4*s+1)*(4*s+1)
344 call rzero(tt,mlen)
345 do i = 1, 2*s
346 tt(i+1,i) = 1.0_rp
347 end do
348 do i = 1, (2*s-1)
349 tt(2*s+2+i,2*s+1+i) = 1.0_rp
350 end do
351 end subroutine construct_basis_matrix
352
354 function cacg_solve_coupled(this, Ax, x, y, z, fx, fy, fz, &
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
371
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)
376
377 end function cacg_solve_coupled
378
379end module cacg
__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 a communication avoiding Conjugate Gradient method.
Definition cacg.f90:34
type(ksp_monitor_t) function cacg_solve(this, ax, x, f, n, coef, bc_projector, gs_h, niter)
S-step CA PCG solve.
Definition cacg.f90:138
subroutine construct_basis_matrix(tt, s)
Monomial matrix constuction, not sparse.
Definition cacg.f90:340
type(ksp_monitor_t) function, dimension(3) cacg_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, bc_projector, gs_h, niter)
S-step CA PCG coupled solve.
Definition cacg.f90:356
subroutine cacg_free(this)
Deallocate a s-step CA PCG solver.
Definition cacg.f90:114
subroutine cacg_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a s-step CA PCG solver.
Definition cacg.f90:71
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
integer, public pe_rank
MPI rank.
Definition comm.F90:59
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
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
subroutine, public x_update(a, b, c, c1, c2, n)
Returns .
Definition math.f90:1252
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:294
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:238
Wrapper for all matrix-matrix product implementations.
subroutine, public mxm(a, n1, b, n2, c, n3)
Compute matrix-matrix product for contiguously packed matrices A,B, and C.
Build configurations.
integer, parameter neko_blk_size
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Krylov preconditioner.
Definition precon.f90:34
Implements scalar_projector_t.
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:398
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
S-step communication avoiding preconditioned conjugate gradient method.
Definition cacg.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.