Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
cg_coupled.f90
Go to the documentation of this file.
1! Copyright (c) 2024-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_cpld
35 use num_types, only : rp, xp
37 use precon, only : pc_t
38 use ax_product, only : ax_t
39 use field, only : field_t
40 use coefs, only : coef_t
41 use gather_scatter, only : gs_t, gs_op_add
44 use math, only : abscmp
46 use mpi_f08, only : mpi_allreduce, mpi_in_place, mpi_sum
47 use utils, only : neko_error
48 use operators, only : rotate_cyc
49 implicit none
50 private
51
53 type, public, extends(ksp_t) :: cg_cpld_t
54 real(kind=rp), allocatable :: w1(:)
55 real(kind=rp), allocatable :: w2(:)
56 real(kind=rp), allocatable :: w3(:)
57 real(kind=rp), allocatable :: r1(:)
58 real(kind=rp), allocatable :: r2(:)
59 real(kind=rp), allocatable :: r3(:)
60 real(kind=rp), allocatable :: p1(:)
61 real(kind=rp), allocatable :: p2(:)
62 real(kind=rp), allocatable :: p3(:)
63 real(kind=rp), allocatable :: z1(:)
64 real(kind=rp), allocatable :: z2(:)
65 real(kind=rp), allocatable :: z3(:)
66 contains
67 procedure, pass(this) :: init => cg_cpld_init
68 procedure, pass(this) :: free => cg_cpld_free
69 procedure, pass(this) :: solve => cg_cpld_nop
70 procedure, pass(this) :: solve_coupled => cg_cpld_solve
71 end type cg_cpld_t
72
73contains
74
76 subroutine cg_cpld_init(this, n, max_iter, M, rel_tol, abs_tol, monitor)
77 class(cg_cpld_t), target, intent(inout) :: this
78 integer, intent(in) :: max_iter
79 class(pc_t), optional, intent(in), target :: M
80 integer, intent(in) :: n
81 real(kind=rp), optional, intent(in) :: rel_tol
82 real(kind=rp), optional, intent(in) :: abs_tol
83 logical, optional, intent(in) :: monitor
84
85 call this%free()
86
87 allocate(this%w1(n))
88 allocate(this%w2(n))
89 allocate(this%w3(n))
90 allocate(this%r1(n))
91 allocate(this%r2(n))
92 allocate(this%r3(n))
93 allocate(this%p1(n))
94 allocate(this%p2(n))
95 allocate(this%p3(n))
96 allocate(this%z1(n))
97 allocate(this%z2(n))
98 allocate(this%z3(n))
99
100 if (present(m)) then
101 this%M => m
102 end if
103
104 if (present(rel_tol) .and. present(abs_tol) .and. present(monitor)) then
105 call this%ksp_init(max_iter, rel_tol, abs_tol, monitor = monitor)
106 else if (present(rel_tol) .and. present(abs_tol)) then
107 call this%ksp_init(max_iter, rel_tol, abs_tol)
108 else if (present(monitor) .and. present(abs_tol)) then
109 call this%ksp_init(max_iter, abs_tol = abs_tol, monitor = monitor)
110 else if (present(rel_tol) .and. present(monitor)) then
111 call this%ksp_init(max_iter, rel_tol, monitor = monitor)
112 else if (present(rel_tol)) then
113 call this%ksp_init(max_iter, rel_tol = rel_tol)
114 else if (present(abs_tol)) then
115 call this%ksp_init(max_iter, abs_tol = abs_tol)
116 else if (present(monitor)) then
117 call this%ksp_init(max_iter, monitor = monitor)
118 else
119 call this%ksp_init(max_iter)
120 end if
121
122 end subroutine cg_cpld_init
123
125 subroutine cg_cpld_free(this)
126 class(cg_cpld_t), intent(inout) :: this
127
128 call this%ksp_free()
129
130 if (allocated(this%w1)) then
131 deallocate(this%w1)
132 end if
133
134 if (allocated(this%w2)) then
135 deallocate(this%w2)
136 end if
137
138 if (allocated(this%w3)) then
139 deallocate(this%w3)
140 end if
141
142 if (allocated(this%r1)) then
143 deallocate(this%r1)
144 end if
145
146 if (allocated(this%r2)) then
147 deallocate(this%r2)
148 end if
149
150 if (allocated(this%r3)) then
151 deallocate(this%r3)
152 end if
153
154 if (allocated(this%p1)) then
155 deallocate(this%p1)
156 end if
157
158 if (allocated(this%p2)) then
159 deallocate(this%p2)
160 end if
161
162 if (allocated(this%p3)) then
163 deallocate(this%p3)
164 end if
165
166 if (allocated(this%z1)) then
167 deallocate(this%z1)
168 end if
169
170 if (allocated(this%z2)) then
171 deallocate(this%z2)
172 end if
173
174 if (allocated(this%z3)) then
175 deallocate(this%z3)
176 end if
177
178 nullify(this%M)
179
180 end subroutine cg_cpld_free
181
182 function cg_cpld_nop(this, Ax, x, f, n, coef, bc_projector, gs_h, niter) &
183 result(ksp_results)
184 class(cg_cpld_t), intent(inout) :: this
185 class(ax_t), intent(in) :: ax
186 type(field_t), intent(inout) :: x
187 integer, intent(in) :: n
188 real(kind=rp), dimension(n), intent(in) :: f
189 type(coef_t), intent(inout) :: coef
190 class(scalar_bc_projector_t), intent(inout) :: bc_projector
191 type(gs_t), intent(inout) :: gs_h
192 type(ksp_monitor_t) :: ksp_results
193 integer, optional, intent(in) :: niter
194
195 ! Throw and error
196 call neko_error('The cpldcg solver is only defined for coupled solves')
197
198 ksp_results%res_final = 0.0
199 ksp_results%iter = 0
200 end function cg_cpld_nop
201
203 function cg_cpld_solve(this, Ax, x, y, z, fx, fy, fz, &
204 n, coef, bc_projector, gs_h, niter) result(ksp_results)
205 class(cg_cpld_t), intent(inout) :: this
206 class(ax_t), intent(in) :: ax
207 type(field_t), intent(inout) :: x
208 type(field_t), intent(inout) :: y
209 type(field_t), intent(inout) :: z
210 integer, intent(in) :: n
211 real(kind=rp), dimension(n), intent(in) :: fx
212 real(kind=rp), dimension(n), intent(in) :: fy
213 real(kind=rp), dimension(n), intent(in) :: fz
214 type(coef_t), intent(inout) :: coef
215 class(vector_bc_projector_t), intent(inout) :: bc_projector
216 type(gs_t), intent(inout) :: gs_h
217 type(ksp_monitor_t), dimension(3) :: ksp_results
218 integer, optional, intent(in) :: niter
219 integer :: i, iter, max_iter, ierr
220 real(kind=rp) :: rnorm, rtr, rtr0, rtz2, rtz1
221 real(kind=rp) :: beta, pap, alpha, norm_fac
222 real(kind=xp) :: tmp_xp, r1_xp, r2_xp, r3_xp, mult_xp
223
224 if (present(niter)) then
225 max_iter = niter
226 else
227 max_iter = this%max_iter
228 end if
229 norm_fac = 1.0_rp / sqrt(coef%volume)
230
231 associate(p1 => this%p1, p2 => this%p2, p3 => this%p3, z1 => this%z1, &
232 z2 => this%z2, z3 => this%z3, r1 => this%r1, r2 => this%r2, &
233 r3 => this%r3, w1 => this%w1, w2 => this%w2, w3 => this%w3)
234
235 rtz1 = 1.0_rp
236 tmp_xp = 0.0_xp
237 !$omp parallel do reduction(+:tmp_xp)
238 do i = 1, n
239 x%x(i,1,1,1) = 0.0_rp
240 y%x(i,1,1,1) = 0.0_rp
241 z%x(i,1,1,1) = 0.0_rp
242 p1(i) = 0.0_rp
243 p2(i) = 0.0_rp
244 p3(i) = 0.0_rp
245 z1(i) = 0.0_rp
246 z2(i) = 0.0_rp
247 z3(i) = 0.0_rp
248 r1(i) = fx(i)
249 r2(i) = fy(i)
250 r3(i) = fz(i)
251 tmp_xp = tmp_xp + (r1(i)**2 + r2(i)**2 + r3(i)**2) &
252 * coef%mult(i,1,1,1)
253 end do
254 !$omp end parallel do
255
256 call mpi_allreduce(mpi_in_place, tmp_xp, 1, mpi_extra_precision, &
257 mpi_sum, neko_comm, ierr)
258 rtr = tmp_xp
259 rnorm = sqrt(rtr)*norm_fac
260 ksp_results%res_start = rnorm
261 ksp_results%res_final = rnorm
262 ksp_results%iter = 0
263 if (abscmp(rnorm, 0.0_rp)) then
264 ksp_results%converged = .true.
265 return
266 end if
267
268 call this%monitor_start('cpldCG')
269 do iter = 1, max_iter
270 call this%M%solve(z1, this%r1, n)
271 call this%M%solve(z2, this%r2, n)
272 call this%M%solve(z3, this%r3, n)
273 rtz2 = rtz1
274
275 tmp_xp = 0.0_xp
276 !$omp parallel do reduction(+:tmp_xp)
277 do i = 1, n
278 tmp_xp = tmp_xp + (z1(i) * r1(i) &
279 + z2(i) * r2(i) &
280 + z3(i) * r3(i)) * coef%mult(i,1,1,1)
281 end do
282 !$omp end parallel do
283
284 call mpi_allreduce(mpi_in_place, tmp_xp, 1, mpi_extra_precision, &
285 mpi_sum, neko_comm, ierr)
286 rtz1 = tmp_xp
287
288 beta = rtz1 / rtz2
289 if (iter .eq. 1) beta = 0.0_rp
290 !$omp parallel do
291 do i = 1, n
292 p1(i) = p1(i) * beta + z1(i)
293 p2(i) = p2(i) * beta + z2(i)
294 p3(i) = p3(i) * beta + z3(i)
295 end do
296 !$omp end parallel do
297
298 call ax%compute_vector(w1, w2, w3, p1, p2, p3, coef, x%msh, x%Xh)
299
300 call rotate_cyc(w1, w2, w3, 1, coef)
301 call gs_h%op(w1, w2, w3, n, gs_op_add)
302 call rotate_cyc(w1, w2, w3, 0, coef)
303
304 call bc_projector%apply(w1, w2, w3, n)
305
306 tmp_xp = 0.0_xp
307 !$omp parallel do reduction(+:tmp_xp)
308 do i = 1, n
309 tmp_xp = tmp_xp + (w1(i) * p1(i) &
310 + w2(i) * p2(i) &
311 + w3(i) * p3(i)) * coef%mult(i,1,1,1)
312 end do
313 !$omp end parallel do
314
315 call mpi_allreduce(mpi_in_place, tmp_xp, 1, mpi_extra_precision, &
316 mpi_sum, neko_comm, ierr)
317 pap = tmp_xp
318
319 alpha = rtz1 / pap
320 tmp_xp = 0.0_xp
321
322 !$omp parallel private (i)
323 !$omp do
324 do i = 1, n
325 x%x(i,1,1,1) = x%x(i,1,1,1) + alpha * p1(i)
326 y%x(i,1,1,1) = y%x(i,1,1,1) + alpha * p2(i)
327 z%x(i,1,1,1) = z%x(i,1,1,1) + alpha * p3(i)
328 end do
329 !$omp end do nowait
330
331 !$omp do reduction(+:tmp_xp)
332 do i = 1, n
333 r1(i) = r1(i) - alpha * w1(i)
334 r2(i) = r2(i) - alpha * w2(i)
335 r3(i) = r3(i) - alpha * w3(i)
336 r1_xp = real(r1(i), kind=xp)
337 r2_xp = real(r2(i), kind=xp)
338 r3_xp = real(r3(i), kind=xp)
339 mult_xp = real(coef%mult(i,1,1,1), kind=xp)
340 tmp_xp = tmp_xp + &
341 (r1_xp * r1_xp + r2_xp * r2_xp + r3_xp * r3_xp) * mult_xp
342 end do
343 !$omp end do nowait
344 !$omp end parallel
345
346 call mpi_allreduce(mpi_in_place, tmp_xp, 1, mpi_extra_precision, &
347 mpi_sum, neko_comm, ierr)
348 rtr = tmp_xp
349
350 if (iter .eq. 1) rtr0 = rtr
351 rnorm = sqrt(rtr) * norm_fac
352 call this%monitor_iter(iter, rnorm)
353 if (rnorm .lt. this%abs_tol) then
354 exit
355 end if
356 end do
357 end associate
358 call this%monitor_stop()
359 ksp_results%res_final = rnorm
360 ksp_results%iter = iter
361 ksp_results%converged = this%is_converged(iter, rnorm)
362 end function cg_cpld_solve
363
364end module cg_cpld
__device__ T solve(const T u, const T y, const T guess, const T nu, const T kappa, const T B)
double real
Apply cyclic boundary condition to a vector field.
Defines a Matrix-vector product.
Definition ax.f90:34
Defines a coupled Conjugate Gradient methods.
type(ksp_monitor_t) function cg_cpld_nop(this, ax, x, f, n, coef, bc_projector, gs_h, niter)
type(ksp_monitor_t) function, dimension(3) cg_cpld_solve(this, ax, x, y, z, fx, fy, fz, n, coef, bc_projector, gs_h, niter)
Coupled PCG solve.
subroutine cg_cpld_free(this)
Deallocate a coupled PCG solver.
subroutine cg_cpld_init(this, n, max_iter, m, rel_tol, abs_tol, monitor)
Initialise a coupled PCG solver.
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
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
integer, parameter, public xp
Definition num_types.f90:16
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Operators.
Definition operators.f90:34
Krylov preconditioner.
Definition precon.f90:34
Implements scalar_projector_t.
Utilities.
Definition utils.f90:35
Implements boundary condition projectors for vector fields. Two types concrete types are provided: se...
Base type for a matrix-vector product providing .
Definition ax.f90:43
Coupled preconditioned conjugate gradient method.
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.