source: codes/icosagcm/trunk/src/disvert.f90 @ 352

Last change on this file since 352 was 210, checked in by ymipsl, 10 years ago

Find automatically a free unit when trying to open a file.
Unit 42 has a big chance to be connected to an other file....

YM

File size: 8.1 KB
Line 
1MODULE disvert_mod
2  USE icosa
3  REAL(rstd), SAVE, POINTER :: ap(:)
4!$OMP THREADPRIVATE(ap)
5  REAL(rstd), SAVE, POINTER :: bp(:)
6!$OMP THREADPRIVATE(bp)
7  REAL(rstd), SAVE, POINTER :: presnivs(:)
8!$OMP THREADPRIVATE(presnivs)
9  REAL(rstd), SAVE, POINTER :: mass_al(:), mass_bl(:), mass_ak(:), mass_bk(:), mass_dak(:), mass_dbk(:)
10!$OMP THREADPRIVATE(mass_al, mass_bl, mass_ak, mass_bk, mass_dak, mass_dbk)
11
12  REAL(rstd) :: ptop ! pressure at top of atmosphere l=llm+1
13!$OMP THREADPRIVATE(ptop)
14  ! vertical coordinate : Lagrangian or mass-based
15  INTEGER, SAVE :: caldyn_eta
16!$OMP THREADPRIVATE(caldyn_eta)
17  INTEGER, PARAMETER :: eta_mass=1, eta_lag=2
18  LOGICAL,SAVE :: ap_bp_present
19!$OMP THREADPRIVATE(ap_bp_present)
20
21CONTAINS
22
23  SUBROUTINE init_disvert
24  USE disvert_std_mod, ONLY: ap_std=>ap, bp_std=>bp, presnivs_std=>presnivs, init_disvert_std=>init_disvert
25  USE disvert_apbp_mod, ONLY: ap_apbp=>ap, bp_apbp=>bp, presnivs_apbp=>presnivs, init_disvert_apbp=>init_disvert
26  USE disvert_ncar_mod, ONLY: ap_ncar=>ap, bp_ncar=>bp, presnivs_ncar=>presnivs, init_disvert_ncar=>init_disvert
27  USE disvert_ncarl30_mod, ONLY: ap_ncarl30=>ap, bp_ncarl30=>bp, presnivs_ncarl30=>presnivs, init_disvert_ncarl30=>init_disvert
28  USE disvert_dcmip31_mod, ONLY: ap_dcmip31=>ap, bp_dcmip31=>bp, presnivs_dcmip31=>presnivs, init_disvert_dcmip31=>init_disvert
29  USE disvert_dcmip200_mod, ONLY: ap_dcmip200=>ap, bp_dcmip200=>bp, presnivs_dcmip200=>presnivs, init_disvert_dcmip200=>init_disvert
30  USE icosa
31  USE mpipara
32  IMPLICIT NONE
33    CHARACTER(len=255) :: def
34    INTEGER :: l
35
36    def='eta_mass'
37    CALL getin('caldyn_eta',def)
38    SELECT CASE(TRIM(def))
39    CASE('eta_mass')
40       caldyn_eta=eta_mass
41    CASE('eta_lag')
42       caldyn_eta=eta_lag
43    CASE DEFAULT
44       IF (is_mpi_root) PRINT *,'Bad selector for variable caldyn_eta : <', TRIM(def),'> options are <eta_mass>, <eta_lag>'
45       STOP
46    END SELECT
47    IF (is_mpi_root) PRINT *, 'caldyn_eta=',TRIM(def), caldyn_eta, eta_lag, eta_mass
48
49    def='std'
50    ap_bp_present=.TRUE.
51    CALL getin("disvert",def)
52
53    SELECT CASE (TRIM(def))
54      CASE('none')
55         IF(caldyn_eta/=eta_lag) THEN
56            IF(is_mpi_root) PRINT *,'disvert_type=none must be used with caldyn_eta=eta_lag'
57            STOP
58         END IF
59         ap_bp_present=.FALSE.
60      CASE('std')
61   
62        CALL init_disvert_std
63        ap=>ap_std
64        bp=>bp_std
65        presnivs=>presnivs_std
66     
67      CASE('read_apbp')
68   
69        CALL init_disvert_apbp
70        ap=>ap_apbp
71        bp=>bp_apbp
72        presnivs=>presnivs_apbp
73       
74      CASE ('ncar')
75
76        CALL init_disvert_ncar
77        ap=>ap_ncar
78        bp=>bp_ncar
79        presnivs=>presnivs_ncar
80
81      CASE ('dcmip31')
82
83        CALL init_disvert_dcmip31
84        ap=>ap_dcmip31
85        bp=>bp_dcmip31
86        presnivs=>presnivs_dcmip31
87
88      CASE ('dcmip200')
89
90        CALL init_disvert_dcmip200
91        ap=>ap_dcmip200
92        bp=>bp_dcmip200
93        presnivs=>presnivs_dcmip200
94
95      CASE ('ncarl30')
96
97        CALL init_disvert_ncarl30
98        ap=>ap_ncarl30
99        bp=>bp_ncarl30
100        presnivs=>presnivs_ncarl30
101      CASE default
102        IF (is_mpi_root) PRINT*,'Bad selector for variable disvert : <', TRIM(def),"> options are <std>, <ncar>, <ncarl30>" 
103        STOP
104       
105    END SELECT
106
107    IF(ap_bp_present) THEN
108       ! Convert from pressure coordinate to mass coordinate
109       ! pk = ap(k) + bp(k)*ps(ij) = ptop + g*( mass_ak(k) + mass_bk(k)*ms(ij) )
110       ptop = ap(llm+1)
111       ALLOCATE(mass_al(llm+1))
112       ALLOCATE(mass_bl(llm+1))
113       ALLOCATE(mass_ak(llm))
114       ALLOCATE(mass_bk(llm))
115       ALLOCATE(mass_dak(llm))
116       ALLOCATE(mass_dbk(llm))
117
118       ! FIXME : leave ps for the moment ; change ps to ms later
119       DO l=1,llm+1
120          !       mass_al(l) = (ap(l)-ptop)/g
121          !       mass_bl(l) = bp(l)/g
122          mass_al(l) = (ap(l)-ptop)
123          mass_bl(l) = bp(l)
124       END DO
125       DO l=1,llm
126          mass_ak(l) = .5*(mass_al(l)+mass_al(l+1))
127          mass_bk(l) = .5*(mass_bl(l)+mass_bl(l+1))
128          mass_dak(l) = mass_al(l)-mass_al(l+1)  ! >0
129          mass_dbk(l) = mass_bl(l)-mass_bl(l+1)  ! >0
130       END DO
131    END IF
132
133  END SUBROUTINE init_disvert 
134 
135  SUBROUTINE compute_rhodz(comp, ps, rhodz)
136    USE icosa
137    USE omp_para
138    LOGICAL, INTENT(IN) :: comp ! .TRUE. to compute, .FALSE. to check
139    REAL(rstd), INTENT(IN) :: ps(iim*jjm)
140    REAL(rstd), INTENT(INOUT) :: rhodz(iim*jjm,llm)
141    REAL(rstd) :: m, err
142    INTEGER :: l,i,j,ij,dd
143    err=0.
144
145    IF(comp) THEN
146       dd=1
147    ELSE
148       dd=0
149    END IF
150
151    DO l = ll_begin, ll_end
152       DO j=jj_begin-dd,jj_end+dd
153          DO i=ii_begin-dd,ii_end+dd
154             ij=(j-1)*iim+i
155             m = ( ap(l) - ap(l+1) + (bp(l)-bp(l+1))*ps(ij) )/g 
156             IF(comp) THEN
157                rhodz(ij,l) = m
158             ELSE
159                err = MAX(err,abs(m-rhodz(ij,l)))
160             END IF
161          ENDDO
162       ENDDO
163    ENDDO
164
165    IF(.NOT. comp) THEN
166       IF(err>1e-10) THEN
167          PRINT *, 'Discrepancy between ps and rhodz detected', err
168          STOP
169       ELSE
170!          PRINT *, 'No discrepancy between ps and rhodz detected'
171       END IF
172    END IF
173
174  END SUBROUTINE compute_rhodz
175
176 
177  SUBROUTINE write_apbp
178  USE icosa
179  USE netcdf_mod
180  IMPLICIT NONE
181    REAL(rstd) :: val(llm)
182    INTEGER :: status
183    INTEGER :: lev,ilev
184    INTEGER :: ncid,levid,ilevid,hyaiid,hybiid,hyamid,hybmid,P0id
185    INTEGER :: l
186
187!$OMP BARRIER
188!$OMP MASTER   
189    status = NF90_CREATE('apbp.nc', NF90_CLOBBER, ncid)
190    status = NF90_DEF_DIM(ncid,'lev',llm,lev)
191    status = NF90_DEF_DIM(ncid,'ilev',llm+1,ilev)
192   
193    status = NF90_DEF_VAR(ncid,'lev',NF90_DOUBLE,(/ lev /),levid)
194    status = NF90_PUT_ATT(ncid,levid,"long_name","hybrid level at midpoints (1000*(A+B))")
195    status = NF90_PUT_ATT(ncid,levid,"units","Pa")
196    status = NF90_PUT_ATT(ncid,levid,"positive","up")
197    status = NF90_PUT_ATT(ncid,levid,"standard_name","atmosphere_hybrid_sigma_pressure_coordinate")
198    status = NF90_PUT_ATT(ncid,levid,"formula_terms","a: hyam b: hybm p0: P0 ps: PS")
199
200    status = NF90_DEF_VAR(ncid,'ilev',NF90_DOUBLE,(/ ilev /),ilevid)
201    status = NF90_PUT_ATT(ncid,ilevid,"long_name","hybrid level at interfaces (1000*(A+B))")
202    status = NF90_PUT_ATT(ncid,ilevid,"units","Pa")
203    status = NF90_PUT_ATT(ncid,ilevid,"positive","up")
204    status = NF90_PUT_ATT(ncid,ilevid,"standard_name","atmosphere_hybrid_sigma_pressure_coordinate")
205    status = NF90_PUT_ATT(ncid,ilevid,"formula_terms","a: hyai b: hybi p0: P0 ps: PS")
206   
207    status = NF90_DEF_VAR(ncid,'hyai',NF90_DOUBLE,(/ ilev /),hyaiid)
208    status = NF90_PUT_ATT(ncid,hyaiid,"long_name","hybrid A coefficient at layer interfaces")
209
210    status = NF90_DEF_VAR(ncid,'hybi',NF90_DOUBLE,(/ ilev /),hybiid)
211    status = NF90_PUT_ATT(ncid,hybiid,"long_name","hybrid B coefficient at layer interfaces")
212
213    status = NF90_DEF_VAR(ncid,'hyam',NF90_DOUBLE,(/ lev /),hyamid)
214    status = NF90_PUT_ATT(ncid,hyamid,"long_name","hybrid A coefficient at midpoint interfaces")
215
216    status = NF90_DEF_VAR(ncid,'hybm',NF90_DOUBLE,(/ lev /),hybmid)
217    status = NF90_PUT_ATT(ncid,hybmid,"long_name","hybrid B coefficient at midpoint interfaces")
218   
219    status = NF90_DEF_VAR(ncid,'P0',NF90_DOUBLE,varid=P0id)
220
221    status = NF90_ENDDEF(ncid)   
222
223    IF(ap_bp_present) THEN
224   
225    status=NF90_PUT_VAR(ncid,ilevid, ap(:)+bp(:)*Preff)
226   
227    DO l=1,llm
228      val(l)= 0.5*(ap(l+1)+ap(l)+Preff*(bp(l)+bp(l+1)))
229    ENDDO
230   
231    status=NF90_PUT_VAR(ncid,levid, val)
232
233    status=NF90_PUT_VAR(ncid,hyaiid, ap(:)/Preff)
234    status=NF90_PUT_VAR(ncid,hybiid, bp(:))
235   
236    DO l=1,llm
237      val(l)= 0.5*(ap(l+1)+ap(l))
238    ENDDO
239    status=NF90_PUT_VAR(ncid,hyamid, val(:)/Preff)
240   
241    DO l=1,llm
242      val(l)= 0.5*(bp(l+1)+bp(l))
243    ENDDO
244    status=NF90_PUT_VAR(ncid,hybmid, val(:))
245 
246    status=NF90_PUT_VAR(ncid,P0id, Preff)
247   
248    END IF
249
250    status=NF90_CLOSE(ncid)
251!$OMP END MASTER
252!$OMP BARRIER
253  END SUBROUTINE write_apbp
254
255END MODULE disvert_mod
Note: See TracBrowser for help on using the repository browser.