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
RevLine 
[12]1MODULE disvert_mod
[19]2  USE icosa
[17]3  REAL(rstd), SAVE, POINTER :: ap(:)
[186]4!$OMP THREADPRIVATE(ap)
[17]5  REAL(rstd), SAVE, POINTER :: bp(:)
[186]6!$OMP THREADPRIVATE(bp)
[17]7  REAL(rstd), SAVE, POINTER :: presnivs(:)
[186]8!$OMP THREADPRIVATE(presnivs)
[156]9  REAL(rstd), SAVE, POINTER :: mass_al(:), mass_bl(:), mass_ak(:), mass_bk(:), mass_dak(:), mass_dbk(:)
[186]10!$OMP THREADPRIVATE(mass_al, mass_bl, mass_ak, mass_bk, mass_dak, mass_dbk)
[159]11
[156]12  REAL(rstd) :: ptop ! pressure at top of atmosphere l=llm+1
[186]13!$OMP THREADPRIVATE(ptop)
[159]14  ! vertical coordinate : Lagrangian or mass-based
15  INTEGER, SAVE :: caldyn_eta
[186]16!$OMP THREADPRIVATE(caldyn_eta)
[159]17  INTEGER, PARAMETER :: eta_mass=1, eta_lag=2
[166]18  LOGICAL,SAVE :: ap_bp_present
[186]19!$OMP THREADPRIVATE(ap_bp_present)
[12]20
21CONTAINS
22
23  SUBROUTINE init_disvert
[17]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
[33]26  USE disvert_ncarl30_mod, ONLY: ap_ncarl30=>ap, bp_ncarl30=>bp, presnivs_ncarl30=>presnivs, init_disvert_ncarl30=>init_disvert
[115]27  USE disvert_dcmip31_mod, ONLY: ap_dcmip31=>ap, bp_dcmip31=>bp, presnivs_dcmip31=>presnivs, init_disvert_dcmip31=>init_disvert
[116]28  USE disvert_dcmip200_mod, ONLY: ap_dcmip200=>ap, bp_dcmip200=>bp, presnivs_dcmip200=>presnivs, init_disvert_dcmip200=>init_disvert
[19]29  USE icosa
[131]30  USE mpipara
[12]31  IMPLICIT NONE
[166]32    CHARACTER(len=255) :: def
[156]33    INTEGER :: l
34
[166]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)
[186]51    PRINT*,"def --> ",def
[166]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.
[17]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')
[12]67
[17]68        CALL init_disvert_ncar
69        ap=>ap_ncar
70        bp=>bp_ncar
71        presnivs=>presnivs_ncar
[33]72
[115]73      CASE ('dcmip31')
74
75        CALL init_disvert_dcmip31
76        ap=>ap_dcmip31
77        bp=>bp_dcmip31
78        presnivs=>presnivs_dcmip31
79
[116]80      CASE ('dcmip200')
81
82        CALL init_disvert_dcmip200
83        ap=>ap_dcmip200
84        bp=>bp_dcmip200
85        presnivs=>presnivs_dcmip200
86
[33]87      CASE ('ncarl30')
88
[64]89        CALL init_disvert_ncarl30
[33]90        ap=>ap_ncarl30
91        bp=>bp_ncarl30
92        presnivs=>presnivs_ncarl30
[186]93        PRINT*,"ap --> ",ap
94        PRINT*,"ap_ncarl30 --> ",ap_ncarl30
[17]95      CASE default
[166]96        IF (is_mpi_root) PRINT*,'Bad selector for variable disvert : <', TRIM(def),"> options are <std>, <ncar>, <ncarl30>" 
[17]97        STOP
98       
99    END SELECT
[12]100
[166]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))
[156]111
[166]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
[156]126
[12]127  END SUBROUTINE init_disvert 
128 
[159]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
[161]139    IF(comp) THEN
140       dd=1
141    ELSE
142       dd=0
143    END IF
[159]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 
[75]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
[186]180
181!$OMP BARRIER
182!$OMP MASTER   
183  IF(ap_bp_present) THEN
[75]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)   
[186]217   
[75]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)
[112]227    status=NF90_PUT_VAR(ncid,hybiid, bp(:))
[75]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   
[166]241    status=NF90_CLOSE(ncid)
[186]242  END IF
243!$OMP END MASTER
244!$OMP BARRIER
[75]245  END SUBROUTINE write_apbp
246
[12]247END MODULE disvert_mod
Note: See TracBrowser for help on using the repository browser.