Neko 1.99.5
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
43 use bc_list, only : bc_list_t
44 use math, only : glsc3, rzero, copy, x_update, abscmp
45 use utils, only : neko_warning
47 use mpi_f08, only : mpi_allreduce, mpi_sum
48 use mxm_wrapper
49 implicit none
50 private
51
53 type, public, extends(ksp_t) :: cacg_t
54 real(kind=rp), allocatable :: r(:)
55 real(kind=rp), allocatable :: p(:)
56 real(kind=rp), allocatable :: pr(:,:)
57 integer :: s = 4
58 contains
59 procedure, pass(this) :: init => cacg_init
60 procedure, pass(this) :: free => cacg_free
61 procedure, pass(this) :: solve => cacg_solve
62 procedure, pass(this) :: solve_coupled => cacg_solve_coupled
63 end type cacg_t
64
65contains
66
68 subroutine cacg_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
69 class(cacg_t), target, intent(inout) :: this
70 class(pc_t), optional, intent(in), target :: M
71 integer, intent(in) :: n
72 integer, intent(in) :: max_iter
73 real(kind=rp), optional, intent(in) :: rel_tol
74 real(kind=rp), optional, intent(in) :: abs_tol
75 logical, optional, intent(in) :: monitor
76 call this%free()
77
78 if (pe_rank .eq. 0) then
79 call neko_warning("Communication Avoiding CG chosen,&
80 & be aware of potential instabilities")
81 end if
82
83 allocate(this%r(n))
84 allocate(this%p(n))
85 allocate(this%PR(n,4*this%s+1))
86 if (present(m)) then
87 this%M => m
88 end if
89
90 if (present(rel_tol) .and. present(abs_tol) .and. present(monitor)) then
91 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
92 else if (present(rel_tol) .and. present(abs_tol)) then
93 call this%ksp_init(max_iter, rel_tol, abs_tol)
94 else if (present(monitor) .and. present(abs_tol)) then
95 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
96 else if (present(rel_tol) .and. present(monitor)) then
97 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
98 else if (present(rel_tol)) then
99 call this%ksp_init(max_iter, rel_tol = rel_tol)
100 else if (present(abs_tol)) then
101 call this%ksp_init(max_iter, abs_tol = abs_tol)
102 else if (present(monitor)) then
103 call this%ksp_init(max_iter, monitor = monitor)
104 else
105 call this%ksp_init(max_iter)
106 end if
107
108 end subroutine cacg_init
109
111 subroutine cacg_free(this)
112 class(cacg_t), intent(inout) :: this
113
114 call this%ksp_free()
115
116 if (allocated(this%PR)) then
117 deallocate(this%PR)
118 end if
119
120 if (allocated(this%r)) then
121 deallocate(this%r)
122 end if
123
124 if (allocated(this%p)) then
125 deallocate(this%p)
126 end if
127
128 nullify(this%M)
129
130
131 end subroutine cacg_free
132
134 function cacg_solve(this, Ax, x, f, n, coef, blst, gs_h, niter) &
135 result(ksp_results)
136 class(cacg_t), intent(inout) :: this
137 class(ax_t), intent(in) :: ax
138 type(field_t), intent(inout) :: x
139 integer, intent(in) :: n
140 real(kind=rp), dimension(n), intent(in) :: f
141 type(coef_t), intent(inout) :: coef
142 type(bc_list_t), intent(inout) :: blst
143 type(gs_t), intent(inout) :: gs_h
144 type(ksp_monitor_t) :: ksp_results
145 integer, optional, intent(in) :: niter
146 integer :: i, j, k, l, iter, max_iter, s, ierr, it
147 real(kind=rp) :: rnorm, rtr, rtz1, tmp
148 real(kind=rp) :: beta(this%s+1), alpha(this%s+1), alpha1, alpha2, norm_fac
149 real(kind=rp), dimension(4*this%s+1,4*this%s+1) :: tt, g, gtt, temp, temp2
150 real(kind=rp) :: p_c(4*this%s+1,this%s+1)
151 real(kind=rp) :: r_c(4*this%s+1,this%s+1)
152 real(kind=rp) :: z_c(4*this%s+1,this%s+1)
153 real(kind=rp) :: x_c(4*this%s+1,this%s+1)
154
155 associate(pr => this%PR, r => this%r, p => this%p)
156 s = this%s
157 if (present(niter)) then
158 max_iter = niter
159 else
160 max_iter = this%max_iter
161 end if
162 norm_fac = 1.0_rp / sqrt(coef%volume)
163
164 rtz1 = 1.0_rp
165 call rzero(x%x, n)
166 call copy(r, f, n)
167 call this%M%solve(p, r, n)
168
169 rtr = glsc3(r, coef%mult, r, n)
170 rnorm = sqrt(rtr)*norm_fac
171 ksp_results%res_start = rnorm
172 ksp_results%res_final = rnorm
173 ksp_results%iter = 0
174 iter = 0
175 if(abscmp(rnorm, 0.0_rp)) then
176 ksp_results%converged = .true.
177 end if
178 call this%monitor_start('CACG')
179 do while (iter < max_iter)
180
181 call copy(pr,p, n)
182 call copy(pr(1,2*s+2), r, n)
183
184 !Here we have hardcoded a monomial basis atm.
185 do i = 2, 2*s + 1
186 if (mod(i,2) .eq. 0) then
187 call ax%compute(pr(1,i), pr(1,i-1), coef, x%msh, x%Xh)
188 call gs_h%gs_op_vector(pr(1,i), n, gs_op_add)
189 call blst%apply_scalar(pr(1,i), n)
190 else
191 call this%M%solve(pr(1,i), pr(1,i-1), n)
192 end if
193 end do
194
195 do i = 2*s+2, 4*s
196 if (mod(i,2) == 0) then
197 call this%M%solve(pr(1,i+1), pr(1,i), n)
198 else
199 call ax%compute(pr(1,i+1), pr(1,i), coef, x%msh, x%Xh)
200 call gs_h%gs_op_vector(pr(1,i+1), n, gs_op_add)
201 call blst%apply_scalar(pr(1,1+i), n)
202 end if
203 end do
204
205 call construct_basis_matrix(tt, s)
206 call rzero(p_c, (4*s+1) * (s+1))
207 p_c(1,1) = 1.0_rp
208 call rzero(r_c, (4*s+1) * (s+1))
209 r_c(2*s+2,1) = 1.0_rp
210 call mxm(tt, 4*s+1, r_c, 4*s+1, z_c,s+1)
211 call rzero(x_c, (4*s+1) * (s+1))
212 call rzero(temp, (4*s+1)**2)
213
214 do i = 0, n, neko_blk_size
215 it = 0
216 if (i + neko_blk_size .le. n) then
217 do j = 1, 4*s+1
218 do l = 1, j
219 it = it + 1
220 do k = 1, neko_blk_size
221 temp(it,1) = temp(it,1) &
222 + pr(i+k,j) * pr(i+k,l) * coef%mult(i+k,1,1,1)
223 end do
224 end do
225 end do
226 else
227 do j = 1, 4*s+1
228 do l = 1, j
229 it = it + 1
230 do k = 1, n-i
231 temp(it,1) = temp(it,1) &
232 + pr(i+k,j) * pr(i+k,l) * coef%mult(i+k,1,1,1)
233 end do
234 end do
235 end do
236 end if
237 end do
238
239 call mpi_allreduce(temp, temp2, it, &
240 mpi_real_precision, mpi_sum, neko_comm, ierr)
241 it = 0
242 do j = 1, 4*s+1
243 do k = 1, j
244 it = it + 1
245 g(j,k) = temp2(it,1)
246 g(k,j) = temp2(it,1)
247 end do
248 end do
249
250 call mxm(g,4*s+1, tt, 4*s+1,gtt,4*s+1)
251
252 do j = 1, s
253 iter = iter + 1
254
255 call mxm(g, 4*s+1, r_c(1,j), 4*s+1,temp, 1)
256 call mxm(gtt, 4*s+1, p_c(1,j), 4*s+1,temp2, 1)
257 alpha1 = 0.0_rp
258 alpha2 = 0.0_rp
259 do i = 1,4*s+1
260 alpha1 = alpha1 + temp(i,1) * z_c(i,j)
261 alpha2 = alpha2 + temp2(i,1) * p_c(i,j)
262 end do
263 alpha(j) = alpha1/alpha2
264
265 do i = 1, 4*s+1
266 x_c(i,j+1) = x_c(i,j) + alpha(j) * p_c(i,j)
267 tmp = 0.0_rp
268 do k = 1, 4*s+1
269 tmp = tmp + tt(i,k) * p_c(k,j)
270 end do
271 r_c(i,j+1) = r_c(i,j) - alpha(j)*tmp
272 tmp = 0.0_rp
273 do k = 1, 4*s+1
274 tmp = tmp + tt(i,k)*r_c(k,j+1)
275 end do
276 z_c(i,j+1) = tmp
277 end do
278
279 call mxm(g,4*s+1,r_c(1,j+1),4*s+1,temp2,1)
280 alpha2 = 0.0_rp
281 do i = 1,4*s+1
282 alpha2 = alpha2 + temp2(i,1)*z_c(i,j+1)
283 end do
284 beta(j) = alpha2 / alpha1
285 do i = 1,4*s+1
286 p_c(i,j+1) = z_c(i,j+1) + beta(j)*p_c(i,j)
287 end do
288 end do
289
290 call rzero(p, n)
291 call rzero(r, n)
292 rtr = 0.0_rp
293 do i = 0, n, neko_blk_size
294 if (i + neko_blk_size .le. n) then
295 do j = 1, 4*s + 1
296 do k = 1, neko_blk_size
297 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + pr(i+k,j) * x_c(j,s+1)
298 p(i+k) = p(i+k) + pr(i+k,j) * p_c(j,s+1)
299 tmp = pr(i+k,j) * r_c(j,s+1)
300 r(i+k) = r(i+k) + tmp
301 end do
302 end do
303 do k = 1, neko_blk_size
304 rtr = rtr + r(i+k)**2 * coef%mult(i+k,1,1,1)
305 end do
306 else
307 do j = 1,4*s+1
308 do k = 1, n-i
309 x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + pr(i+k,j) * x_c(j,s+1)
310 p(i+k) = p(i+k) + pr(i+k,j) * p_c(j,s+1)
311 tmp = pr(i+k,j) * r_c(j,s+1)
312 r(i+k) = r(i+k) + tmp
313 end do
314 end do
315 do k = 1, n-i
316 rtr = rtr + r(i+k)**2 * coef%mult(i+k,1,1,1)
317 end do
318 end if
319 end do
320
321 call mpi_allreduce(rtr, tmp, 1, &
322 mpi_real_precision, mpi_sum, neko_comm, ierr)
323 rnorm = norm_fac*sqrt(tmp)
324 call this%monitor_iter(iter, rnorm)
325 if( rnorm <= this%abs_tol) exit
326 end do
327 call this%monitor_stop()
328 ksp_results%res_final = rnorm
329 ksp_results%iter = iter
330 ksp_results%converged = this%is_converged(iter, rnorm)
331
332 end associate
333
334 end function cacg_solve
335
337 subroutine construct_basis_matrix(Tt, s)
338 integer, intent(in) :: s
339 real(kind=rp), intent(inout) :: tt(4*s+1,4*s+1)
340 integer :: mlen, i
341 mlen = (4*s+1)*(4*s+1)
342 call rzero(tt,mlen)
343 do i = 1, 2*s
344 tt(i+1,i) = 1.0_rp
345 end do
346 do i = 1, (2*s-1)
347 tt(2*s+2+i,2*s+1+i) = 1.0_rp
348 end do
349 end subroutine construct_basis_matrix
350
352 function cacg_solve_coupled(this, Ax, x, y, z, fx, fy, fz, &
353 n, coef, blstx, blsty, blstz, gs_h, niter) result(ksp_results)
354 class(cacg_t), intent(inout) :: this
355 class(ax_t), intent(in) :: ax
356 type(field_t), intent(inout) :: x
357 type(field_t), intent(inout) :: y
358 type(field_t), intent(inout) :: z
359 integer, intent(in) :: n
360 real(kind=rp), dimension(n), intent(in) :: fx
361 real(kind=rp), dimension(n), intent(in) :: fy
362 real(kind=rp), dimension(n), intent(in) :: fz
363 type(coef_t), intent(inout) :: coef
364 type(bc_list_t), intent(inout) :: blstx
365 type(bc_list_t), intent(inout) :: blsty
366 type(bc_list_t), intent(inout) :: blstz
367 type(gs_t), intent(inout) :: gs_h
368 type(ksp_monitor_t), dimension(3) :: ksp_results
369 integer, optional, intent(in) :: niter
370
371 ksp_results(1) = this%solve(ax, x, fx, n, coef, blstx, gs_h, niter)
372 ksp_results(2) = this%solve(ax, y, fy, n, coef, blsty, gs_h, niter)
373 ksp_results(3) = this%solve(ax, z, fz, n, coef, blstz, gs_h, niter)
374
375 end function cacg_solve_coupled
376
377end module cacg
378
__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 list of bc_t.
Definition bc_list.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, blst, gs_h, niter)
S-step CA PCG solve.
Definition cacg.f90:136
subroutine construct_basis_matrix(tt, s)
Monomial matrix constuction, not sparse.
Definition cacg.f90:338
type(ksp_monitor_t) function, dimension(3) cacg_solve_coupled(this, ax, x, y, z, fx, fy, fz, n, coef, blstx, blsty, blstz, gs_h, niter)
S-step CA PCG coupled solve.
Definition cacg.f90:354
subroutine cacg_free(this)
Deallocate a s-step CA PCG solver.
Definition cacg.f90:112
subroutine cacg_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a s-step CA PCG solver.
Definition cacg.f90:69
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:53
integer, public pe_rank
MPI rank.
Definition comm.F90:58
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:45
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:51
Definition math.f90:60
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
Definition math.f90:1287
subroutine, public x_update(a, b, c, c1, c2, n)
Returns .
Definition math.f90:1249
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:291
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:235
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:12
Krylov preconditioner.
Definition precon.f90:34
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:398
Base type for a matrix-vector product providing .
Definition ax.f90:43
A list of allocatable `bc_t`. Follows the standard interface of lists.
Definition bc_list.f90:49
S-step communication avoiding preconditioned conjugate gradient method.
Definition cacg.f90:53
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:62
Type for storing initial and final residuals in a Krylov solver.
Definition krylov.f90:56
Base abstract type for a canonical Krylov method, solving .
Definition krylov.f90:73
Defines a canonical Krylov preconditioner.
Definition precon.f90:40