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

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

Add new vertical discretisation by reading ap bp in an input file (ehouarn subroutines)

YM

File size: 8.2 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    PRINT*,"def --> ",def
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        PRINT*,"ap --> ",ap
102        PRINT*,"ap_ncarl30 --> ",ap_ncarl30
103      CASE default
104        IF (is_mpi_root) PRINT*,'Bad selector for variable disvert : <', TRIM(def),"> options are <std>, <ncar>, <ncarl30>" 
105        STOP
106       
107    END SELECT
108
109    IF(ap_bp_present) THEN
110       ! Convert from pressure coordinate to mass coordinate
111       ! pk = ap(k) + bp(k)*ps(ij) = ptop + g*( mass_ak(k) + mass_bk(k)*ms(ij) )
112       ptop = ap(llm+1)
113       ALLOCATE(mass_al(llm+1))
114       ALLOCATE(mass_bl(llm+1))
115       ALLOCATE(mass_ak(llm))
116       ALLOCATE(mass_bk(llm))
117       ALLOCATE(mass_dak(llm))
118       ALLOCATE(mass_dbk(llm))
119
120       ! FIXME : leave ps for the moment ; change ps to ms later
121       DO l=1,llm+1
122          !       mass_al(l) = (ap(l)-ptop)/g
123          !       mass_bl(l) = bp(l)/g
124          mass_al(l) = (ap(l)-ptop)
125          mass_bl(l) = bp(l)
126       END DO
127       DO l=1,llm
128          mass_ak(l) = .5*(mass_al(l)+mass_al(l+1))
129          mass_bk(l) = .5*(mass_bl(l)+mass_bl(l+1))
130          mass_dak(l) = mass_al(l)-mass_al(l+1)  ! >0
131          mass_dbk(l) = mass_bl(l)-mass_bl(l+1)  ! >0
132       END DO
133    END IF
134
135  END SUBROUTINE init_disvert 
136 
137  SUBROUTINE compute_rhodz(comp, ps, rhodz)
138    USE icosa
139    USE omp_para
140    LOGICAL, INTENT(IN) :: comp ! .TRUE. to compute, .FALSE. to check
141    REAL(rstd), INTENT(IN) :: ps(iim*jjm)
142    REAL(rstd), INTENT(INOUT) :: rhodz(iim*jjm,llm)
143    REAL(rstd) :: m, err
144    INTEGER :: l,i,j,ij,dd
145    err=0.
146
147    IF(comp) THEN
148       dd=1
149    ELSE
150       dd=0
151    END IF
152
153    DO l = ll_begin, ll_end
154       DO j=jj_begin-dd,jj_end+dd
155          DO i=ii_begin-dd,ii_end+dd
156             ij=(j-1)*iim+i
157             m = ( ap(l) - ap(l+1) + (bp(l)-bp(l+1))*ps(ij) )/g 
158             IF(comp) THEN
159                rhodz(ij,l) = m
160             ELSE
161                err = MAX(err,abs(m-rhodz(ij,l)))
162             END IF
163          ENDDO
164       ENDDO
165    ENDDO
166
167    IF(.NOT. comp) THEN
168       IF(err>1e-10) THEN
169          PRINT *, 'Discrepancy between ps and rhodz detected', err
170          STOP
171       ELSE
172!          PRINT *, 'No discrepancy between ps and rhodz detected'
173       END IF
174    END IF
175
176  END SUBROUTINE compute_rhodz
177
178 
179  SUBROUTINE write_apbp
180  USE icosa
181  USE netcdf_mod
182  IMPLICIT NONE
183    REAL(rstd) :: val(llm)
184    INTEGER :: status
185    INTEGER :: lev,ilev
186    INTEGER :: ncid,levid,ilevid,hyaiid,hybiid,hyamid,hybmid,P0id
187    INTEGER :: l
188
189!$OMP BARRIER
190!$OMP MASTER   
191    status = NF90_CREATE('apbp.nc', NF90_CLOBBER, ncid)
192    status = NF90_DEF_DIM(ncid,'lev',llm,lev)
193    status = NF90_DEF_DIM(ncid,'ilev',llm+1,ilev)
194   
195    status = NF90_DEF_VAR(ncid,'lev',NF90_DOUBLE,(/ lev /),levid)
196    status = NF90_PUT_ATT(ncid,levid,"long_name","hybrid level at midpoints (1000*(A+B))")
197    status = NF90_PUT_ATT(ncid,levid,"units","Pa")
198    status = NF90_PUT_ATT(ncid,levid,"positive","up")
199    status = NF90_PUT_ATT(ncid,levid,"standard_name","atmosphere_hybrid_sigma_pressure_coordinate")
200    status = NF90_PUT_ATT(ncid,levid,"formula_terms","a: hyam b: hybm p0: P0 ps: PS")
201
202    status = NF90_DEF_VAR(ncid,'ilev',NF90_DOUBLE,(/ ilev /),ilevid)
203    status = NF90_PUT_ATT(ncid,ilevid,"long_name","hybrid level at interfaces (1000*(A+B))")
204    status = NF90_PUT_ATT(ncid,ilevid,"units","Pa")
205    status = NF90_PUT_ATT(ncid,ilevid,"positive","up")
206    status = NF90_PUT_ATT(ncid,ilevid,"standard_name","atmosphere_hybrid_sigma_pressure_coordinate")
207    status = NF90_PUT_ATT(ncid,ilevid,"formula_terms","a: hyai b: hybi p0: P0 ps: PS")
208   
209    status = NF90_DEF_VAR(ncid,'hyai',NF90_DOUBLE,(/ ilev /),hyaiid)
210    status = NF90_PUT_ATT(ncid,hyaiid,"long_name","hybrid A coefficient at layer interfaces")
211
212    status = NF90_DEF_VAR(ncid,'hybi',NF90_DOUBLE,(/ ilev /),hybiid)
213    status = NF90_PUT_ATT(ncid,hybiid,"long_name","hybrid B coefficient at layer interfaces")
214
215    status = NF90_DEF_VAR(ncid,'hyam',NF90_DOUBLE,(/ lev /),hyamid)
216    status = NF90_PUT_ATT(ncid,hyamid,"long_name","hybrid A coefficient at midpoint interfaces")
217
218    status = NF90_DEF_VAR(ncid,'hybm',NF90_DOUBLE,(/ lev /),hybmid)
219    status = NF90_PUT_ATT(ncid,hybmid,"long_name","hybrid B coefficient at midpoint interfaces")
220   
221    status = NF90_DEF_VAR(ncid,'P0',NF90_DOUBLE,varid=P0id)
222
223    status = NF90_ENDDEF(ncid)   
224
225    IF(ap_bp_present) THEN
226   
227    status=NF90_PUT_VAR(ncid,ilevid, ap(:)+bp(:)*Preff)
228   
229    DO l=1,llm
230      val(l)= 0.5*(ap(l+1)+ap(l)+Preff*(bp(l)+bp(l+1)))
231    ENDDO
232   
233    status=NF90_PUT_VAR(ncid,levid, val)
234
235    status=NF90_PUT_VAR(ncid,hyaiid, ap(:)/Preff)
236    status=NF90_PUT_VAR(ncid,hybiid, bp(:))
237   
238    DO l=1,llm
239      val(l)= 0.5*(ap(l+1)+ap(l))
240    ENDDO
241    status=NF90_PUT_VAR(ncid,hyamid, val(:)/Preff)
242   
243    DO l=1,llm
244      val(l)= 0.5*(bp(l+1)+bp(l))
245    ENDDO
246    status=NF90_PUT_VAR(ncid,hybmid, val(:))
247 
248    status=NF90_PUT_VAR(ncid,P0id, Preff)
249   
250    END IF
251
252    status=NF90_CLOSE(ncid)
253!$OMP END MASTER
254!$OMP BARRIER
255  END SUBROUTINE write_apbp
256
257END MODULE disvert_mod
Note: See TracBrowser for help on using the repository browser.