source: codes/icosagcm/devel/src/initial/etat0_collocated.f90 @ 879

Last change on this file since 879 was 856, checked in by dubos, 5 years ago

devel : towards Fortran driver for unstructured/LAM meshes

File size: 10.5 KB
Line 
1MODULE etat0_collocated_mod
2  USE icosa
3  USE grid_param
4  USE omp_para, ONLY : is_omp_level_master
5  USE caldyn_vars_mod, ONLY : hydrostatic
6  IMPLICIT NONE         
7  PRIVATE
8
9  CHARACTER(len=255),SAVE :: etat0_type
10!$OMP THREADPRIVATE(etat0_type)
11
12    PUBLIC :: etat0_type, etat0_collocated
13
14! Important notes for OpenMP
15! When etat0 is called, vertical OpenMP parallelism is deactivated.
16! Therefore only the omp_level_master thread must work, i.e. :
17!   !$OMP BARRIER
18!    DO ind=1,ndomain
19!      IF (.NOT. assigned_domain(ind) .OR. .NOT. is_omp_level_master) CYCLE
20!      ...
21!    END DO
22!   !$OMP BARRIER
23! There MUST be NO OMP BARRIER inside the DO-LOOP or any routine it calls.
24
25CONTAINS
26 
27  SUBROUTINE etat0_collocated(f_phis,f_ps,f_mass,f_theta_rhodz,f_u, f_geopot,f_W, f_q)
28    USE theta2theta_rhodz_mod
29    TYPE(t_field),POINTER :: f_ps(:)
30    TYPE(t_field),POINTER :: f_mass(:)
31    TYPE(t_field),POINTER :: f_phis(:)
32    TYPE(t_field),POINTER :: f_theta_rhodz(:)
33    TYPE(t_field),POINTER :: f_u(:)
34    TYPE(t_field),POINTER :: f_geopot(:)
35    TYPE(t_field),POINTER :: f_W(:)
36    TYPE(t_field),POINTER :: f_q(:)
37 
38    TYPE(t_field),POINTER,SAVE :: f_temp(:) ! SAVE => all threads see the same f_temp
39    REAL(rstd),POINTER :: ps(:)
40    REAL(rstd),POINTER :: mass(:,:)
41    REAL(rstd),POINTER :: phis(:)
42    REAL(rstd),POINTER :: theta_rhodz(:,:,:)
43    REAL(rstd),POINTER :: temp(:,:)
44    REAL(rstd),POINTER :: u(:,:)
45    REAL(rstd),POINTER :: geopot(:,:)
46    REAL(rstd),POINTER :: W(:,:)
47    REAL(rstd),POINTER :: q(:,:,:)
48    INTEGER :: ind
49
50    CALL allocate_field(f_temp,field_t,type_real,llm,name='temp')
51
52    DO ind=1,ndomain
53      IF (.NOT. assigned_domain(ind) .OR. .NOT. is_omp_level_master) CYCLE
54      CALL swap_dimensions(ind)
55      CALL swap_geometry(ind)
56      ps=f_ps(ind)
57      mass=f_mass(ind)
58      phis=f_phis(ind)
59      theta_rhodz=f_theta_rhodz(ind)
60      temp=f_temp(ind)
61      u=f_u(ind)
62      geopot=f_geopot(ind)
63      w=f_w(ind)
64      q=f_q(ind)
65
66      SELECT CASE(grid_type)
67      CASE(grid_ico)
68         CALL compute_etat0_collocated_hex(phis, ps, mass, theta_rhodz(:,:,1), u, geopot, W, q)
69      CASE(grid_unst)
70         CALL compute_etat0_collocated_unst(phis, ps, mass, theta_rhodz(:,:,1), u, geopot, W, q)
71      CASE DEFAULT
72         STOP 'Unexpected value of grid_type encountered in etat0_collocated.'
73      END SELECT
74
75    ENDDO
76   
77    CALL deallocate_field(f_temp)
78   
79  END SUBROUTINE etat0_collocated
80
81  SUBROUTINE compute_etat0_collocated_hex(phis,ps,mass,theta_rhodz,u, geopot,W, q)
82    REAL(rstd),INTENT(INOUT) :: ps(iim*jjm)
83    REAL(rstd),INTENT(INOUT) :: mass(iim*jjm,llm)
84    REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm)
85    REAL(rstd),INTENT(OUT) :: phis(iim*jjm)
86    REAL(rstd),INTENT(OUT) :: u(3*iim*jjm,llm)
87    REAL(rstd),INTENT(OUT) :: W(iim*jjm,llm+1)
88    REAL(rstd),INTENT(OUT) :: geopot(iim*jjm,llm+1)
89    REAL(rstd),INTENT(OUT) :: q(iim*jjm,llm,nqtot)
90
91    REAL(rstd) :: ps_e(3*iim*jjm)
92    REAL(rstd) :: phis_e(3*iim*jjm)
93    REAL(rstd) :: mass_e(3*iim*jjm,llm)
94    REAL(rstd) :: geopot_e(3*iim*jjm,llm+1)
95    REAL(rstd) :: q_e(3*iim*jjm,llm,nqtot)
96
97    w(:,:) = 0
98    CALL compute_etat0_collocated(iim*jjm  , lon_i, lat_i, phis,   ps,   mass,   theta_rhodz, geopot,   q)
99    CALL compute_etat0_collocated(3*iim*jjm, lon_e, lat_e, phis_e, ps_e, mass_e, mass_e, geopot_e, q_e, ep_e, u)
100
101  END SUBROUTINE compute_etat0_collocated_hex
102
103  SUBROUTINE compute_etat0_collocated_unst(phis,ps,mass,theta_rhodz,u, geopot,W, q)
104    REAL(rstd),INTENT(INOUT) :: ps(primal_num)
105    REAL(rstd),INTENT(INOUT) :: mass(llm,primal_num)
106    REAL(rstd),INTENT(OUT) :: theta_rhodz(llm,primal_num)
107    REAL(rstd),INTENT(OUT) :: phis(primal_num)
108    REAL(rstd),INTENT(OUT) :: u(llm, edge_num)
109    REAL(rstd),INTENT(OUT) :: W(llm+1, primal_num)
110    REAL(rstd),INTENT(OUT) :: geopot(llm+1, primal_num)
111    REAL(rstd),INTENT(OUT) :: q(llm, primal_num, nqtot)
112    ! The 2D/3D arrays below have the shape expected by compute_etat0_collocated
113    REAL(rstd) :: ps_e(edge_num)
114    REAL(rstd) :: phis_e(edge_num)
115    REAL(rstd) :: u_e(edge_num, llm)
116    REAL(rstd) :: mass_i(primal_num, llm), theta_rhodz_i(primal_num, llm), mass_e(edge_num, llm)
117    REAL(rstd) :: geopot_i(edge_num, llm+1), geopot_e(edge_num, llm+1)
118    REAL(rstd) :: q_i(primal_num, llm, nqtot), q_e(edge_num, llm, nqtot)
119    INTEGER :: iq
120
121    w(:,:) = 0
122    CALL compute_etat0_collocated(primal_num  , lon_i, lat_i, phis,   ps,   mass_i,   theta_rhodz_i, geopot_i,   q_i)
123    CALL compute_etat0_collocated(edge_num, lon_e, lat_e, phis_e, ps_e, mass_e, mass_e, geopot_e, q_e, ep_e, u_e)
124    mass = TRANSPOSE(mass_i)
125    theta_rhodz = TRANSPOSE(theta_rhodz_i)
126    geopot = TRANSPOSE(geopot_i)
127    u = TRANSPOSE(u_e)
128    DO iq=1,nqtot
129       q(:,:,iq) = TRANSPOSE(q_i(:,:,iq))
130    END DO
131  END SUBROUTINE compute_etat0_collocated_unst
132 
133  SUBROUTINE compute_etat0_collocated(ngrid, lon, lat, phis, ps, mass, theta_rhodz, geopot, q, ep, uperp)
134    USE etat0_isothermal_mod, ONLY : compute_isothermal => compute_etat0
135    USE etat0_jablonowsky06_mod, ONLY : compute_jablonowsky06 => compute_etat0
136    USE etat0_dcmip1_mod, ONLY : compute_dcmip1 => compute_etat0
137    USE etat0_dcmip2_mod, ONLY : compute_dcmip2 => compute_etat0
138    USE etat0_dcmip3_mod, ONLY : compute_dcmip3 => compute_etat0
139    USE etat0_dcmip4_mod, ONLY : compute_dcmip4 => compute_etat0
140    USE etat0_dcmip5_mod, ONLY : compute_dcmip5 => compute_etat0
141    USE etat0_bubble_mod, ONLY : compute_bubble => compute_etat0 
142    USE etat0_williamson_mod, ONLY : compute_w91_6 => compute_etat0
143    USE etat0_temperature_mod, ONLY: compute_temperature => compute_etat0
144    USE etat0_dcmip2016_baroclinic_wave_mod, ONLY : compute_dcmip2016_baroclinic_wave => compute_etat0
145    USE etat0_dcmip2016_cyclone_mod, ONLY : compute_dcmip2016_cyclone => compute_etat0
146    USE etat0_dcmip2016_supercell_mod, ONLY : compute_dcmip2016_supercell => compute_etat0
147    USE disvert_mod, ONLY : ptop, ap, bp, mass_ak, mass_bk, mass_dak, mass_dbk
148    INTEGER :: ngrid
149    REAL(rstd),INTENT(IN)    :: lon(ngrid), lat(ngrid)
150    REAL(rstd),INTENT(INOUT) :: ps(ngrid)
151    REAL(rstd),INTENT(INOUT) :: mass(ngrid,llm)
152    REAL(rstd),INTENT(OUT)   :: theta_rhodz(ngrid,llm)
153    REAL(rstd),INTENT(OUT)   :: phis(ngrid)
154    REAL(rstd),INTENT(OUT)   :: geopot(ngrid,llm+1)
155    REAL(rstd),INTENT(OUT)   :: q(ngrid,llm,nqtot)
156    REAL(rstd),INTENT(OUT), OPTIONAL   :: ep(ngrid,3), uperp(ngrid,llm)
157
158    REAL(rstd)   :: ulon(ngrid,llm)
159    REAL(rstd)   :: ulat(ngrid,llm)
160    REAL(rstd)   :: temp(ngrid,llm)
161
162    LOGICAL :: autoinit_mass, autoinit_NH
163    INTEGER :: ij,l
164    REAL(rstd) :: clat, slat, clon, slon, u3d(3), p_ik, mass_ik, v_ik
165    REAL(rstd) :: q_ik, r_ik, chi, entropy, theta, log_p_preff
166
167    ! For NH, geopotential and vertical momentum must be initialized.
168    ! Unless autoinit_NH is set to .FALSE. , they will be initialized
169    ! to hydrostatic geopotential and zero
170    autoinit_mass = .TRUE.
171    autoinit_NH = .NOT. hydrostatic
172
173    SELECT CASE (TRIM(etat0_type))
174    CASE ('isothermal')
175       CALL compute_isothermal(ngrid, phis, ps, temp, ulon, ulat, q)
176    CASE ('temperature_profile')
177       CALL compute_temperature(ngrid, phis, ps, temp, ulon, ulat, q)
178    CASE('jablonowsky06')
179       CALL compute_jablonowsky06(ngrid, lon, lat, phis, ps, temp, ulon, ulat)
180    CASE('dcmip1')
181       CALL compute_dcmip1(ngrid, lon, lat, phis, ps, temp, ulon, ulat, q)
182    CASE ('dcmip2_mountain','dcmip2_schaer_noshear','dcmip2_schaer_shear')
183       CALL compute_dcmip2(ngrid, lon, lat, phis, ps, temp, ulon, ulat)
184    CASE('dcmip3')
185       CALL compute_dcmip3(ngrid, lon, lat, phis, ps, temp, ulon, ulat, geopot, q)
186       autoinit_NH = .FALSE. ! compute_dcmip3 initializes geopot
187    CASE('dcmip4')
188       CALL compute_dcmip4(ngrid, lon, lat, phis, ps, temp, ulon, ulat, q)
189    CASE('dcmip5')
190       CALL compute_dcmip5(ngrid, lon, lat, phis, ps, temp, ulon, ulat, q)
191    CASE('bubble')
192       CALL compute_bubble(ngrid, lon, lat, phis, ps, temp, ulon, ulat, geopot, q)
193!       autoinit_NH = .FALSE. ! compute_bubble initializes geopot
194    CASE('williamson91.6')
195       CALL compute_w91_6(ngrid, lon, lat, phis, mass(:,1), theta_rhodz(:,1), ulon(:,1), ulat(:,1))
196       autoinit_mass = .FALSE. ! do not overwrite mass
197    CASE('dcmip2016_baroclinic_wave')
198       CALL compute_dcmip2016_baroclinic_wave(ngrid, lon, lat, phis, ps, temp, ulon, ulat, q)
199    CASE('dcmip2016_cyclone')
200       CALL compute_dcmip2016_cyclone(ngrid, lon, lat, phis, ps, temp, ulon, ulat, q)
201    CASE('dcmip2016_supercell')
202       CALL compute_dcmip2016_supercell(ngrid, lon, lat, phis, ps, temp, ulon, ulat, q)
203    END SELECT
204
205    IF(PRESENT(uperp)) THEN
206       DO l = 1, llm
207          DO ij=1,ngrid
208             clat = COS(lat(ij))
209             slat = SIN(lat(ij))
210             clon = COS(lon(ij))
211             slon = SIN(lon(ij))
212             u3d(1) = -clon*slat*ulat(ij,l) - slon*ulon(ij,l)
213             u3d(2) = -slon*slat*ulat(ij,l) + clon*ulon(ij,l)
214             u3d(3) =       clat*ulat(ij,l)   
215             uperp(ij,l) = SUM(u3d*ep(ij,:))
216          END DO
217       END DO
218    END IF
219
220    IF(autoinit_mass) THEN
221       DO l = 1, llm
222          DO ij=1,ngrid
223             mass_ik = (mass_dak(l) + mass_dbk(l)*ps(ij))/g
224             p_ik = ptop + mass_ak(l) + mass_bk(l)*ps(ij)
225             mass(ij,l) = mass_ik
226             SELECT CASE(caldyn_thermo)
227             CASE(thermo_theta)
228                theta = temp(ij,l)*(p_ik/preff)**(-kappa)
229                theta_rhodz(ij,l) = mass_ik * theta
230             CASE(thermo_entropy)
231                log_p_preff = log(p_ik/preff)
232                chi = log(temp(ij,l)/Treff)
233                entropy = cpp*chi-Rd*log_p_preff
234                theta_rhodz(ij,l) = mass_ik * entropy
235             CASE(thermo_moist)
236                q_ik=q(ij,l,1)
237                r_ik=1.-q_ik
238                mass_ik = mass_ik*(1.-q_ik) ! dry mass
239                log_p_preff = log(p_ik/preff)
240                chi = log(temp(ij,l)/Treff)
241                entropy = r_ik*(cpp*chi-Rd*nu) + q_ik*(cppv*chi-Rv*log_p_preff)
242                theta_rhodz(ij,l) = mass_ik * entropy
243             CASE DEFAULT
244                STOP
245             END SELECT
246          END DO
247       END DO
248    END IF
249
250    IF(autoinit_NH) THEN
251       geopot(:,1) = phis(:) ! surface geopotential
252       DO l = 1, llm
253          DO ij=1,ngrid
254             ! hybrid pressure coordinate
255             p_ik = ptop + mass_ak(l) + mass_bk(l)*ps(ij)
256             mass_ik = (mass_dak(l) + mass_dbk(l)*ps(ij))/g
257             ! v=R.T/p, R=kappa*cpp
258             v_ik = kappa*cpp*temp(ij,l)/p_ik
259             geopot(ij,l+1) = geopot(ij,l) + mass_ik*v_ik*g
260          END DO
261       END DO
262    END IF
263
264  END SUBROUTINE compute_etat0_collocated
265
266END MODULE etat0_collocated_mod
Note: See TracBrowser for help on using the repository browser.