FV3 Bundle
solve_elliptic_system.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 !> Solves the elliptic system that arises when inverting potential vorticity.
10 
11 !> Here, we are solving the coupled system:
12 !! \f{eqnarray}{
13 !! \nabla^2 \psi_1 - F_1 (\psi_1 -\psi_2 ) &=& p_1 \\\\
14 !! \nabla^2 \psi_2 - F_2 (\psi_2 -\psi_1 ) &=& p_2 \nonumber
15 !! \f}
16 !! where the subscript refers to model level, and
17 !! \f$ \nabla^2 \f$ is the 5-point finite-difference two-dimensional Laplacian.
18 !!
19 !! We reduce this to a 2D problem, which we solve for
20 !! \f$ \nabla^2 \psi_1 \f$:
21 !! \f[
22 !! \nabla^2 \left(\nabla^2 \psi_1 \right) - (F_1 + F_2 ) \nabla^2 \psi_1 =
23 !! \nabla^2 p_1 - F_2 p_1 - F_1 p_2
24 !! \f]
25 !!
26 !! Having found \f$ \nabla^2 \psi_1 \f$, we invert the Laplacian
27 !! to determine \f$ \psi_1 \f$, and then get \f$ \psi_2 \f$ by substitution
28 !! in equation 1 above.
29 
30 subroutine solve_elliptic_system (x,pv,nx,ny,deltax,deltay,F1,F2)
31 
32 !--- invert potential vorticity to get streamfunction
33 
34 use kinds
35 implicit none
36 
37 integer, intent(in) :: nx !< Zonal grid dimension
38 integer, intent(in) :: ny !< Meridional grid dimension
39 real(kind=kind_real), intent(out) :: x(nx,ny,2) !< Streamfunction
40 real(kind=kind_real), intent(in) :: pv(nx,ny,2) !< Right hand side
41 real(kind=kind_real), intent(in) :: deltax !< Zonal grid spacing (non-dimensional)
42 real(kind=kind_real), intent(in) :: deltay !< Meridional grid spacing (non-dimensional)
43 real(kind=kind_real), intent(in) :: F1 !< Coefficient in the PV operator
44 real(kind=kind_real), intent(in) :: F2 !< Coefficient in the PV operator
45 
46 real(kind=kind_real) :: rhs(nx,ny), del2x1(nx,ny)
47 
48 !--- Solve the 2D problem
49 
50 call laplacian_2d (pv(:,:,1),rhs,nx,ny,deltax,deltay)
51 rhs(:,:) = rhs(:,:) - f2*pv(:,:,1) - f1*pv(:,:,2)
52 
53 call solve_helmholz (del2x1,rhs,-(f1+f2),nx,ny,deltax,deltay)
54 
55 !--- Invert Laplacian to get x on level 1
56 
57 call solve_helmholz (x(:,:,1),del2x1,0.0_kind_real,nx,ny,deltax,deltay)
58 
59 !--- Calculate x on level 2
60 
61 x(:,:,2) = x(:,:,1) + (pv(:,:,1)-del2x1(:,:))*(1.0_kind_real/f1)
62 
63 end subroutine solve_elliptic_system
subroutine solve_helmholz(x, b, c, nx, ny, deltax, deltay)
Solve a Helmholz equation.
subroutine solve_elliptic_system(x, pv, nx, ny, deltax, deltay, F1, F2)
Solves the elliptic system that arises when inverting potential vorticity.
subroutine laplacian_2d(x, del2x, nx, ny, deltax, deltay)
Horizontal Laplacian operator.