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

Last change on this file since 159 was 159, checked in by dubos, 11 years ago

Towards Lagrangian vertical coordinate (not there yet)

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