Neko  0.8.1
A portable framework for high-order spectral element flow simulations
cg.f90
Go to the documentation of this file.
1 ! Copyright (c) 2020-2024, 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 !
34 module cg
35  use num_types, only: rp
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
42  use bc, only : bc_list_t, bc_list_apply
43  use math, only : glsc3, rzero, copy, abscmp
44  use comm
45  implicit none
46  private
47 
48  integer, parameter :: cg_p_space = 7
49 
51  type, public, extends(ksp_t) :: cg_t
52  real(kind=rp), allocatable :: w(:)
53  real(kind=rp), allocatable :: r(:)
54  real(kind=rp), allocatable :: p(:,:)
55  real(kind=rp), allocatable :: z(:)
56  real(kind=rp), allocatable :: alpha(:)
57  contains
58  procedure, pass(this) :: init => cg_init
59  procedure, pass(this) :: free => cg_free
60  procedure, pass(this) :: solve => cg_solve
61  end type cg_t
62 
63 contains
64 
66  subroutine cg_init(this, n, max_iter, M, rel_tol, abs_tol)
67  class(cg_t), intent(inout), target :: this
68  integer, intent(in) :: max_iter
69  class(pc_t), optional, intent(inout), target :: M
70  integer, intent(in) :: n
71  real(kind=rp), optional, intent(inout) :: rel_tol
72  real(kind=rp), optional, intent(inout) :: abs_tol
73 
74  call this%free()
75 
76  allocate(this%w(n))
77  allocate(this%r(n))
78  allocate(this%p(n,cg_p_space))
79  allocate(this%z(n))
80  allocate(this%alpha(cg_p_space))
81 
82  if (present(m)) then
83  this%M => m
84  end if
85 
86  if (present(rel_tol) .and. present(abs_tol)) then
87  call this%ksp_init(max_iter, rel_tol, abs_tol)
88  else if (present(rel_tol)) then
89  call this%ksp_init(max_iter, rel_tol=rel_tol)
90  else if (present(abs_tol)) then
91  call this%ksp_init(max_iter, abs_tol=abs_tol)
92  else
93  call this%ksp_init(max_iter)
94  end if
95 
96  end subroutine cg_init
97 
99  subroutine cg_free(this)
100  class(cg_t), intent(inout) :: this
101 
102  call this%ksp_free()
103 
104  if (allocated(this%w)) then
105  deallocate(this%w)
106  end if
107 
108  if (allocated(this%r)) then
109  deallocate(this%r)
110  end if
111 
112  if (allocated(this%p)) then
113  deallocate(this%p)
114  end if
115 
116  if (allocated(this%z)) then
117  deallocate(this%z)
118  end if
119 
120  if (allocated(this%alpha)) then
121  deallocate(this%alpha)
122  end if
123 
124  nullify(this%M)
125 
126  end subroutine cg_free
127 
129  function cg_solve(this, Ax, x, f, n, coef, blst, gs_h, niter) result(ksp_results)
130  class(cg_t), intent(inout) :: this
131  class(ax_t), intent(inout) :: ax
132  type(field_t), intent(inout) :: x
133  integer, intent(in) :: n
134  real(kind=rp), dimension(n), intent(inout) :: f
135  type(coef_t), intent(inout) :: coef
136  type(bc_list_t), intent(inout) :: blst
137  type(gs_t), intent(inout) :: gs_h
138  type(ksp_monitor_t) :: ksp_results
139  integer, optional, intent(in) :: niter
140  integer :: iter, max_iter, i, j, k, p_cur, p_prev
141  real(kind=rp) :: rnorm, rtr, rtz2, rtz1, x_plus(neko_blk_size)
142  real(kind=rp) :: beta, pap, norm_fac
143 
144  if (present(niter)) then
145  max_iter = niter
146  else
147  max_iter = this%max_iter
148  end if
149  norm_fac = 1.0_rp / sqrt(coef%volume)
150 
151  associate(w => this%w, r => this%r, p => this%p, &
152  z => this%z, alpha => this%alpha)
153 
154  rtz1 = 1.0_rp
155  call rzero(x%x, n)
156  call rzero(p(1,cg_p_space), n)
157  call copy(r, f, n)
158 
159  rtr = glsc3(r, coef%mult, r, n)
160  rnorm = sqrt(rtr) * norm_fac
161  ksp_results%res_start = rnorm
162  ksp_results%res_final = rnorm
163  ksp_results%iter = 0
164  p_prev = cg_p_space
165  p_cur = 1
166  if(abscmp(rnorm, 0.0_rp)) return
167  do iter = 1, max_iter
168  call this%M%solve(z, r, n)
169  rtz2 = rtz1
170  rtz1 = glsc3(r, coef%mult, z, n)
171 
172  beta = rtz1 / rtz2
173  if (iter .eq. 1) beta = 0.0_rp
174  do i = 1, n
175  p(i,p_cur) = z(i) + beta * p(i,p_prev)
176  end do
177 
178  call ax%compute(w, p(1,p_cur), coef, x%msh, x%Xh)
179  call gs_h%op(w, n, gs_op_add)
180  call bc_list_apply(blst, w, n)
181 
182  pap = glsc3(w, coef%mult, p(1,p_cur), n)
183 
184  alpha(p_cur) = rtz1 / pap
185  call second_cg_part(rtr, r, coef%mult, w, alpha(p_cur), n)
186  rnorm = sqrt(rtr) * norm_fac
187 
188  if ((p_cur .eq. cg_p_space) .or. &
189  (rnorm .lt. this%abs_tol) .or. iter .eq. max_iter) then
190  do i = 0, n, neko_blk_size
191  if (i + neko_blk_size .le. n) then
192  do k = 1, neko_blk_size
193  x_plus(k) = 0.0_rp
194  end do
195  do j = 1, p_cur
196  do k = 1, neko_blk_size
197  x_plus(k) = x_plus(k) + alpha(j) * p(i+k,j)
198  end do
199  end do
200  do k = 1, neko_blk_size
201  x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(k)
202  end do
203  else
204  do k = 1, n-i
205  x_plus(1) = 0.0_rp
206  do j = 1, p_cur
207  x_plus(1) = x_plus(1) + alpha(j) * p(i+k,j)
208  end do
209  x%x(i+k,1,1,1) = x%x(i+k,1,1,1) + x_plus(1)
210  end do
211  end if
212  end do
213  p_prev = p_cur
214  p_cur = 1
215  if (rnorm .lt. this%abs_tol) exit
216  else
217  p_prev = p_cur
218  p_cur = p_cur + 1
219  end if
220  end do
221  end associate
222 
223  ksp_results%res_final = rnorm
224  ksp_results%iter = iter
225 
226  end function cg_solve
227 
228  subroutine second_cg_part(rtr, r, mult, w, alpha, n)
229  integer, intent(in) :: n
230  real(kind=rp), intent(inout) :: r(n), rtr
231  real(kind=rp), intent(in) ::mult(n), w(n), alpha
232  integer :: i, ierr
233 
234  rtr = 0.0_rp
235  do i = 1, n
236  r(i) = r(i) - alpha*w(i)
237  rtr = rtr + r(i) * r(i) * mult(i)
238  end do
239  call mpi_allreduce(mpi_in_place, rtr, 1, &
240  mpi_real_precision, mpi_sum, neko_comm, ierr)
241 
242  end subroutine second_cg_part
243 
244 end module cg
245 
246 
Defines a Matrix-vector product.
Definition: ax.f90:34
Defines a boundary condition.
Definition: bc.f90:34
Defines various Conjugate Gradient methods.
Definition: cg.f90:34
subroutine cg_free(this)
Deallocate a standard PCG solver.
Definition: cg.f90:100
integer, parameter cg_p_space
Definition: cg.f90:48
subroutine cg_init(this, n, max_iter, M, rel_tol, abs_tol)
Initialise a standard PCG solver.
Definition: cg.f90:67
type(ksp_monitor_t) function cg_solve(this, Ax, x, f, n, coef, blst, gs_h, niter)
Standard PCG solve.
Definition: cg.f90:130
subroutine second_cg_part(rtr, r, mult, w, alpha, n)
Definition: cg.f90:229
Coefficients.
Definition: coef.f90:34
Definition: comm.F90:1
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:50
Definition: math.f90:60
real(kind=rp) function, public glsc3(a, b, c, n)
Weighted inner product .
Definition: math.f90:810
subroutine, public copy(a, b, n)
Copy a vector .
Definition: math.f90:211
subroutine, public rzero(a, n)
Zero a real vector.
Definition: math.f90:167
integer, parameter, public rp
Global precision used in computations.
Definition: num_types.f90:12
Krylov preconditioner.
Definition: precon.f90:34
Base type for a matrix-vector product providing .
Definition: ax.f90:43
A list of boundary conditions.
Definition: bc.f90:102
Standard preconditioned conjugate gradient method.
Definition: cg.f90:51
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition: coef.f90:54
Type for storing initial and final residuals in a Krylov solver.
Definition: krylov.f90:55
Base abstract type for a canonical Krylov method, solving .
Definition: krylov.f90:65
Defines a canonical Krylov preconditioner.
Definition: precon.f90:40