source: LMDZ5/trunk/libf/phylmd/StratAer/interp_sulf_input.F90 @ 2690

Last change on this file since 2690 was 2690, checked in by oboucher, 8 years ago

Adding a module for stratospheric aerosols with a bin scheme.
The module gets activated with -strataer true compiling option.
May not quite work yet, more testing needed, but should not affect
the rest of LMDz as everything is under a CPP_StratAer key.

File size: 9.4 KB
Line 
1SUBROUTINE interp_sulf_input(debutphy,pdtphys,paprs,tr_seri,SO2_backgr_tend, &
2                            & OCS_backgr_tend,SO2_lifetime,OCS_lifetime)
3
4  USE netcdf95, ONLY: nf95_close, nf95_gw_var, nf95_inq_dimid, &
5                      nf95_inq_varid, nf95_inquire_dimension, nf95_open
6  USE netcdf, ONLY: nf90_get_var, nf90_noerr, nf90_nowrite
7
8  USE mod_grid_phy_lmdz
9  USE mod_phys_lmdz_mpi_data, ONLY :  is_mpi_root
10  USE mod_phys_lmdz_para
11  USE dimphy
12  USE phys_cal_mod
13  USE infotrac
14  USE aerophys
15
16  IMPLICIT NONE
17
18  include "YOMCST.h"
19  include "dimensions.h"
20
21! Variable input
22  REAL paprs(klon,klev+1)
23  REAL tr_seri(klon,klev,nbtr)
24  REAL, INTENT(IN)    :: pdtphys    ! Pas d'integration pour la physique (seconde)
25  LOGICAL, INTENT(IN) :: debutphy   ! le flag de l'initialisation de la physique
26
27! Variables locales
28  INTEGER nmth
29  INTEGER n_lat   ! number of latitudes in the input data
30  INTEGER n_lon   ! number of longitudes in the input data
31  INTEGER, SAVE :: n_lev   ! number of levels in the input data
32  INTEGER n_mth   ! number of months in the input data
33  REAL OCS_tmp
34  REAL SO2_tmp
35
36! Champs reconstitues
37  REAL paprs_glo(klon_glo,klev+1)
38  REAL tr_seri_glo(klon_glo,klev,nbtr)
39
40  REAL, POINTER:: latitude(:)
41! (of input data sorted in strictly ascending order)
42
43  REAL, POINTER:: longitude(:)
44! (of input data sorted in strictly ascending order)
45
46  REAL, POINTER:: time(:)
47! (of input data sorted in strictly ascending order)
48
49  REAL, POINTER:: lev(:)
50! levels of input data
51
52  REAL, ALLOCATABLE :: OCS_input(:, :, :, :)
53  REAL, ALLOCATABLE :: SO2_input(:, :, :, :)
54  REAL, ALLOCATABLE :: OCS_input_mth(:, :, :)
55  REAL, ALLOCATABLE :: SO2_input_mth(:, :, :)
56  REAL, SAVE, ALLOCATABLE :: OCS_input_tmp(:, :)
57  REAL, SAVE, ALLOCATABLE :: SO2_input_tmp(:, :)
58  REAL, ALLOCATABLE :: OCS_lifetime_in(:, :, :, :)
59  REAL, ALLOCATABLE :: SO2_lifetime_in(:, :, :, :)
60  REAL, ALLOCATABLE :: OCS_lifetime_mth(:, :, :)
61  REAL, ALLOCATABLE :: SO2_lifetime_mth(:, :, :)
62  REAL, SAVE, ALLOCATABLE :: OCS_lifetime_tmp(:, :)
63  REAL, SAVE, ALLOCATABLE :: SO2_lifetime_tmp(:, :)
64!
65  INTEGER i, k, kk, ilon, ilev, j
66  REAL p_bound
67
68! For NetCDF:
69  INTEGER ncid_in  ! IDs for input files
70  INTEGER varid, ncerr
71
72! variable output
73  REAL OCS_backgr_tend_glo(klon_glo,klev)
74  REAL SO2_backgr_tend_glo(klon_glo,klev)
75  REAL OCS_backgr_tend(klon,klev)
76  REAL SO2_backgr_tend(klon,klev)
77  REAL OCS_lifetime_glo(klon_glo,klev)
78  REAL SO2_lifetime_glo(klon_glo,klev)
79  REAL OCS_lifetime(klon,klev)
80  REAL SO2_lifetime(klon,klev)
81   
82  INTEGER, PARAMETER :: lev_input=17
83!--pressure at interfaces of input data (in Pa)
84  REAL, DIMENSION(lev_input+1), PARAMETER ::          &
85                    paprs_input=(/                    &
86  1.00000002e+05,   6.06530673e+04,   3.67879449e+04, &
87  2.23130165e+04,   1.35335286e+04,   8.20850004e+03, &
88  4.97870695e+03,   3.01973841e+03,   1.83156393e+03, &
89  1.11089968e+03,   6.73794715e+02,   4.08677153e+02, &
90  2.47875223e+02,   1.50343923e+02,   9.11881985e+01, &
91  5.53084382e+01,   3.35462635e+01,   0.0           /)
92!
93  REAL, PARAMETER :: epsilon_OCS=1.0e-20     ! minimum OCS concentration [kg/kgA] for weighting of lifetime
94  REAL, PARAMETER :: epsilon_SO2=1.0e-20     ! minimum SO2 concentration [kg/kgA] for weighting of lifetime
95  REAL, PARAMETER :: min_OCS_lifetime= 3600. !minimum OCS lifetime [sec]
96  REAL, PARAMETER :: min_SO2_lifetime=86400. !minimum SO2 lifetime [sec]
97
98!--preparation of fields
99  CALL gather(paprs, paprs_glo)
100  CALL gather(tr_seri, tr_seri_glo)
101
102  IF (debutphy.AND.is_mpi_root) THEN
103
104!--reading emission files
105    CALL nf95_open("ocs_so2_annual_lmdz.nc", nf90_nowrite, ncid_in)
106
107    CALL nf95_inq_varid(ncid_in, "LEV", varid)
108    CALL nf95_gw_var(ncid_in, varid, lev)
109    n_lev = size(lev)
110
111    CALL nf95_inq_varid(ncid_in, "lat", varid)
112    CALL nf95_gw_var(ncid_in, varid, latitude)
113    n_lat = size(latitude)
114
115    CALL nf95_inq_varid(ncid_in, "lon", varid)
116    CALL nf95_gw_var(ncid_in, varid, longitude)
117    n_lon = size(longitude)
118
119    CALL nf95_inq_varid(ncid_in, "TIME", varid)
120    CALL nf95_gw_var(ncid_in, varid, time)
121    n_mth = size(time)
122
123    IF (.NOT.allocated(OCS_input))  allocate(OCS_input(n_lon, n_lat, n_lev, n_mth))
124    IF (.NOT.allocated(SO2_input))  allocate(SO2_input(n_lon, n_lat, n_lev, n_mth))
125    IF (.NOT.allocated(OCS_lifetime_in))  allocate(OCS_lifetime_in(n_lon, n_lat, n_lev, n_mth))
126    IF (.NOT.allocated(SO2_lifetime_in))  allocate(SO2_lifetime_in(n_lon, n_lat, n_lev, n_mth))
127
128    CALL nf95_inq_varid(ncid_in, "OCS", varid)
129    ncerr = nf90_get_var(ncid_in, varid, OCS_input)
130    print *,'code erreur OCS=', ncerr, varid
131
132    CALL nf95_inq_varid(ncid_in, "SO2", varid)
133    ncerr = nf90_get_var(ncid_in, varid, SO2_input)
134    print *,'code erreur SO2=', ncerr, varid
135
136    CALL nf95_inq_varid(ncid_in, "OCS_LIFET", varid)
137    ncerr = nf90_get_var(ncid_in, varid, OCS_lifetime_in)
138    print *,'code erreur OCS_lifetime_in=', ncerr, varid
139
140    CALL nf95_inq_varid(ncid_in, "SO2_LIFET", varid)
141    ncerr = nf90_get_var(ncid_in, varid, SO2_lifetime_in)
142    print *,'code erreur SO2_lifetime_in=', ncerr, varid
143
144    CALL nf95_close(ncid_in)
145
146    IF (.NOT.allocated(OCS_input_mth)) allocate(OCS_input_mth(n_lon, n_lat, n_lev))
147    IF (.NOT.allocated(SO2_input_mth)) allocate(SO2_input_mth(n_lon, n_lat, n_lev))
148    IF (.NOT.allocated(OCS_input_tmp)) allocate(OCS_input_tmp(klon_glo, n_lev))
149    IF (.NOT.allocated(SO2_input_tmp)) allocate(SO2_input_tmp(klon_glo, n_lev))
150    IF (.NOT.allocated(OCS_lifetime_mth)) allocate(OCS_lifetime_mth(n_lon, n_lat, n_lev))
151    IF (.NOT.allocated(SO2_lifetime_mth)) allocate(SO2_lifetime_mth(n_lon, n_lat, n_lev))
152    IF (.NOT.allocated(OCS_lifetime_tmp)) allocate(OCS_lifetime_tmp(klon_glo, n_lev))
153    IF (.NOT.allocated(SO2_lifetime_tmp)) allocate(SO2_lifetime_tmp(klon_glo, n_lev))
154
155!---select the correct month, undo multiplication with 1.e12 (precision reasons)
156!---correct latitudinal order and convert input from volume mixing ratio to mass mixing ratio
157    nmth=mth_cur
158    DO j=1,n_lat
159      SO2_input_mth(:,j,:) = 1.e-12*SO2_input(:,n_lat+1-j,:,nmth)*mSO2mol/mAIRmol
160      OCS_input_mth(:,j,:) = 1.e-12*OCS_input(:,n_lat+1-j,:,nmth)*mOCSmol/mAIRmol
161      SO2_lifetime_mth(:,j,:) = SO2_lifetime_in(:,n_lat+1-j,:,nmth)
162      OCS_lifetime_mth(:,j,:) = OCS_lifetime_in(:,n_lat+1-j,:,nmth)
163    ENDDO
164
165!---reduce to a klon_glo grid but keep the levels
166    CALL grid2dTo1d_glo(OCS_input_mth,OCS_input_tmp)
167    CALL grid2dTo1d_glo(SO2_input_mth,SO2_input_tmp)
168    CALL grid2dTo1d_glo(OCS_lifetime_mth,OCS_lifetime_tmp)
169    CALL grid2dTo1d_glo(SO2_lifetime_mth,SO2_lifetime_tmp)
170
171!--set lifetime to very high value in uninsolated areas
172    DO i=1, klon_glo
173      DO kk=1, n_lev
174        IF (OCS_lifetime_tmp(i,kk)==0.0) THEN
175          OCS_lifetime_tmp(i,kk)=1.0e12
176        ENDIF
177        IF (SO2_lifetime_tmp(i,kk)==0.0) THEN
178          SO2_lifetime_tmp(i,kk)=1.0e12
179        ENDIF
180      ENDDO
181    ENDDO
182
183  ENDIF !(debutphy.AND.is_mpi_root)
184
185  IF (is_mpi_root) THEN
186
187!--set to background value everywhere in the very beginning, later only in the troposphere
188      IF (debutphy.AND.MAXVAL(tr_seri_glo).LT.1.e-30) THEN
189        p_bound=0.0
190      ELSE
191        p_bound=50000.
192      ENDIF
193
194!--regridding tracer concentration on the vertical
195      DO i=1, klon_glo
196        DO k=1, klev
197          !
198          OCS_tmp=tr_seri_glo(i,k,id_OCS_strat)
199          SO2_tmp=tr_seri_glo(i,k,id_SO2_strat)
200          !--OCS and SO2 prescribed below p_bound
201          IF (paprs_glo(i,k).GT.p_bound) THEN
202            tr_seri_glo(i,k,id_OCS_strat)=0.0
203            tr_seri_glo(i,k,id_SO2_strat)=0.0
204            DO kk=1, n_lev
205            tr_seri_glo(i,k,id_OCS_strat)=tr_seri_glo(i,k,id_OCS_strat)+ &
206               MAX(0.0,MIN(paprs_glo(i,k),paprs_input(kk))-MAX(paprs_glo(i,k+1),paprs_input(kk+1))) &
207               *OCS_input_tmp(i,kk)/(paprs_glo(i,k)-paprs_glo(i,k+1))
208            tr_seri_glo(i,k,id_SO2_strat)=tr_seri_glo(i,k,id_SO2_strat)+ &
209               MAX(0.0,MIN(paprs_glo(i,k),paprs_input(kk))-MAX(paprs_glo(i,k+1),paprs_input(kk+1))) &
210               *SO2_input_tmp(i,kk)/(paprs_glo(i,k)-paprs_glo(i,k+1))
211            ENDDO
212          ENDIF
213          OCS_backgr_tend_glo(i,k)=tr_seri_glo(i,k,id_OCS_strat)-OCS_tmp
214          SO2_backgr_tend_glo(i,k)=tr_seri_glo(i,k,id_SO2_strat)-SO2_tmp
215          !---regrid weighted lifetime
216          OCS_lifetime_glo(i,k)=0.0
217          SO2_lifetime_glo(i,k)=0.0
218          DO kk=1, n_lev
219          OCS_lifetime_glo(i,k)=OCS_lifetime_glo(i,k)+ &
220               MAX(0.0,MIN(paprs_glo(i,k),paprs_input(kk))-MAX(paprs_glo(i,k+1),paprs_input(kk+1))) &
221               *OCS_lifetime_tmp(i,kk)/(paprs_glo(i,k)-paprs_glo(i,k+1))
222          SO2_lifetime_glo(i,k)=SO2_lifetime_glo(i,k)+ &
223               MAX(0.0,MIN(paprs_glo(i,k),paprs_input(kk))-MAX(paprs_glo(i,k+1),paprs_input(kk+1))) &
224               *SO2_lifetime_tmp(i,kk)/(paprs_glo(i,k)-paprs_glo(i,k+1))
225          ENDDO
226        ENDDO
227      ENDDO
228
229  ENDIF !--is_mpi_root
230
231  CALL scatter(tr_seri_glo, tr_seri)
232  CALL scatter(OCS_backgr_tend_glo, OCS_backgr_tend)
233  CALL scatter(SO2_backgr_tend_glo, SO2_backgr_tend)
234  CALL scatter(OCS_lifetime_glo, OCS_lifetime)
235  CALL scatter(SO2_lifetime_glo, SO2_lifetime)
236
237  !convert SO2_backgr_tend from kg(SO2)/kgA to kg(S)/m2/layer/s for saving as diagnostic
238  DO ilon=1, klon
239    DO ilev=1, klev
240      SO2_backgr_tend(ilon,ilev)=SO2_backgr_tend(ilon,ilev)*mSatom/mSO2mol*(paprs(ilon,ilev)-paprs(ilon,ilev+1))/RG/pdtphys
241      OCS_backgr_tend(ilon,ilev)=OCS_backgr_tend(ilon,ilev)*mSatom/mOCSmol*(paprs(ilon,ilev)-paprs(ilon,ilev+1))/RG/pdtphys
242    ENDDO
243  ENDDO
244 
245  RETURN
246
247END SUBROUTINE interp_sulf_input
Note: See TracBrowser for help on using the repository browser.