source: codes/icosagcm/devel/src/dynamics/compute_NH_geopot.F90 @ 862

Last change on this file since 862 was 859, checked in by jisesh, 5 years ago

devel: separate module for compute_NH_geopot

File size: 6.3 KB
Line 
1MODULE compute_NH_geopot_mod
2  USE grid_param, ONLY : llm
3  IMPLICIT NONE
4  PRIVATE
5
6  LOGICAL, SAVE :: debug_hevi_solver = .FALSE.
7
8  PUBLIC :: compute_NH_geopot
9
10CONTAINS
11
12  SUBROUTINE compute_NH_geopot(tau, phis, m_ik, m_il, theta, W_il, Phi_il)
13    USE icosa
14    USE disvert_mod
15    USE caldyn_vars_mod
16    USE omp_para
17    REAL(rstd), PARAMETER :: pbot=1e5, rho_bot=1e6
18    REAL(rstd),INTENT(IN)    :: tau ! solve Phi-tau*dPhi/dt = Phi_rhs
19    REAL(rstd),INTENT(IN)    :: phis(iim*jjm)
20    REAL(rstd),INTENT(IN)    :: m_ik(iim*jjm,llm)
21    REAL(rstd),INTENT(IN)    :: m_il(iim*jjm,llm+1)
22    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm)
23    REAL(rstd),INTENT(IN)    :: W_il(iim*jjm,llm+1)   ! vertical momentum
24    REAL(rstd),INTENT(INOUT) :: Phi_il(iim*jjm,llm+1) ! geopotential
25
26    REAL(rstd) :: Phi_star_il(iim*jjm,llm+1) 
27    REAL(rstd) :: p_ik(iim*jjm,llm)      ! pressure
28    REAL(rstd) :: R_il(iim*jjm,llm+1)    ! rhs of tridiag problem
29    REAL(rstd) :: x_il(iim*jjm,llm+1)    ! solution of tridiag problem
30    REAL(rstd) :: A_ik(iim*jjm,llm)      ! off-diagonal coefficients of tridiag problem
31    REAL(rstd) :: B_il(iim*jjm,llm+1)    ! diagonal coefficients of tridiag problem
32    REAL(rstd) :: C_ik(iim*jjm,llm)      ! Thomas algorithm
33    REAL(rstd) :: D_il(iim*jjm,llm+1)    ! Thomas algorithm
34    REAL(rstd) :: gamma, rho_ij, X_ij, Y_ij
35    REAL(rstd) :: wil, tau2_g, g2, gm2, ml_g2, c2_mik, vreff
36
37    INTEGER    :: iter, ij, l, ij_omp_begin_ext, ij_omp_end_ext
38
39    CALL distrib_level(ij_begin_ext,ij_end_ext, ij_omp_begin_ext,ij_omp_end_ext)
40
41    IF(dysl) THEN
42#define PHI_BOT(ij) phis(ij)
43#include "../kernels_hex/compute_NH_geopot.k90"
44#undef PHI_BOT
45    ELSE
46!    FIXME : vertical OpenMP parallelism will not work
47   
48    tau2_g=tau*tau/g
49    g2=g*g
50    gm2 = g**-2
51    gamma = 1./(1.-kappa)
52   
53    ! compute Phi_star
54    DO l=1,llm+1
55       !DIR$ SIMD
56       DO ij=ij_begin_ext,ij_end_ext
57          Phi_star_il(ij,l) = Phi_il(ij,l) + tau*g2*(W_il(ij,l)/m_il(ij,l)-tau)
58       ENDDO
59    ENDDO
60
61    ! Newton-Raphson iteration : Phi_il contains current guess value
62    DO iter=1,5 ! 2 iterations should be enough
63
64       ! Compute pressure, A_ik
65       DO l=1,llm
66          !DIR$ SIMD
67          DO ij=ij_begin_ext,ij_end_ext
68             rho_ij = (g*m_ik(ij,l))/(Phi_il(ij,l+1)-Phi_il(ij,l))
69             X_ij = (cpp/preff)*kappa*theta(ij,l)*rho_ij
70             p_ik(ij,l) = preff*(X_ij**gamma)
71             c2_mik = gamma*p_ik(ij,l)/(rho_ij*m_ik(ij,l)) ! c^2 = gamma*R*T = gamma*p/rho
72             A_ik(ij,l) = c2_mik*(tau/g*rho_ij)**2
73          ENDDO
74       ENDDO
75
76       ! Compute residual, B_il
77       ! bottom interface l=1
78       !DIR$ SIMD
79       DO ij=ij_begin_ext,ij_end_ext
80          ml_g2 = gm2*m_il(ij,1) 
81          B_il(ij,1) = A_ik(ij,1) + ml_g2 + tau2_g*rho_bot
82          R_il(ij,1) = ml_g2*( Phi_il(ij,1)-Phi_star_il(ij,1))  &
83               + tau2_g*( p_ik(ij,1)-pbot+rho_bot*(Phi_il(ij,1)-phis(ij)) )
84       ENDDO
85       ! inner interfaces
86       DO l=2,llm
87          !DIR$ SIMD
88          DO ij=ij_begin_ext,ij_end_ext
89             ml_g2 = gm2*m_il(ij,l) 
90             B_il(ij,l) = A_ik(ij,l)+A_ik(ij,l-1) + ml_g2
91             R_il(ij,l) = ml_g2*( Phi_il(ij,l)-Phi_star_il(ij,l))  &
92                     + tau2_g*(p_ik(ij,l)-p_ik(ij,l-1))
93             ! consistency check : if Wil=0 and initial state is in hydrostatic balance
94             ! then Phi_star_il(ij,l) = Phi_il(ij,l) - tau^2*g^2
95             ! and residual = tau^2*(ml+(1/g)dl_pi)=0
96          ENDDO
97       ENDDO
98       ! top interface l=llm+1
99       !DIR$ SIMD
100       DO ij=ij_begin_ext,ij_end_ext
101          ml_g2 = gm2*m_il(ij,llm+1) 
102          B_il(ij,llm+1) = A_ik(ij,llm) + ml_g2
103          R_il(ij,llm+1) = ml_g2*( Phi_il(ij,llm+1)-Phi_star_il(ij,llm+1))  &
104               + tau2_g*( ptop-p_ik(ij,llm) )
105       ENDDO
106
107       ! FIXME later
108       ! the lines below modify the tridiag problem
109       ! for flat, rigid boundary conditions at top and bottom :
110       ! zero out A(1), A(llm), R(1), R(llm+1)
111       ! => x(l)=0 at l=1,llm+1
112       DO ij=ij_begin_ext,ij_end_ext
113          A_ik(ij,1) = 0.
114          A_ik(ij,llm) = 0.
115          R_il(ij,1) = 0.
116          R_il(ij,llm+1) = 0.
117       ENDDO
118
119       IF(debug_hevi_solver) THEN ! print Linf(residual)
120          PRINT *, '[hevi_solver] R,p', iter, MAXVAL(ABS(R_il)), MAXVAL(p_ik)
121       END IF
122
123       ! Solve -A(l-1)x(l-1) + B(l)x(l) - A(l)x(l+1) = R(l) using Thomas algorithm
124       ! Forward sweep :
125       ! C(0)=0, C(l) = -A(l) / (B(l)+A(l-1)C(l-1)),
126       ! D(0)=0, D(l) = (R(l)+A(l-1)D(l-1)) / (B(l)+A(l-1)C(l-1))
127       ! bottom interface l=1
128       !DIR$ SIMD
129       DO ij=ij_begin_ext,ij_end_ext
130          X_ij = 1./B_il(ij,1)
131          C_ik(ij,1) = -A_ik(ij,1) * X_ij 
132          D_il(ij,1) =  R_il(ij,1) * X_ij
133       ENDDO
134       ! inner interfaces/layers
135       DO l=2,llm
136          !DIR$ SIMD
137          DO ij=ij_begin_ext,ij_end_ext
138             X_ij = 1./(B_il(ij,l) + A_ik(ij,l-1)*C_ik(ij,l-1))
139             C_ik(ij,l) = -A_ik(ij,l) * X_ij 
140             D_il(ij,l) =  (R_il(ij,l)+A_ik(ij,l-1)*D_il(ij,l-1)) * X_ij
141          ENDDO
142       ENDDO
143       ! top interface l=llm+1
144       !DIR$ SIMD
145       DO ij=ij_begin_ext,ij_end_ext
146          X_ij = 1./(B_il(ij,llm+1) + A_ik(ij,llm)*C_ik(ij,llm))
147          D_il(ij,llm+1) =  (R_il(ij,llm+1)+A_ik(ij,llm)*D_il(ij,llm)) * X_ij
148       ENDDO
149       
150       ! Back substitution :
151       ! x(i) = D(i)-C(i)x(i+1), x(N+1)=0
152       ! + Newton-Raphson update
153       x_il=0. ! FIXME
154       ! top interface l=llm+1
155       !DIR$ SIMD
156       DO ij=ij_begin_ext,ij_end_ext
157          x_il(ij,llm+1) = D_il(ij,llm+1)
158          Phi_il(ij,llm+1) = Phi_il(ij,llm+1) - x_il(ij,llm+1)
159       ENDDO
160       ! lower interfaces
161       DO l=llm,1,-1
162          !DIR$ SIMD
163          DO ij=ij_begin_ext,ij_end_ext
164             x_il(ij,l) = D_il(ij,l) - C_ik(ij,l)*x_il(ij,l+1)
165             Phi_il(ij,l) = Phi_il(ij,l) - x_il(ij,l)
166          ENDDO
167       ENDDO
168
169       IF(debug_hevi_solver) THEN
170          PRINT *, '[hevi_solver] A,B', iter, MAXVAL(ABS(A_ik)),MAXVAL(ABS(B_il))
171          PRINT *, '[hevi_solver] C,D', iter, MAXVAL(ABS(C_ik)),MAXVAL(ABS(D_il))
172          DO l=1,llm+1
173             WRITE(*,'(A,I2.1,I3.2,E9.2)') '[hevi_solver] x', iter,l, MAXVAL(ABS(x_il(:,l)))
174          END DO
175       END IF
176
177    END DO ! Newton-Raphson
178
179    END IF ! dysl
180   
181  END SUBROUTINE compute_NH_geopot
182
183END MODULE compute_NH_geopot_mod
Note: See TracBrowser for help on using the repository browser.