source: codes/icosagcm/devel/src/dynamics/compute_caldyn_fast.F90

Last change on this file was 1027, checked in by dubos, 4 years ago

devel : towards conformity to F2008 standard

File size: 9.2 KB
Line 
1MODULE compute_caldyn_fast_mod
2  USE prec, ONLY : rstd
3  USE grid_param
4  USE earth_const
5  USE disvert_mod
6  USE omp_para
7  USE trace
8  IMPLICIT NONE
9  PRIVATE
10
11#include "../unstructured/unstructured.h90"
12
13  PUBLIC :: compute_caldyn_fast_unst, compute_caldyn_fast_hex, compute_caldyn_fast_manual
14
15CONTAINS
16
17#ifdef BEGIN_DYSL
18
19{% macro case_caldyn_fast(name) %}
20  CASE({{name}})
21    FORALL_CELLS()
22      ON_PRIMAL
23        Phi_ik = .5*(geopot(CELL)+geopot(UP(CELL)))
24        {{ caller() }}
25      END_BLOCK
26    END_BLOCK
27{%- endmacro %}
28
29KERNEL(caldyn_fast) 
30  !
31  SELECT CASE(caldyn_thermo)
32  CASE(thermo_boussinesq)
33     FORALL_CELLS()
34       ON_PRIMAL
35         berni(CELL) = pk(CELL)
36         ! from now on pk contains the vertically-averaged geopotential
37         pk(CELL) = .5*(geopot(CELL)+geopot(UP(CELL)))
38       END_BLOCK
39     END_BLOCK
40  {% call case_caldyn_fast('thermo_theta') %}
41     berni(CELL) = Phi_ik
42  {%- endcall %}
43  {% call case_caldyn_fast('thermo_entropy') %}
44     berni(CELL) = Phi_ik + pk(CELL)*(cpp-theta(CELL,1)) ! Gibbs = Cp.T-Ts = T(Cp-s)
45  {%- endcall %}
46  {% call case_caldyn_fast('thermo_variable_Cp') %}
47    ! thermodynamics with variable Cp
48    !           Cp(T) = Cp0 * (T/T0)^nu
49    ! =>            h = Cp(T).T/(nu+1)
50     cp_ik = cpp*(pk(ij,l)/Treff)**nu
51     berni(CELL) = Phi_ik + pk(CELL)*(cp_ik/(nu+1.)-theta(CELL,1)) ! Gibbs = h-Ts = T(Cp/(nu+1)-s)
52  {%- endcall %}
53  CASE DEFAULT
54    PRINT *, 'Unsupported value of caldyn_thermo : ',caldyn_thermo  ! FIXME
55    STOP
56  END SELECT
57!
58  FORALL_CELLS()
59    ON_EDGES
60      due = .5*(theta(CELL1,1)+theta(CELL2,1))*(pk(CELL2)-pk(CELL1)) + berni(CELL2)-berni(CELL1)
61      du(EDGE) = du(EDGE) - SIGN*due
62      u(EDGE) = u(EDGE) + tau*du(EDGE)
63    END_BLOCK
64  END_BLOCK 
65!
66END_BLOCK
67
68#endif END_DYSL
69
70!-------------- Wrappers for F2008 conformity -----------------
71
72  SUBROUTINE compute_caldyn_fast_hex(tau,theta,geopot, pk,berni,du,u)
73    REAL(rstd),INTENT(IN)    :: tau, theta(:,:,:), geopot(:,:)
74    REAL(rstd),INTENT(INOUT) :: pk(:,:), berni(:,:), du(:,:), u(:,:)
75    CALL compute_caldyn_fast_hex_(tau,theta,geopot, pk,berni,du,u)
76  END SUBROUTINE compute_caldyn_fast_hex
77
78  SUBROUTINE compute_caldyn_fast_unst(tau,theta,geopot, pk,berni,du,u)
79    REAL(rstd),INTENT(IN)    :: tau, theta(:,:,:), geopot(:,:)
80    REAL(rstd),INTENT(INOUT) :: pk(:,:), berni(:,:), du(:,:), u(:,:)
81    CALL compute_caldyn_fast_unst_(tau,theta,geopot, pk,berni,du,u)
82  END SUBROUTINE compute_caldyn_fast_unst
83
84!--------------------------------------------------------------
85
86  SUBROUTINE compute_caldyn_fast_unst_(tau,theta,geopot, pk,berni,du,u)
87    USE ISO_C_BINDING, only : C_DOUBLE, C_FLOAT
88    USE data_unstructured_mod, ONLY : enter_trace, exit_trace, &
89         id_fast, dual_deg, dual_edge, dual_ne, dual_vertex, &
90         up, down, left, right
91    NUM, INTENT(IN) :: tau
92    FIELD_MASS   :: pk,berni  ! INOUT, OUT
93    FIELD_THETA  :: theta     ! IN
94    FIELD_GEOPOT :: geopot    ! IN
95    FIELD_U      :: u,du      ! INOUT,INOUT
96    DECLARE_INDICES
97    DECLARE_EDGES
98    NUM          :: due, cp_ik, Phi_ik
99    START_TRACE(id_fast, 4,0,2) ! primal, dual, edge
100#include "../kernels_unst/caldyn_fast.k90"
101    STOP_TRACE
102  END SUBROUTINE compute_caldyn_fast_unst_
103
104  SUBROUTINE compute_caldyn_fast_hex_(tau,theta,geopot, pk,berni,du,u)
105    USE icosa
106    REAL(rstd),INTENT(IN)    :: tau                ! "solve" u-tau*du/dt = rhs
107    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm,nqdyn)
108    REAL(rstd),INTENT(IN)    :: geopot(iim*jjm,llm+1)
109    REAL(rstd),INTENT(INOUT) :: pk(iim*jjm,llm)
110    REAL(rstd),INTENT(INOUT) :: berni(iim*jjm,llm)  ! partial Bernoulli function
111    REAL(rstd),INTENT(INOUT) :: du(iim*3*jjm,llm)
112    REAL(rstd),INTENT(INOUT) :: u(iim*3*jjm,llm)   ! INOUT if tau>0
113    REAL(rstd) :: berniv(iim*jjm,llm)  ! moist Bernoulli function
114
115    INTEGER :: ij,l
116    REAL(rstd) :: due, cp_ik, Phi_ik
117
118    CALL trace_start("compute_caldyn_fast")
119#include "../kernels_hex/caldyn_fast.k90"
120    CALL trace_end("compute_caldyn_fast")
121   
122  END SUBROUTINE compute_caldyn_fast_hex_
123
124  SUBROUTINE compute_caldyn_fast_manual(tau,theta,geopot, pk,berni,du,u)
125    USE icosa
126    REAL(rstd),INTENT(IN)    :: tau                ! "solve" u-tau*du/dt = rhs
127    REAL(rstd),INTENT(IN)    :: theta(iim*jjm,llm,nqdyn)
128    REAL(rstd),INTENT(IN)    :: geopot(iim*jjm,llm+1)
129    REAL(rstd),INTENT(INOUT) :: pk(iim*jjm,llm)
130    REAL(rstd),INTENT(INOUT) :: berni(iim*jjm,llm)  ! partial Bernoulli function
131    REAL(rstd),INTENT(INOUT) :: du(iim*3*jjm,llm)
132    REAL(rstd),INTENT(INOUT) :: u(iim*3*jjm,llm)   ! INOUT if tau>0
133    REAL(rstd) :: berniv(iim*jjm,llm)  ! moist Bernoulli function
134
135    INTEGER :: ij,l
136    REAL(rstd) :: cp_ik, qv, temp, chi, log_p_preff, due, due_right, due_lup, due_ldown
137
138    CALL trace_start("compute_caldyn_fast")
139
140    ! Compute Bernoulli term
141    IF(boussinesq) THEN
142       DO l=ll_begin,ll_end
143          !DIR$ SIMD
144          DO ij=ij_begin,ij_end         
145             berni(ij,l) = pk(ij,l)
146             ! from now on pk contains the vertically-averaged geopotential
147             pk(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1))
148          END DO
149       END DO
150    ELSE ! compressible
151
152       DO l=ll_begin,ll_end
153          SELECT CASE(caldyn_thermo)
154          CASE(thermo_theta) ! vdp = theta.dpi => B = Phi
155             !DIR$ SIMD
156             DO ij=ij_begin,ij_end         
157                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1))
158             END DO
159          CASE(thermo_entropy) ! vdp = dG + sdT => B = Phi + G, G=h-Ts=T*(cpp-s)
160             !DIR$ SIMD
161             DO ij=ij_begin,ij_end         
162                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
163                     + pk(ij,l)*(cpp-theta(ij,l,1)) ! pk=temperature, theta=entropy
164             END DO
165          CASE(thermo_moist) 
166             !DIR$ SIMD
167             DO ij=ij_begin,ij_end         
168                ! du/dt = grad(Bd)+rv.grad(Bv)+s.grad(T)
169                ! Bd = Phi + gibbs_d
170                ! Bv = Phi + gibbs_v
171                ! pk=temperature, theta=entropy
172                qv = theta(ij,l,2)
173                temp = pk(ij,l)
174                chi = log(temp/Treff)
175                log_p_preff = (chi*(cpp+qv*cppv)-theta(ij,l,1))/(Rd+qv*Rv) ! log(p/preff)
176                berni(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
177                     + temp*(cpp*(1.-chi)+Rd*log_p_preff)
178                berniv(ij,l) = .5*(geopot(ij,l)+geopot(ij,l+1)) &
179                     + temp*(cppv*(1.-chi)+Rv*log_p_preff)
180            END DO
181          END SELECT
182       END DO
183
184    END IF ! Boussinesq/compressible
185
186!!! u:=u+tau*du, du = -grad(B)-theta.grad(pi)
187    DO l=ll_begin,ll_end
188       IF(caldyn_thermo == thermo_moist) THEN
189          !DIR$ SIMD
190          DO ij=ij_begin,ij_end         
191             due_right =  berni(ij+t_right,l)-berni(ij,l)       &
192                  + 0.5*(theta(ij,l,1)+theta(ij+t_right,l,1))   &
193                       *(pk(ij+t_right,l)-pk(ij,l))             &
194                  + 0.5*(theta(ij,l,2)+theta(ij+t_right,l,2))   &
195                       *(berniv(ij+t_right,l)-berniv(ij,l))
196             
197             due_lup = berni(ij+t_lup,l)-berni(ij,l)            &
198                  + 0.5*(theta(ij,l,1)+theta(ij+t_lup,l,1))     &
199                       *(pk(ij+t_lup,l)-pk(ij,l))               &
200                  + 0.5*(theta(ij,l,2)+theta(ij+t_lup,l,2))     &
201                       *(berniv(ij+t_lup,l)-berniv(ij,l))
202             
203             due_ldown = berni(ij+t_ldown,l)-berni(ij,l)        &
204                  + 0.5*(theta(ij,l,1)+theta(ij+t_ldown,l,1))   &
205                       *(pk(ij+t_ldown,l)-pk(ij,l))             &
206                  + 0.5*(theta(ij,l,2)+theta(ij+t_ldown,l,2))   &
207                       *(berniv(ij+t_ldown,l)-berniv(ij,l))
208             
209             du(ij+u_right,l) = du(ij+u_right,l) - ne_right*due_right
210             du(ij+u_lup,l)   = du(ij+u_lup,l)   - ne_lup*due_lup
211             du(ij+u_ldown,l) = du(ij+u_ldown,l) - ne_ldown*due_ldown
212             u(ij+u_right,l) = u(ij+u_right,l) + tau*du(ij+u_right,l)
213             u(ij+u_lup,l)   = u(ij+u_lup,l)   + tau*du(ij+u_lup,l)
214             u(ij+u_ldown,l) = u(ij+u_ldown,l) + tau*du(ij+u_ldown,l)
215          END DO
216       ELSE
217          !DIR$ SIMD
218          DO ij=ij_begin,ij_end         
219             due_right =  0.5*(theta(ij,l,1)+theta(ij+t_right,l,1))  &
220                  *(pk(ij+t_right,l)-pk(ij,l))        &
221                  +  berni(ij+t_right,l)-berni(ij,l)
222             due_lup = 0.5*(theta(ij,l,1)+theta(ij+t_lup,l,1))    &
223                  *(pk(ij+t_lup,l)-pk(ij,l))          &
224                  +  berni(ij+t_lup,l)-berni(ij,l)
225             due_ldown = 0.5*(theta(ij,l,1)+theta(ij+t_ldown,l,1)) &
226                  *(pk(ij+t_ldown,l)-pk(ij,l))      &
227                  +   berni(ij+t_ldown,l)-berni(ij,l)
228             du(ij+u_right,l) = du(ij+u_right,l) - ne_right*due_right
229             du(ij+u_lup,l)   = du(ij+u_lup,l)   - ne_lup*due_lup
230             du(ij+u_ldown,l) = du(ij+u_ldown,l) - ne_ldown*due_ldown
231             u(ij+u_right,l) = u(ij+u_right,l) + tau*du(ij+u_right,l)
232             u(ij+u_lup,l)   = u(ij+u_lup,l)   + tau*du(ij+u_lup,l)
233             u(ij+u_ldown,l) = u(ij+u_ldown,l) + tau*du(ij+u_ldown,l)
234          END DO
235       END IF
236    END DO
237
238    CALL trace_end("compute_caldyn_fast")
239
240  END SUBROUTINE compute_caldyn_fast_manual
241
242END MODULE compute_caldyn_fast_mod
Note: See TracBrowser for help on using the repository browser.