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

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

Add new openMP parallelism based on distribution of domains on threads. There is no more limitation of number of threads by MPI process.

YM

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