FV3 Bundle
solve_helmholz.f90
Go to the documentation of this file.
1 ! (C) Copyright 2009-2016 ECMWF.
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 ! In applying this licence, ECMWF does not waive the privileges and immunities
6 ! granted to it by virtue of its status as an intergovernmental organisation nor
7 ! does it submit to any jurisdiction.
8 
9 !> Solve a Helmholz equation.
10 
11 !> This routine solves the Helmholz equation:
12 !! \f$ \nabla^2 \psi + c \psi = b \f$,
13 !! where \f$ c \f$ is a constant, and where \f$ \nabla^2 \f$ is the
14 !! two-dimensional, 5-point finite-difference Laplacian.
15 !!
16 !! The solution method is to apply an FFT in the zonal direction. This
17 !! reduces the problem to a set of un-coupled tri-diagonal systems that
18 !! are solved with the standard back-substitution algorithm.
19 
20 subroutine solve_helmholz (x,b,c,nx,ny,deltax,deltay)
22 use kinds
23 implicit none
24 
25 integer, intent(in) :: nx !< Zonal grid dimension
26 integer, intent(in) :: ny !< Meridional grid dimension
27 real(kind=kind_real), intent(out) :: x(nx,ny) !< Solution
28 real(kind=kind_real), intent(in) :: b(nx,ny) !< Right hand side
29 real(kind=kind_real), intent(in) :: c !< Coefficient in the linear operator
30 real(kind=kind_real), intent(in) :: deltax !< Zonal grid spacing (non-dimensional)
31 real(kind=kind_real), intent(in) :: deltay !< Meridional grid spacing (non-dimensional)
32 
33 real(kind=kind_real) :: v(ny), z(ny), bext(nx+2,ny), xext(nx+2,ny)
34 real(kind=kind_real) :: pi, am, bm, w
35 integer :: k, i, iri, jj
36 
37 x(:,:) = 0.0_kind_real
38 
39 if (maxval(abs(b))>0.0_kind_real) then
40 
41  !--- transform
42  do jj=1,ny
43  call fft_fwd(nx,b(:,jj),bext(:,jj))
44  enddo
45 
46  pi = 4.0_kind_real*atan(1.0_kind_real)
47 
48  !--- loop over wavenumber
49 
50  do k=0,nx/2
51 
52  !--- solve the tri-diagonal systems
53 
54  am = c + 2.0_kind_real*( cos( 2.0_kind_real*real(k,kind_real)*pi &
55  /real(nx,kind_real)) &
56  -1.0_kind_real)/(deltax*deltax) &
57  - 2.0_kind_real/(deltay*deltay)
58 
59  bm = 1.0_kind_real/(deltay*deltay)
60 
61  do iri=1,2
62  v(1) = bm/am
63  z(1) = bext(2*k+iri,1)/am
64 
65  do i=2,ny
66  w = am-bm*v(i-1)
67  v(i) = bm/w
68  z(i) = (bext(2*k+iri,i)-bm*z(i-1))/w
69  enddo
70 
71  xext(2*k+iri,ny) = z(ny)
72  do i=ny-1,1,-1
73  xext(2*k+iri,i) = z(i) - v(i)*xext(2*k+iri,i+1)
74  enddo
75  enddo
76  enddo
77 
78  !--- transform back
79  do jj=1,ny
80  call fft_inv(nx,xext(:,jj),x(:,jj))
81  enddo
82 
83 endif
84 
85 end subroutine solve_helmholz
subroutine, public fft_inv(kk, pf, pg)
Definition: fft_mod.F90:66
Fortran module for Eigen FFTs.
Definition: fft.F90:24
subroutine solve_helmholz(x, b, c, nx, ny, deltax, deltay)
Solve a Helmholz equation.
subroutine, public fft_fwd(kk, pg, pf)
Definition: fft_mod.F90:49