source: codes/icosagcm/devel/src/dynamics/compute_caldyn_solver.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: 4.6 KB
Line 
1MODULE compute_caldyn_solver_mod
2  USE grid_param, ONLY : llm
3  IMPLICIT NONE
4  PRIVATE
5
6  PUBLIC :: compute_caldyn_solver
7
8CONTAINS
9
10  SUBROUTINE compute_caldyn_solver(tau,phis, rhodz,theta,pk, geopot,W, m_il,pres, dPhi,dW,du)
11    USE icosa
12    USE caldyn_vars_mod
13    USE trace
14    USE omp_para, ONLY : ll_begin, ll_end,ll_beginp1,ll_endp1
15    USE disvert_mod, ONLY : ptop
16    USE caldyn_kernels_hevi_mod
17    USE compute_NH_geopot_mod
18    REAL(rstd), PARAMETER :: pbot=1e5, rho_bot=1e6
19    REAL(rstd),INTENT(IN) :: tau ! "solve" Phi-tau*dPhi/dt = Phi_rhs
20    REAL(rstd),INTENT(IN)    :: phis(iim*jjm)
21    REAL(rstd),INTENT(IN)    :: rhodz(iim*jjm,llm)
22    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm,nqdyn)
23    REAL(rstd),INTENT(OUT)   :: pk(iim*jjm,llm)
24    REAL(rstd),INTENT(INOUT) :: geopot(iim*jjm,llm+1)
25    REAL(rstd),INTENT(INOUT) :: W(iim*jjm,llm+1) ! OUT if tau>0
26    REAL(rstd),INTENT(OUT)   :: m_il(iim*jjm,llm+1)        ! rhodz averaged to interfaces
27    REAL(rstd),INTENT(OUT)   :: pres(iim*jjm,llm)          ! pressure
28    REAL(rstd),INTENT(OUT)   :: dW(iim*jjm,llm+1)
29    REAL(rstd),INTENT(OUT)   :: dPhi(iim*jjm,llm+1)
30    REAL(rstd),INTENT(OUT)   :: du(3*iim*jjm,llm)
31
32    REAL(rstd) :: berni(iim*jjm,llm)         ! (W/m_il)^2
33    REAL(rstd) :: berni1(iim*jjm)         ! (W/m_il)^2
34    !REAL(rstd) :: gamma, rho_ij, T_ij, X_ij, Y_ij, vreff, Rd, Cvd, Rd_preff
35    REAL(rstd) :: gamma, rho_ij, T_ij, X_ij, Y_ij, vreff, Cvd, Rd_preff
36    INTEGER    :: ij, l
37
38    CALL trace_start("compute_caldyn_solver")
39
40    !Rd=cpp*kappa
41
42    IF(dysl) THEN
43
44!$OMP BARRIER
45
46#include "../kernels_hex/caldyn_mil.k90"
47  IF(tau>0) THEN ! solve implicit problem for geopotential
48    CALL compute_NH_geopot(tau,phis, rhodz, m_il, theta, W, geopot)
49  END IF
50#define PHI_BOT(ij) phis(ij)
51#include "../kernels_hex/caldyn_solver.k90"
52#undef PHI_BOT
53!$OMP BARRIER
54
55    ELSE
56
57#define BERNI(ij) berni1(ij)
58    ! FIXME : vertical OpenMP parallelism will not work
59
60    ! average m_ik to interfaces => m_il
61    !DIR$ SIMD
62    DO ij=ij_begin_ext,ij_end_ext
63       m_il(ij,1) = .5*rhodz(ij,1)
64    ENDDO
65    DO l=2,llm
66       !DIR$ SIMD
67       DO ij=ij_begin_ext,ij_end_ext
68          m_il(ij,l) = .5*(rhodz(ij,l-1)+rhodz(ij,l))
69       ENDDO
70    ENDDO
71    !DIR$ SIMD
72    DO ij=ij_begin_ext,ij_end_ext
73       m_il(ij,llm+1) = .5*rhodz(ij,llm)
74    ENDDO
75
76    IF(tau>0) THEN ! solve implicit problem for geopotential
77       CALL compute_NH_geopot(tau, phis, rhodz, m_il, theta, W, geopot)
78    END IF
79
80    ! Compute pressure, stored temporarily in pk
81    ! kappa = R/Cp
82    ! 1-kappa = Cv/Cp
83    ! Cp/Cv = 1/(1-kappa)
84    gamma = 1./(1.-kappa)
85    DO l=1,llm
86       !DIR$ SIMD
87       DO ij=ij_begin_ext,ij_end_ext
88          rho_ij = (g*rhodz(ij,l))/(geopot(ij,l+1)-geopot(ij,l))
89          X_ij = (cpp/preff)*kappa*theta(ij,l,1)*rho_ij
90          ! kappa.theta.rho = p/exner
91          ! => X = (p/p0)/(exner/Cp)
92          !      = (p/p0)^(1-kappa)
93          pk(ij,l) = preff*(X_ij**gamma)
94       ENDDO
95    ENDDO
96
97    ! Update W, compute tendencies
98    DO l=2,llm
99       !DIR$ SIMD
100       DO ij=ij_begin_ext,ij_end_ext
101          dW(ij,l)   = (1./g)*(pk(ij,l-1)-pk(ij,l)) - m_il(ij,l)
102          W(ij,l)    = W(ij,l)+tau*dW(ij,l) ! update W
103          dPhi(ij,l) = g*g*W(ij,l)/m_il(ij,l)
104       ENDDO
105       !       PRINT *,'Max dPhi', l,ij_begin,ij_end, MAXVAL(abs(dPhi(ij_begin:ij_end,l)))
106       !       PRINT *,'Max dW', l,ij_begin,ij_end, MAXVAL(abs(dW(ij_begin:ij_end,l)))
107    ENDDO
108    ! Lower BC (FIXME : no orography yet !)
109    DO ij=ij_begin,ij_end         
110       dPhi(ij,1)=0
111       W(ij,1)=0
112       dW(ij,1)=0
113       dPhi(ij,llm+1)=0 ! rigid lid
114       W(ij,llm+1)=0
115       dW(ij,llm+1)=0
116    ENDDO
117    ! Upper BC p=ptop
118    !    DO ij=ij_omp_begin_ext,ij_omp_end_ext
119    !       dPhi(ij,llm+1) = W(ij,llm+1)/rhodz(ij,llm)
120    !       dW(ij,llm+1) = (1./g)*(pk(ij,llm)-ptop) - .5*rhodz(ij,llm)
121    !    ENDDO
122   
123    ! Compute Exner function (needed by compute_caldyn_fast) and du=-g^2.grad(w^2)
124    DO l=1,llm
125       !DIR$ SIMD
126       DO ij=ij_begin_ext,ij_end_ext
127          pk(ij,l) = cpp*((pk(ij,l)/preff)**kappa) ! other formulae possible if exponentiation is slow
128          BERNI(ij) = (-.25*g*g)*(              &
129                 (W(ij,l)/m_il(ij,l))**2       &
130               + (W(ij,l+1)/m_il(ij,l+1))**2 )
131       ENDDO
132       DO ij=ij_begin,ij_end         
133          du(ij+u_right,l) = ne_right*(BERNI(ij)-BERNI(ij+t_right))
134          du(ij+u_lup,l)   = ne_lup  *(BERNI(ij)-BERNI(ij+t_lup))
135          du(ij+u_ldown,l) = ne_ldown*(BERNI(ij)-BERNI(ij+t_ldown))
136       ENDDO
137    ENDDO
138#undef BERNI
139
140    END IF ! dysl
141
142    CALL trace_end("compute_caldyn_solver")
143   
144  END SUBROUTINE compute_caldyn_solver
145 
146END MODULE compute_caldyn_solver_mod
Note: See TracBrowser for help on using the repository browser.