- Timestamp:
- Nov 22, 2017, 11:01:27 PM (7 years ago)
- Location:
- LMDZ6/trunk/libf/phylmd
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
LMDZ6/trunk/libf/phylmd/physiq_mod.F90
r3082 r3086 2071 2071 IF(adjust_tropopause) THEN 2072 2072 CALL regr_pr_time_av(ncid_climoz, vars_climoz(1:read_climoz), & 2073 ro3i, press_edg_climoz, paprs, wo, time_climoz, &2074 longitude_deg, latitude_deg, press_cen_climoz,&2073 ro3i, 'C', press_cen_climoz, pplay, wo, paprs(:,1), & 2074 time_climoz , longitude_deg, latitude_deg, & 2075 2075 dyn_tropopause(t_seri, ztsol, paprs, pplay, rot)) 2076 2076 ELSE 2077 CALL regr_pr_time_av(ncid_climoz, vars_climoz(1:read_climoz), & 2078 ro3i, press_edg_climoz, paprs, wo, time_climoz) 2077 CALL regr_pr_time_av(ncid_climoz, vars_climoz(1:read_climoz), & 2078 ro3i, 'C', press_cen_climoz, pplay, wo, paprs(:,1), & 2079 time_climoz ) 2079 2080 END IF 2080 2081 ! Convert from mole fraction of ozone to column density of ozone in a -
LMDZ6/trunk/libf/phylmd/regr_pr_comb_coefoz_m.F90
r3043 r3086 129 129 130 130 call regr_pr_time_av(ncid, (/"a2 ", "a4 ", "a6 ", & 131 "P_net_Mob ", "r_Mob ", "temp_Mob ", "R_Het "/), REAL(julien-1),&132 press_in_edg, paprs, coefoz)131 "P_net_Mob ", "r_Mob ", "temp_Mob ", "R_Het "/), & 132 REAL(julien-1), 'I', press_in_edg, paprs, coefoz) 133 133 a2 = coefoz(:, :, 1) 134 134 a4_mass = coefoz(:, :, 2) * 48. / 29. -
LMDZ6/trunk/libf/phylmd/regr_pr_time_av_m.F90
r3069 r3086 16 16 ! to the LMDZ vertical grid. 17 17 ! * the forcing fields are stretched if the following arguments are present: 18 ! - "lat_in": input file latitudes. 19 ! - "pcen_in": input file cells center pressure levels. 20 ! - "ptrop_ou": target grid (LMDZ) tropopause pressure. 18 ! - "lat_in": input file latitudes. 19 ! - "Ptrp_ou": target grid (LMDZ) tropopause pressure. 21 20 ! so that the tropopause is shifted to the position of the one of LMDZ. 22 21 ! Note that the ozone quantity conservation is not ensured. … … 35 34 ! except that the latitudes are in ascending order in the input file. 36 35 ! * We assume that all the input fields have the same coordinates. 37 ! * The target vertical LMDZ grid is the grid of layer boundaries. 38 ! * Regridding in pressure is conservative, second order. 36 ! * The target vertical LMDZ grid is the grid of layer centers. 37 ! * Regridding in pressure can be: 38 ! - Ploc=='I': pressures provided at Interfaces => conservative 2nd order 39 ! OK for ozone coefficients regridding in Cariolle routines. 40 ! - Ploc=='C': pressures provides at cells Centers => classical linear 41 ! OK for ozone vertical regridding, especially when torpopause 42 ! adjustment is activated, to avoid "strairs shape effect" on profiles. 39 43 ! * All the fields are regridded as a single multi-dimensional array, so it 40 44 ! saves CPU time to call this procedure once for several NetCDF variables … … 43 47 ! 1) read from the file if "tropopause_air_pressure" field is available. 44 48 ! 2) computed using "tro3" and "tro3_at_tropopause' (if available). 45 ! 3) computed using "tro3" and a fixed threshold otherwise, determined using46 ! an empirical three parameters law:49 ! 3) computed using "tro3" and a fixed threshold otherwise, constant or 50 ! determined using an empirical three parameters law: 47 51 ! o3t(ppbV)=co1+co2*SIN(PI*(month-2)/6)*TANH(lat_deg/co3) 48 52 ! => co1 and co2 are in ppbV, and co3 in degrees. … … 52 56 ! * Fields with suffix "m"/"p" are at the closest records earlier/later than 53 57 ! the mid-julian day "julien", on the global "dynamics" horizontal grid. 54 ! * Fields(i,j,k,l) are at longitude-latitude "rlonv(i)-rlatu(j)", pressure55 ! interval "pint_in(k:k+1)]" and variable "nam(l)".58 ! * Fields(i,j,k,l) are at longitude-latitude-name "rlonv(i)-rlatu(j)-nam(l)", 59 ! pressure level/interval (Ploc=="C"/"I") "pcen_in(k)"/"pcen_in(k:k+1)]". 56 60 ! * In the 2D file case, the values are the same for all longitudes. 57 61 ! * The tropopause correction works like this: the input fields (file) are 58 62 ! interpolated on output (LMDZ) pressure field, which is streched using a power 59 ! law in a limited zone made of 3layers:60 ! 1) between the two tropopauses (file and LMDZ)61 ! 2) in an upper and a lower transitions layers63 ! law in a limited zone made of 2 layers: 64 ! 1) between lower bound (lower than lowest tropopause) and LMDZ tropopause 65 ! 2) between LMDZ tropopause and upper bound (higher thzn highest tropopause) 62 66 ! The stretching function has the following form: 63 ! Sigma_str = Sigma^(1+alpha), with alpha=LOG(SigT_in/SigT_ou)/LOG(SigT_ou)64 ! This value shifts the file tropopause to the height of the one of LMDZ.65 ! The stretching is fully applied in the central zone only, and only partially66 ! in the transitions zones, thick enough to guarantee a growing stretched67 ! pressure field. The ponderation function for alpha to modulate the stretching68 ! is constant equal to 1 in the central layer, and quasi-linear (from 1 to 0)69 ! in the transition layers (from 1 to 0 ; in fact: sections of 1/log function),70 ! making this localisation function quasi-trapezoidal.67 ! Sigma_str = Sigma^(1+alpha*phi(Sigma)), where: 68 ! * alpha=LOG(SigT_in/SigT_ou)/LOG(SigT_ou) 69 ! This value shifts the file tropopause to the height of the one of LMDZ. 70 ! * phi is quasi-linear (sections of 1/log function) in the adjacent intervals: 71 ! - from 0 to 1 in [Sig_top,SigT_ou] 72 ! - from 1 to 0 in [SigT_ou,Sig_bot] 73 ! This quasi-triangular localization function ponderates alpha-law from one near 74 ! the tropopause to zero each side apart. 71 75 ! 72 76 ! * The following fields are on the global "dynamics" grid, as read from files: 73 REAL, SAVE, ALLOCATABLE :: v1m(:,:,:,:) !--- Previous ozone fields 74 REAL, SAVE, ALLOCATABLE :: v1p(:,:,:,:) !--- Next ozone fields 75 REAL, SAVE, ALLOCATABLE :: psm(:,:), psp(:,:) !--- Surface pressure 77 REAL, SAVE, ALLOCATABLE :: v1 (:,:,:,:) !--- Current time ozone fields 78 ! v1: Field read/interpol at time "julien" on the global "dynamics" horiz. grid. 79 REAL, SAVE, ALLOCATABLE :: v1m(:,:,:,:) !--- Previous time ozone fields 80 REAL, SAVE, ALLOCATABLE :: v1p(:,:,:,:) !--- Next time ozone fields 81 REAL, SAVE, ALLOCATABLE :: pgm(:,:), pgp(:,:) !--- Ground pressure 76 82 REAL, SAVE, ALLOCATABLE :: ptm(:,:), ptp(:,:) !--- Tropopause pressure 77 83 REAL, SAVE, ALLOCATABLE :: otm(:,:), otp(:,:) !--- Tropopause o3 mix. ratio … … 82 88 ! * for monthly input files: julien is in [time_in(irec),time_in(irec+1)] 83 89 LOGICAL, SAVE :: linterp !--- Interpolation in time 84 LOGICAL, SAVE :: lPrS urf!--- Surface pressure flag85 LOGICAL, SAVE :: lPrT rop!--- Tropopause pressure flag86 LOGICAL, SAVE :: lO3T rop!--- Tropopause ozone flag90 LOGICAL, SAVE :: lPrSfile !--- Surface pressure flag 91 LOGICAL, SAVE :: lPrTfile !--- Tropopause pressure flag 92 LOGICAL, SAVE :: lO3Tfile !--- Tropopause ozone flag 87 93 LOGICAL, SAVE :: lfirst=.TRUE. !--- First call flag 88 94 !$OMP THREADPRIVATE(lfirst) 89 95 REAL, PARAMETER :: pTropUp=9.E+3 !--- Value < tropopause pressure (Pa) 90 REAL, PARAMETER :: gamm = 0.4 !--- Relative thickness of transitions91 REAL, PARAMETER :: rho = 1.3!--- Max tropopauses sigma ratio92 REAL, PARAMETER :: o3t0 = 1.E-7!--- Nominal O3 vmr at tropopause93 LOGICAL, PARAMETER :: l o3tp=.FALSE. !--- Use parametrized O3 vmr at tropopause94 LOGICAL, PARAMETER :: debug=.FALSE.!--- Force writefield_phy multiple outputs96 REAL, PARAMETER :: gamm =0.4 !--- Max. stretched layer sigma ratio 97 REAL, PARAMETER :: rho =1.4 !--- Max tropopauses sigma ratio 98 REAL, PARAMETER :: o3t0 =1.E-7 !--- Nominal O3 vmr at tropopause 99 LOGICAL, PARAMETER :: lO3Tpara=.FALSE. !--- Parametrized O3 vmr at tropopause 100 LOGICAL, PARAMETER :: ldebug=.TRUE.!--- Force writefield_phy multiple outputs 95 101 REAL, PARAMETER :: ChemPTrMin=9.E+3 !--- Thresholds for minimum and maximum 96 102 REAL, PARAMETER :: ChemPTrMax=4.E+4 ! chemical tropopause pressure (Pa). … … 102 108 !------------------------------------------------------------------------------- 103 109 ! 104 SUBROUTINE regr_pr_time_av(fID, nam, julien, pint_in, pint_ou, v3,&105 time_in, lon_in, lat_in, pcen_in, ptrop_ou)110 SUBROUTINE regr_pr_time_av(fID, nam, julien, Ploc, Pre_in, Pre_ou, v3, Pgnd_ou,& 111 time_in, lon_in, lat_in, Ptrp_ou) 106 112 ! 107 113 !------------------------------------------------------------------------------- … … 118 124 USE slopes_m, ONLY: slopes 119 125 USE mod_phys_lmdz_mpi_data, ONLY: is_mpi_root 120 USE mod_grid_phy_lmdz, ONLY: nbp_lon, nbp_lat,nbp_lev126 USE mod_grid_phy_lmdz, ONLY: nlon=>nbp_lon, nlat=>nbp_lat, nlev_ou=>nbp_lev 121 127 USE mod_phys_lmdz_transfert_para, ONLY: scatter2d, scatter 122 128 USE phys_cal_mod, ONLY: calend, year_len, days_elapsed, jH_cur 123 129 !------------------------------------------------------------------------------- 124 130 ! Arguments: 125 INTEGER, INTENT(IN) :: fID!--- NetCDF file ID131 INTEGER, INTENT(IN) :: fID !--- NetCDF file ID 126 132 CHARACTER(LEN=13), INTENT(IN) :: nam(:) !--- NetCDF variables names 127 REAL, INTENT(IN) :: julien !--- Days since Jan 1st 128 !--- File & LMDZ (resp. decreasing & increasing order) interfaces pressure, Pa 129 REAL, INTENT(IN) :: pint_in(:) !--- in: file (nlev_in+1) 130 REAL, INTENT(IN) :: pint_ou(:,:) !--- out: LMDZ (klon,nbp_lev+1) 131 REAL, INTENT(OUT) :: v3(:,:,:) !--- Regridded fld (klon,llm,n_var) 133 REAL, INTENT(IN) :: julien !--- Days since Jan 1st 134 CHARACTER(LEN=1), INTENT(IN) :: Ploc !--- Pressures locations 135 !--- File/LMDZ (resp. decreasing & increasing order) pressure, Pa 136 ! At cells centers or interfaces depending on "Ploc" keyword (C/I) 137 REAL, INTENT(IN) :: Pre_in(:) !--- in: file (nlev_in[+1]) 138 REAL, INTENT(IN) :: Pre_ou(:,:) !--- out: LMDZ (klon,nlev_ou[+1]) 139 REAL, INTENT(OUT) :: v3(:,:,:) !--- Regr. fld (klon,nlev_ou,n_var) 140 REAL, INTENT(IN), OPTIONAL :: Pgnd_ou(:) !--- LMDZ ground pressure (klon) 132 141 REAL, INTENT(IN), OPTIONAL :: time_in(:) !--- Records times, in days 133 142 ! since Jan 1 of current year 134 143 REAL, INTENT(IN), OPTIONAL :: lon_in(:) !--- File longitudes vector (klon) 135 144 REAL, INTENT(IN), OPTIONAL :: lat_in(:) !--- File latitudes vector (klon) 136 REAL, INTENT(IN), OPTIONAL :: pcen_in(:) !--- File mid-layers pres (nlev_in) 137 REAL, INTENT(IN), OPTIONAL :: ptrop_ou(:)!--- LMDZ tropopause pres (klon) 145 REAL, INTENT(IN), OPTIONAL :: Ptrp_ou(:) !--- LMDZ tropopause pres (klon) 138 146 !------------------------------------------------------------------------------- 139 147 ! Local variables: … … 142 150 CHARACTER(LEN=80) :: sub 143 151 CHARACTER(LEN=320) :: str 144 INTEGER :: vID, ncerr, n_var, ibot, i bo0, nn, itrp145 INTEGER :: i, nlev_in, n_dim, itop, it o0, i0152 INTEGER :: vID, ncerr, n_var, ibot, iout, nn 153 INTEGER :: i, nlev_in, n_dim, itop, itrp, i0 146 154 LOGICAL :: lAdjTro !--- Need to adjust tropopause 147 155 REAL :: y_frac !--- Elapsed year fraction 148 156 REAL :: alpha, beta, al !--- For stretching/interpolation 149 157 REAL :: SigT_in, SigT_ou !--- Input and output tropopauses 150 REAL :: Sig_bot, Sig_top !--- Fully strained layer bounds 151 REAL :: Sig_bo0, Sig_to0 !--- Total strained layers bounds 152 REAL :: Sig_in(SIZE(pint_in)) !--- Input field sigma levels 153 REAL :: Sig_ou (nbp_lev+1) !--- Output LMDZ sigma levels 154 REAL :: phi (nbp_lev+1) !--- Stretching exponent anomaly 155 REAL :: pstr_ou(nbp_lev+1) !--- Stretched pressure levels 156 REAL :: pintou (nbp_lev+1) !--- pint_ou in reversed order 157 REAL :: v1(nbp_lon,nbp_lat,SIZE(pint_in)-1,SIZE(nam)) 158 REAL :: v2(klon, SIZE(pint_in)-1,SIZE(nam)) 159 ! v1: Field read/interpol at time "julien" on the global "dynamics" horiz. grid. 160 ! v2: Field scattered to the partial "physics" horizontal grid. 158 REAL :: Sig_bot, Sig_top !--- Bounds of quasi-hat function 159 REAL :: Sig_bo0, Sig_to0 !--- Lower/upper tropopauses 160 REAL :: Sig_in (SIZE(Pre_in)) !--- Input field sigma levels 161 REAL :: Sig_ou (SIZE(Pre_ou,2)) !--- Output LMDZ sigma levels 162 REAL :: phi (SIZE(Pre_ou,2)) !--- Stretching exponent anomaly 163 REAL :: Pstr_ou(SIZE(Pre_ou,2)) !--- Stretched pressure levels 164 REAL :: Pres_ou(SIZE(Pre_ou,2)) !--- Pre_ou(i,:), reversed order 165 REAL, DIMENSION(nlon, nlat) :: pg1, pt1, ot1 166 REAL, DIMENSION(klon) :: Pgnd_in, Ptrp_in, Otrp_in 167 REAL, DIMENSION(klon) :: Ptrop_ou, Pgrnd_ou 168 ! * The following fields are scattered to the partial "physics" horizontal grid. 169 REAL, POINTER :: v2(:,:,:) !--- Current time ozone fields 161 170 ! In the 2D file case, the values are the same for all longitudes. 162 ! "v2(i, k, l)" is at longitude-latitude "xlon(i)-xlat(i)". 163 ! Both are for pressure interval "press_in_edg(k:k+1)]" and variable "nam(l)" 164 REAL, DIMENSION(nbp_lon, nbp_lat) :: ps1, pt1, ot1 165 REAL, DIMENSION(klon) :: ps2, pt2, ot2, ptropou 171 ! "v2(i, k, l)" is at longitude-latitude "xlon(i)-xlat(i)" and name "nam(l)" 172 ! Both are: * if Ploc=='I' in pressure interval "press_in_edg(k:k+1)" 173 ! * if Ploc=='C' at pressure "press_in_cen(k)" 174 REAL, TARGET :: & 175 v2i(klon,SIZE(Pre_in)-1,SIZE(nam)), & !--- v2 in Ploc=='I' case 176 v2c(klon,SIZE(Pre_in) ,SIZE(nam)) !--- v2 in Ploc=='C' case 166 177 LOGICAL :: ll 167 178 !--- For debug 168 REAL, DIMENSION(klon) :: ptrop_in, ptrop_ef!, dzStrain, dzStrain0 169 ! REAL, DIMENSION(klon,nbp_lev+1) :: pstrn_ou, phii 179 REAL, DIMENSION(klon) :: Ptrop_in, Ptrop_ef 180 REAL, DIMENSION(klon) :: dzStrain, dzStrain0 181 REAL, DIMENSION(klon,SIZE(Pre_ou,2)) :: Pstrn_ou, phii 170 182 !------------------------------------------------------------------------------- 171 183 sub="regr_pr_time_av" 172 nlev_in=SIZE(pint_in)-1 173 CALL assert(SIZE(v3,1)==klon, TRIM(sub)//" v3 klon") 174 CALL assert(SIZE(v3,2)==nbp_lev, TRIM(sub)//" v3 nbp_lev") 184 nlev_in=SIZE(Pre_in); IF(Ploc=='I') nlev_in=nlev_in-1 185 IF(Ploc=='I') THEN; v2 => v2i; ELSE; v2 => v2c; END IF 186 CALL assert(SIZE(Pre_ou,1)==klon,TRIM(sub)//" Pre_ou klon") 187 CALL assert(SIZE(v3,1)==klon, TRIM(sub)//" v3 klon") 188 CALL assert(SIZE(v3,2)==nlev_ou, TRIM(sub)//" v3 nlev_ou") 189 IF(Ploc=='I') CALL assert(SIZE(Pre_ou,2)==nlev_ou+1,TRIM(sub)//" Pre_ou nlev_ou+1") 190 IF(Ploc=='C') CALL assert(SIZE(Pre_ou,2)==nlev_ou ,TRIM(sub)//" Pre_ou nlev_ou") 175 191 n_var = assert_eq(SIZE(nam),SIZE(v3,3),TRIM(sub)//" v3 n_var") 176 CALL assert(SIZE(pint_ou,1)==klon ,TRIM(sub)//" pint_ou klon") 177 CALL assert(SIZE(pint_ou,2)==nbp_lev+1,TRIM(sub)//" pint_ou nbp_lev+1") 178 IF(PRESENT(lon_in)) CALL assert(SIZE(lon_in )==klon,TRIM(sub)//" lon_in klon") 179 IF(PRESENT(lat_in)) CALL assert(SIZE(lat_in )==klon,TRIM(sub)//" lat_in klon") 180 IF(PRESENT(ptrop_ou)) CALL assert(SIZE(ptrop_ou)==klon,TRIM(sub)//" ptrop_ou klon") 181 IF(PRESENT(pcen_in)) CALL assert(SIZE(pcen_in )==nlev_in,TRIM(sub)//" pcen_in") 182 lAdjTro=PRESENT(ptrop_ou) 183 IF(lAdjTro.AND.(.NOT.PRESENT(lat_in).OR..NOT.PRESENT(pcen_in))) & 184 CALL abort_physic(sub, 'Missing lat_in and/or pcen_in (adjust_tropopause=T)', 1) 192 IF(PRESENT(Pgnd_ou)) CALL assert(SIZE(Pgnd_ou)==klon,TRIM(sub)//" Pgnd_ou klon") 193 IF(PRESENT(lon_in)) CALL assert(SIZE(lon_in )==klon,TRIM(sub)//" lon_in klon") 194 IF(PRESENT(lat_in)) CALL assert(SIZE(lat_in )==klon,TRIM(sub)//" lat_in klon") 195 IF(PRESENT(Ptrp_ou)) CALL assert(SIZE(Ptrp_ou)==klon,TRIM(sub)//" Ptrp_ou klon") 196 lAdjTro=PRESENT(Ptrp_ou) 197 IF(lAdjTro) THEN 198 IF(.NOT.PRESENT(lat_in)) & 199 CALL abort_physic(sub, 'Missing lat_in (required if adjust_tropopause=T)', 1) 200 IF(.NOT.PRESENT(Pgnd_ou).AND.Ploc=='C') & 201 CALL abort_physic(sub, 'Missing ground Pr(required if adjust_tropopause=T)', 1) 202 IF(PRESENT(Pgnd_ou)) THEN; Pgrnd_ou=Pgnd_ou; ELSE; Pgrnd_ou=Pre_ou(:,1); END IF 203 END IF 185 204 186 205 !$OMP MASTER … … 189 208 !=== CHECK WHICH FIELDS ARE AVAILABLE IN THE INPUT FILE 190 209 IF(lfirst) THEN 191 lPrS urf=NF90_INQ_VARID(fID,"ps" ,vID)==NF90_NOERR192 lPrT rop=NF90_INQ_VARID(fID,"tropopause_air_pressure",vID)==NF90_NOERR193 lO3T rop=NF90_INQ_VARID(fID,"tro3_at_tropopause" ,vID)==NF90_NOERR210 lPrSfile=lAdjTro.AND.NF90_INQ_VARID(fID,"ps" ,vID)==NF90_NOERR 211 lPrTfile=lAdjTro.AND.NF90_INQ_VARID(fID,"tropopause_air_pressure",vID)==NF90_NOERR 212 lO3Tfile=lAdjTro.AND.NF90_INQ_VARID(fID,"tro3_at_tropopause" ,vID)==NF90_NOERR 194 213 CALL NF95_INQ_DIMID(fID,"time",vID) 195 214 CALL NF95_INQUIRE_DIMENSION(fID,vID,nclen=ntim_in) 196 215 linterp=PRESENT(time_in).AND.ntim_in==14 216 ALLOCATE(v1(nlon,nlat,nlev_in,n_var)) 197 217 IF(linterp) THEN 198 ALLOCATE(v1m(nbp_lon,nbp_lat,nlev_in,n_var)) 199 ALLOCATE(v1p(nbp_lon,nbp_lat,nlev_in,n_var)) 200 ALLOCATE(psm(nbp_lon,nbp_lat),psp(nbp_lon,nbp_lat)) 201 ALLOCATE(ptm(nbp_lon,nbp_lat),ptp(nbp_lon,nbp_lat)) 202 IF(lO3Trop) ALLOCATE(otm(nbp_lon,nbp_lat),otp(nbp_lon,nbp_lat)) 218 ALLOCATE(v1m(nlon,nlat,nlev_in,n_var),v1p(nlon,nlat,nlev_in,n_var)) 219 IF(lPrSfile) ALLOCATE(pgm(nlon,nlat),pgp(nlon,nlat)) 220 IF(lPrTfile) ALLOCATE(ptm(nlon,nlat),ptp(nlon,nlat)) 221 IF(lO3Tfile) ALLOCATE(otm(nlon,nlat),otp(nlon,nlat)) 203 222 END IF 204 223 !--- INITIAL INDEX: LOCATE A LAYER WELL ABOVE TROPOPAUSE (50hPa) 205 IF(lAdjTro) itrp0=locate(pcen_in,pTropUp) 206 CALL msg(lPrSurf,'Using GROUND PRESSURE from input O3 forcing file.',sub) 207 CALL msg(linterp,'Monthly O3 files => ONLINE TIME INTERPOLATION.',sub) 208 CALL msg(lAdjTro,'o3 forcing file tropopause location uses:',sub) 209 IF(lPrTrop) THEN 210 CALL msg(lAdjTro,' PRESSURE AT TROPOPAUSE from file.') 211 ELSE IF(lO3Trop) THEN 212 CALL msg(lAdjTro,' O3 CONCENTRATION AT TROPOPAUSE from file.') 213 ELSE IF(lo3tp) THEN 214 CALL msg(lAdjTro,' PARAMETRIZED O3 concentration at tropopause.') 215 ELSE 216 CALL msg(lAdjTro,' CONSTANT O3 concentration at tropopause.') 217 END IF 224 IF(lAdjTro) itrp0=locate(Pre_in,pTropUp) 225 CALL msg(linterp,'Monthly O3 files => ONLINE TIME INTERPOLATION.' ,sub) 226 CALL msg(lPrSfile,'Using GROUND PRESSURE from input O3 forcing file.',sub) 227 CALL msg(lAdjTro ,'o3 forcing file tropopause location uses:' ,sub) 228 IF(lPrTfile) THEN; str=' INPUT FILE PRESSURE' 229 ELSE IF(lO3Tfile) THEN; str=' INPUT FILE O3 CONCENTRATION' 230 ELSE IF(lO3Tpara) THEN; str=' PARAMETRIZED O3 concentration' 231 ELSE; str=' CONSTANT O3 concentration'; END IF 232 CALL msg(lAdjTro,TRIM(str)//' at tropopause') 218 233 END IF 219 234 … … 223 238 !=== TIME INTERPOLATION FOR MONTHLY INPUT FILES 224 239 IF(linterp) THEN 225 WRITE(str,'( 3(a,f12.8))')'Interpolating O3 at julian day ',julien,' from '&226 &//'fields at times ',time_in(irec),' and ', time_in(irec+1)240 WRITE(str,'(a,f12.8,2(a,f5.1))')'Interpolating O3 at julian day ',julien,& 241 ' from fields at times ',time_in(irec),' and ', time_in(irec+1) 227 242 CALL msg(.TRUE.,str,sub) 228 243 al=(time_in(irec+1)-julien)/(time_in(irec+1)-time_in(irec)) 229 244 v1=al*v1m+(1.-al)*v1p 230 IF(lPrS urf) ps1=al*psm+(1.-al)*psp231 IF(lPrT rop) pt1=al*ptm+(1.-al)*ptp232 IF(lO3T rop) ot1=al*otm+(1.-al)*otp245 IF(lPrSfile) pg1=al*pgm+(1.-al)*pgp 246 IF(lPrTfile) pt1=al*ptm+(1.-al)*ptp 247 IF(lO3Tfile) ot1=al*otm+(1.-al)*otp 233 248 END IF 234 249 END IF 235 250 !$OMP END MASTER 236 251 IF(lfirst) THEN 237 lfirst=.FALSE.; CALL bcast(lfirst)238 IF(lAdjTro) CALL bcast(itrp0)239 CALL bcast(lPr Trop); CALL bcast(lPrSurf)240 CALL bcast(lO3T rop); CALL bcast(linterp)252 lfirst=.FALSE.; CALL bcast(lfirst) 253 IF(lAdjTro) CALL bcast(itrp0) 254 CALL bcast(lPrSfile); CALL bcast(lPrTfile) 255 CALL bcast(lO3Tfile); CALL bcast(linterp) 241 256 END IF 242 257 CALL scatter2d(v1,v2) 243 !--- No "ps" in input file => assumed to be equal to current LMDZ ground press 244 IF(lPrSurf) THEN; CALL scatter2d(ps1,ps2); ELSE; ps2=pint_ou(:,1); END IF 245 IF(lPrTrop) CALL scatter2d(pt1,pt2) 246 IF(lO3Trop) CALL scatter2d(ot1,ot2) 247 248 !--- REGRID IN PRESSURE ; 3rd index inverted because "paprs" is decreasing 249 IF(.NOT.lAdjTro) THEN 258 IF(lPrSfile) CALL scatter2d(pg1,Pgnd_in) 259 IF(lPrTfile) CALL scatter2d(pt1,Ptrp_in) 260 IF(lO3Tfile) CALL scatter2d(ot1,Otrp_in) 261 !--- No ground pressure in input file => choose it to be the one of LMDZ 262 IF(lAdjTro.AND..NOT.lPrSfile) Pgnd_in(:)=Pgrnd_ou(:) 263 264 !------------------------------------------------------------------------------- 265 IF(.NOT.lAdjTro) THEN !--- REGRID IN PRESSURE ; NO TROPOPAUSE ADJUSTMENT 266 !------------------------------------------------------------------------------- 250 267 DO i=1,klon 251 pintou = pint_ou(i,nbp_lev+1:1:-1) 252 CALL regr_conserv(1,v2(i,:,:), pint_in(:), pintou(:), & 253 v3(i,nbp_lev:1:-1,:), slopes(1,v2(i,:,:), pint_in(:))) 268 Pres_ou=Pre_ou(i,SIZE(Pre_ou,2):1:-1) !--- pplay & paprs are decreasing 269 IF(Ploc=='C') CALL regr_lint (1,v2(i,:,:), LOG(Pre_in(:)), & 270 LOG(Pres_ou(:)), v3(i,nlev_ou:1:-1,:)) 271 IF(Ploc=='I') CALL regr_conserv(1,v2(i,:,:), Pre_in(:) , & 272 Pres_ou(:) , v3(i,nlev_ou:1:-1,:), slopes(1,v2(i,:,:), Pre_in(:))) 254 273 END DO 255 ELSE 274 !------------------------------------------------------------------------------- 275 ELSE !--- REGRID IN PRESSURE ; TROPOPAUSE ADJUSTMENT 276 !------------------------------------------------------------------------------- 256 277 y_frac=(REAL(days_elapsed)+jH_cur)/year_len 257 278 … … 259 280 DO i=1,klon 260 281 261 !--- LOCAL INPUT/OUTPUT (FILE/LMDZ) SIGMA LEVELS AT INTERFACES262 pintou=pint_ou(i,nbp_lev+1:1:-1) !--- increasing values263 Sig_in(:) = [pint_in(1:nlev_in+1)/ps2(i)]!--- increasing values264 Sig_ou(:) = [pintou (1:nbp_lev)/ps2(i),1.0]!--- increasing values282 !--- INPUT/OUTPUT (FILE/LMDZ) SIGMA LEVELS IN CURRENT COLUMN 283 Pres_ou = Pre_ou(i,SIZE(Pre_ou,2):1:-1)!--- pplay & paprs are decreasing 284 Sig_in(:) = Pre_in (:)/Pgnd_in(i) !--- increasing values 285 Sig_ou(:) = Pres_ou(:)/Pgnd_ou(i) !--- increasing values 265 286 266 287 !--- INPUT (FILE) SIGMA LEVEL AT TROPOPAUSE ; extreme values are filtered … … 268 289 ! ozone hole fooling the crude chemical tropopause detection algorithm. 269 290 SigT_in = get_SigTrop(i,itrp) 270 SigT_in=MIN(SigT_in,ChemPTrMax/ ps2(i))!--- too low value filtered271 SigT_in=MAX(SigT_in,ChemPTrMin/ ps2(i))!--- too high value filtered291 SigT_in=MIN(SigT_in,ChemPTrMax/Pgnd_in(i)) !--- too low value filtered 292 SigT_in=MAX(SigT_in,ChemPTrMin/Pgnd_ou(i)) !--- too high value filtered 272 293 273 294 !--- OUTPUT (LMDZ) SIGMA LEVEL AT TROPOPAUSE ; too high variations of the 274 ! dynamical tropopause (especially in filaments) are conterbalanced with a275 ! filter ensuring it stays within a certain distance around input (file)295 ! dynamical tropopause (especially in filaments) are conterbalanced with 296 ! a filter ensuring it stays within a certain distance around input (file) 276 297 ! tropopause, hence avoiding avoid a too thick stretched region ; a final 277 298 ! extra-safety filter keeps the tropopause pressure value realistic. 278 SigT_ou = ptrop_ou(i)/ps2(i) 279 IF(SigT_ou<SigT_in/rho) SigT_ou=SigT_in/rho !--- too low value w/r input 280 IF(SigT_ou>SigT_in*rho) SigT_ou=SigT_in*rho !--- too high value w/r input 281 SigT_ou=MIN(SigT_ou,DynPTrMax/ps2(i)) !--- too low value filtered 282 SigT_ou=MAX(SigT_ou,DynPTrMin/ps2(i)) !--- too high value filtered 283 ptropou(i)=SigT_ou*ps2(i) 284 285 !--- FULLY STRETCHED LAYER BOUNDS (alpha power law fully applied) 299 SigT_ou = Ptrp_ou(i)/Pgnd_ou(i) 300 IF(SigT_ou<SigT_in/rho) SigT_ou=SigT_in/rho !--- too low value w/r input 301 IF(SigT_ou>SigT_in*rho) SigT_ou=SigT_in*rho !--- too high value w/r input 302 SigT_ou=MIN(SigT_ou,DynPTrMax/Pgnd_ou(i)) !--- too low value filtered 303 SigT_ou=MAX(SigT_ou,DynPTrMin/Pgnd_ou(i)) !--- too high value filtered 304 Ptrop_ou(i)=SigT_ou*Pgnd_ou(i) 305 iout = locate(Sig_ou(:),SigT_ou) 306 307 !--- POWER LAW COEFFICIENT FOR TROPOPAUSES MATCHING 286 308 alpha = LOG(SigT_in/SigT_ou)/LOG(SigT_ou) 287 Sig_bot = MAX(SigT_in,SigT_ou) ; ibot = locate(Sig_ou(:),Sig_bot) 288 Sig_top = MIN(SigT_in,SigT_ou) ; itop = locate(Sig_ou(:),Sig_top)289 290 !--- PARTIALLY STRETCHED LAYER BOUNDS (fraction of alpha applied)291 ! The used formulae ensure the first derivative stays positive.292 beta = LOG(Sig_top)/LOG(Sig_bot)293 Sig_bo0 = Sig_bot ; IF(alpha<0.) Sig_bo0 = Sig_bot**(1/beta)294 Sig_to0 = Sig_top ; IF(alpha>0.) Sig_to0 = Sig_top ** beta295 296 !--- SOME ADDITIONAL MARGIN, PROPORTIONAL TO STRETCHED REGION THICKNESS297 !--- gamma<log(Sig_bo0/|alpha|) to keep Sig_bo0<1298 Sig_bo0 = MIN(Sig_bo0*EXP( gamm*ABS(alpha)), 0.95+(1.-0.95)*Sig_bo0)299 Sig_to0 = Sig_to0*EXP(-gamm*ABS(alpha))300 ibo0 = locate(Sig_ou(:),Sig_bo0)301 ito0 = locate(Sig_ou(:),Sig_to0)302 303 !--- STRETCHING POWER LAW FUNCTION:304 ! 0 in [0,Sig_to0] and [Sig_bo0,1] ; 1 in [Sig_bot,Sig_top]305 ! 0 ->1 in [Sig_to0,Sig_top] 1->0 in [Sig_bot,Sig_bo0]309 310 !--- DETERMINE STRETCHING DOMAIN UPPER AND LOWER BOUNDS 311 Sig_bo0 = MAX(SigT_in,SigT_ou) !--- lowest tropopause 312 Sig_to0 = MIN(SigT_in,SigT_ou) !--- highest tropopause 313 beta = (Sig_bo0/Sig_to0)**gamm !--- stretching exponent 314 Sig_bot = MIN(Sig_bo0*beta,0.1*(9.+Sig_bot)) !--- must be <1 315 ibot = locate(Sig_ou(:),Sig_bot) !--- layer index 316 IF(ibot-iout<2) THEN !--- at least one layer thick 317 ibot=MIN(iout+2,nlev_ou); Sig_bot=Sig_ou(ibot) 318 END IF 319 Sig_top = Sig_to0/beta !--- upper bound 320 itop = locate(Sig_ou(:),Sig_top) !--- layer index 321 IF(iout-itop<2) THEN !--- at least one layer thick 322 itop=MAX(iout-2,1); Sig_top=Sig_ou(itop) 323 END IF 324 325 !--- STRETCHING POWER LAW LOCALIZATION FUNCTION: 326 ! 0 in [0,Sig_top] 0->1 in [Sig_top,SigT_ou] 327 ! 0 in [Sig_bot,1] 1->0 in [SigT_ou, Sig_bot] 306 328 phi(:)=0. 307 phi(itop+1:ibot) = 1. 308 phi(ito0+1:itop) = (1.-LOG(Sig_to0)/LOG(Sig_ou(ito0+1:itop)))& 309 *LOG(Sig_top)/LOG(Sig_top/Sig_to0) 310 phi(ibot+1:ibo0) = (1.-LOG(Sig_bo0)/LOG(Sig_ou(ibot+1:ibo0)))& 311 *LOG(Sig_bot)/LOG(Sig_bot/Sig_bo0) 329 phi(itop+1:iout) = (1.-LOG(Sig_top)/LOG(Sig_ou(itop+1:iout)))& 330 *LOG(SigT_ou)/LOG(SigT_ou/Sig_top) 331 phi(iout+1:ibot) = (1.-LOG(Sig_bot)/LOG(Sig_ou(iout+1:ibot)))& 332 *LOG(SigT_ou)/LOG(SigT_ou/Sig_bot) 312 333 313 334 !--- LOCALY STRECHED OUTPUT (LMDZ) PRESSURE PROFILES (INCREASING ORDER) 314 pstr_ou(:) = pintou(:) * Sig_ou(:)**(alpha*phi(:))335 Pstr_ou(:) = Pres_ou(:) * Sig_ou(:)**(alpha*phi(:)) 315 336 316 337 !--- REGRID INPUT PROFILE ON STRAINED VERTICAL OUTPUT LEVELS 317 CALL regr_conserv(1, v2(i,:,:), pint_in(:), pstr_ou(:), & 318 v3(i,nbp_lev:1:-1,:), slopes(1,v2(i,:,:),pint_in(:))) 338 IF(Ploc=='C') CALL regr_lint (1, v2(i,:,:), LOG(Pre_in(:)), & 339 LOG(Pstr_ou(:)), v3(i,nlev_ou:1:-1,:)) 340 IF(Ploc=='I') CALL regr_conserv(1, v2(i,:,:), Pre_in(:) , & 341 Pstr_ou(:) , v3(i,nlev_ou:1:-1,:), slopes(1,v2(i,:,:), Pre_in(:))) 319 342 320 343 !--- CHECK CONCENTRATIONS. strato: 50ppbV-15ppmV ; tropo: 5ppbV-300ppbV. 321 i0=n bp_lev-locate(pintou(:),ptropou(i))+1322 ll=check_ozone(v3(i, 1:i0 344 i0=nlev_ou-locate(Pres_ou(:),Ptrop_ou(i))+1 345 ll=check_ozone(v3(i, 1:i0-1 ,1),lon_in(i),lat_in(i),1 ,'troposphere', & 323 346 5.E-9,3.0E-7) 324 347 ! IF(ll) CALL abort_physic(sub, 'Inconsistent O3 values in troposphere', 1) 325 ll=check_ozone(v3(i,i0:n bp_lev,1),lon_in(i),lat_in(i),i0,'stratosphere', &348 ll=check_ozone(v3(i,i0:nlev_ou,1),lon_in(i),lat_in(i),i0,'stratosphere', & 326 349 5.E-8,1.5E-5) 327 350 ! IF(ll) CALL abort_physic(sub, 'Inconsistent O3 values in stratosphere', 1) 328 351 329 IF( debug) THEN330 ! dzStrain0(i)=7.*LOG(Sig_bo0/Sig_to0)331 ! dzStrain (i)=7.*LOG(Sig_bot/Sig_top)332 ptrop_in(i) = SigT_in*ps2(i)333 ! Pstrn_ou(i,:)= pstr_ou334 ! phii(i,:)=phi(:)335 ptrop_ef(i)=chem_tropopause(i, itrp, locate(pintou(:),PTropUp),&336 pintou(:), v3(:,nbp_lev+1:1:-1,1),o3trop=o3t0)352 IF(ldebug) THEN 353 dzStrain0(i) = SIGN(7.*LOG(Sig_bo0/Sig_to0),SigT_in-SigT_ou) 354 dzStrain (i) = SIGN(7.*LOG(Sig_bot/Sig_top),SigT_in-SigT_ou) 355 Ptrop_in (i) = SigT_in*Pgnd_in(i) 356 Pstrn_ou(i,:)= Pstr_ou 357 phii(i,:) = phi(:) 358 Ptrop_ef(i) = PTrop_chem(i, itrp, locate(Pres_ou(:),PTropUp), & 359 Pres_ou(:), v3(:,nlev_ou:1:-1,1),o3trop=o3t0) 337 360 END IF 338 361 END DO 339 IF(debug) THEN 340 ! CALL writefield_phy('PreSt_ou' ,Pstrn_ou,nbp_lev+1) !--- Strained pressure 341 ! CALL writefield_phy('dzStrain' ,dzStrain ,1) !--- Fully & total strained 342 ! CALL writefield_phy('dzStrain0',dzStrain0,1) !--- regions thickness 343 ! CALL writefield_phy('phi',phii,nbp_lev+1) !--- Localisation function 344 !--- Tropopauses pressures: 345 CALL writefield_phy('PreTr_in',ptrop_in,1) !--- Input and effective 346 CALL writefield_phy('PreTr_ef',ptrop_ef,1) ! chemical tropopauses 347 END IF 348 END IF 349 IF(debug) THEN 350 IF(lAdjTro) & 351 CALL writefield_phy('PreTr_ou',ptropou,1) !--- LMDz dyn tropopause 362 END IF 363 IF(ldebug.AND.lAdjTro) THEN 364 CALL writefield_phy('PreSt_ou' ,Pstrn_ou,SIZE(Pre_ou,2)) !--- Strained Pres 365 CALL writefield_phy('dzStrain' ,dzStrain ,1) !--- Strained thickness 366 CALL writefield_phy('dzStrain0',dzStrain0,1) !--- Tropopauses distance 367 CALL writefield_phy('phi',phii,nlev_ou) !--- Localization function 368 !--- Tropopauses pressures: 369 CALL writefield_phy('PreTr_in',Ptrop_in,1) !--- Input and effective 370 CALL writefield_phy('PreTr_ou',Ptrop_ou,1) !--- LMDz dyn tropopause 371 CALL writefield_phy('PreTr_ef',Ptrop_ef,1) !--- Effective chem tropop 372 END IF 373 IF(ldebug) THEN 352 374 CALL writefield_phy('Ozone_in',v2(:,:,1),nlev_in)!--- Raw input O3 field 353 CALL writefield_phy('Ozone_ou',v3(:,:,1),n bp_lev)!--- Output ozone field354 CALL writefield_phy('P int_ou' ,pint_ou,1+nbp_lev)!--- LMDZ unstreched Press375 CALL writefield_phy('Ozone_ou',v3(:,:,1),nlev_ou)!--- Output ozone field 376 CALL writefield_phy('Pres_ou' ,Pre_ou,SIZE(Pre_ou,2))!--- LMDZ Pressure 355 377 END IF 356 378 … … 369 391 CALL get_3Dfields(v1) !--- Read ozone field(s) 370 392 IF(lAdjTro) THEN !--- Additional files for fields strain 371 IF(lPrS urf) CALL get_2Dfield(ps1,"ps")372 IF(lPrT rop) CALL get_2Dfield(pt1,"tropopause_air_pressure")373 IF(lO3T rop) CALL get_2Dfield(ot1,"tro3_at_tropopause")393 IF(lPrSfile) CALL get_2Dfield(pg1,"ps") 394 IF(lPrTfile) CALL get_2Dfield(pt1,"tropopause_air_pressure") 395 IF(lO3Tfile) CALL get_2Dfield(ot1,"tro3_at_tropopause") 374 396 END IF 375 397 ELSE !=== MONTHLY FILES: GET 2 NEAREST RECS … … 383 405 CALL get_3Dfields(v1m) !--- Read ozone field(s) 384 406 IF(lAdjTro) THEN !--- Additional files for fields strain 385 IF(lPrS urf) CALL get_2Dfield(psm,"ps")386 IF(lPrT rop) CALL get_2Dfield(ptm,"tropopause_air_pressure")387 IF(lO3T rop) CALL get_2Dfield(otm,"tro3_at_tropopause")407 IF(lPrSfile) CALL get_2Dfield(pgm,"ps") 408 IF(lPrTfile) CALL get_2Dfield(ptm,"tropopause_air_pressure") 409 IF(lO3Tfile) CALL get_2Dfield(otm,"tro3_at_tropopause") 388 410 END IF 389 411 ELSE !=== SHIFT FIELDS … … 394 416 v1m=v1p !--- Ozone fields 395 417 IF(lAdjTro) THEN !--- Additional files for fields strain 396 IF(lPrS urf) psm=psp !--- Surface pressure397 IF(lPrT rop) ptm=ptp !--- Tropopause pressure398 IF(lO3T rop) otm=otp !--- Tropopause ozone418 IF(lPrSfile) pgm=pgp !--- Surface pressure 419 IF(lPrTfile) ptm=ptp !--- Tropopause pressure 420 IF(lO3Tfile) otm=otp !--- Tropopause ozone 399 421 END IF 400 422 END IF … … 405 427 CALL get_3Dfields(v1p) !--- Read ozone field(s) 406 428 IF(lAdjTro) THEN !--- Additional files for fields strain 407 IF(lPrS urf) CALL get_2Dfield(psp,"ps")408 IF(lPrT rop) CALL get_2Dfield(ptp,"tropopause_air_pressure")409 IF(lO3T rop) CALL get_2Dfield(otp,"tro3_at_tropopause")429 IF(lPrSfile) CALL get_2Dfield(pgp,"ps") 430 IF(lPrTfile) CALL get_2Dfield(ptp,"tropopause_air_pressure") 431 IF(lO3Tfile) CALL get_2Dfield(otp,"tro3_at_tropopause") 410 432 END IF 411 433 irec=irec-1 … … 438 460 !--- Flip latitudes: ascending in input file, descending in "rlatu". 439 461 IF(n_dim==3) THEN 440 v(1,:) = v(1,n bp_lat:1:-1)441 v(2:,:)= SPREAD(v(1,:),DIM=1,ncopies=n bp_lon-1) !--- Duplication462 v(1,:) = v(1,nlat:1:-1) 463 v(2:,:)= SPREAD(v(1,:),DIM=1,ncopies=nlon-1) !--- Duplication 442 464 ELSE 443 v(:,:) = v(:,n bp_lat:1:-1)465 v(:,:) = v(:,nlat:1:-1) 444 466 END IF 445 467 … … 471 493 !--- Flip latitudes: ascending in input file, descending in "rlatu". 472 494 IF(n_dim==3) THEN 473 v(1,:,:,:) = v(1,n bp_lat:1:-1,:,:)474 v(2:,:,:,:)= SPREAD(v(1,:,:,:),DIM=1,ncopies=n bp_lon-1) !--- Duplication495 v(1,:,:,:) = v(1,nlat:1:-1,:,:) 496 v(2:,:,:,:)= SPREAD(v(1,:,:,:),DIM=1,ncopies=nlon-1) !--- Duplication 475 497 ELSE 476 v(:,:,:,:) = v(:,n bp_lat:1:-1,:,:)498 v(:,:,:,:) = v(:,nlat:1:-1,:,:) 477 499 END IF 478 500 … … 485 507 !------------------------------------------------------------------------------- 486 508 ! 487 FUNCTION get_SigTrop(ih,it) 488 ! 489 !------------------------------------------------------------------------------- 490 ! Arguments: 509 FUNCTION get_SigTrop(ih,it) RESULT(out) 510 ! 511 !------------------------------------------------------------------------------- 512 ! Arguments: 513 REAL :: out 491 514 INTEGER, INTENT(IN) :: ih 492 515 INTEGER, INTENT(OUT) :: it 493 REAL :: get_Sigtrop 494 !------------------------------------------------------------------------------- 495 !--- Pressure at tropopause is read in the forcing file 496 IF(lPrTrop) THEN !--- PrTrop KNOWN FROM FILE 497 get_SigTrop=pt2(ih)/ps2(ih); RETURN 498 END IF 499 !--- Chemical tropopause definition is used using a particular threshold 500 IF(lO3Trop) THEN !--- o3trop KNOWN FROM FILE 501 get_SigTrop=chem_tropopause(ih,it,itrp0,pint_in,v2(:,:,1),pcen_in,ot2(ih)) 502 ELSE IF(lo3tp) THEN !--- o3trop PARAMETRIZATION 503 get_SigTrop=chem_tropopause(ih,it,itrp0,pint_in,v2(:,:,1),pcen_in) 504 ELSE !--- o3trop CONSTANT 505 get_SigTrop=chem_tropopause(ih,it,itrp0,pint_in,v2(:,:,1),pcen_in,o3t0) 506 END IF 507 get_SigTrop=get_SigTrop/ps2(ih) 516 !------------------------------------------------------------------------------- 517 !--- Pressure at tropopause read from the forcing file 518 IF(lPrTfile) THEN; out=Ptrp_in(ih)/Pgnd_in(ih); RETURN; END IF 519 520 !--- Chemical tropopause definition based on a particular threshold 521 IF(lO3Tfile) THEN; out=PTrop_chem(ih,it,itrp0,Pre_in,v2(:,:,1),Otrp_in(ih)) 522 ELSE IF(lO3Tpara) THEN; out=PTrop_chem(ih,it,itrp0,Pre_in,v2(:,:,1)) 523 ELSE ; out=PTrop_chem(ih,it,itrp0,Pre_in,v2(:,:,1),o3t0); END IF 524 out=out/Pgnd_in(ih) 508 525 509 526 END FUNCTION get_SigTrop … … 514 531 !------------------------------------------------------------------------------- 515 532 ! 516 FUNCTION chem_tropopause(ih,it,it0,pint,o3,pcen,o3trop)533 FUNCTION PTrop_chem(ih,it,it0,pres,o3,o3trop) RESULT(out) 517 534 ! 518 535 !------------------------------------------------------------------------------- … … 529 546 !------------------------------------------------------------------------------- 530 547 ! Arguments: 531 REAL :: chem_tropopause!--- Pressure at tropopause548 REAL :: out !--- Pressure at tropopause 532 549 INTEGER, INTENT(IN) :: ih !--- Horizontal index 533 550 INTEGER, INTENT(OUT) :: it !--- Index of tropopause layer 534 551 INTEGER, INTENT(IN) :: it0 !--- Idx: higher than tropopause 535 REAL, INTENT(IN) :: p int(:) !--- Cells-interf Pr, increasing552 REAL, INTENT(IN) :: pres(:) !--- Pressure profile, increasing 536 553 REAL, INTENT(IN) :: o3(:,:) !--- Ozone field (pptV) 537 REAL, OPTIONAL, INTENT(IN) :: pcen(:) !--- Cells-center Pr, increasing538 554 REAL, OPTIONAL, INTENT(IN) :: o3trop !--- Ozone at tropopause 539 555 !------------------------------------------------------------------------------- 540 556 ! Local variables: 541 REAL :: o3t!--- Ozone concent. at tropopause542 REAL :: al!--- Interpolation coefficient543 REAL :: coef!--- Coeff of latitude modulation557 REAL :: o3t !--- Ozone concent. at tropopause 558 REAL :: al !--- Interpolation coefficient 559 REAL :: coef !--- Coeff of latitude modulation 544 560 REAL, PARAMETER :: co3(3)=[91.,28.,20.] !--- Coeff for o3 at tropopause 545 561 !------------------------------------------------------------------------------- … … 556 572 it=it0; DO WHILE(o3(ih,it+1)>=o3t); it=it+1; END DO 557 573 al=(o3(ih,it)-o3t)/(o3(ih,it)-o3(ih,it+1)) 558 IF(PRESENT(pcen)) THEN 559 chem_tropopause = pcen(it)**(1.-al) * pcen(it+1)**al 560 ELSE 561 chem_tropopause = SQRT( pint(it)**(1.-al) * pint(it+2)**al * pint(it+1) ) 562 END IF 563 it = locate(pint(:), chem_tropopause) !--- pint(it)<ptrop<pint(it+1) 564 565 END FUNCTION chem_tropopause 566 ! 567 !------------------------------------------------------------------------------- 568 569 570 !------------------------------------------------------------------------------- 571 ! 572 FUNCTION check_ozone(o3col, lon, lat, ilev0, layer, vmin, vmax) 574 IF(Ploc=='C') out = pres(it)**(1.-al) * pres(it+1)**al 575 IF(Ploc=='I') out = SQRT(pres(it)**(1.-al) * pres(it+2)**al *pres(it+1)) 576 it = locate(pres(:), out) !--- pres(it)<Ptrop<pres(it+1) 577 578 END FUNCTION PTrop_chem 579 ! 580 !------------------------------------------------------------------------------- 581 582 583 !------------------------------------------------------------------------------- 584 ! 585 FUNCTION check_ozone(o3col, lon, lat, ilev0, layer, vmin, vmax) RESULT(out) 573 586 ! 574 587 !------------------------------------------------------------------------------- … … 576 589 !------------------------------------------------------------------------------- 577 590 ! Arguments: 578 LOGICAL :: check_ozone!--- .T. => some wrong values591 LOGICAL :: out !--- .T. => some wrong values 579 592 REAL, INTENT(IN) :: o3col(:), lon, lat 580 593 INTEGER, INTENT(IN) :: ilev0 … … 592 605 lmin=.FALSE.; IF(PRESENT(vmin)) lmin=COUNT(o3col<vmin)/=0 593 606 lmax=.FALSE.; IF(PRESENT(vmax)) lmax=COUNT(o3col>vmax)/=0 594 check_ozone=lmin.OR.lmax; IF(.NOT.check_ozone) RETURN 595 IF(prt_level<1) RETURN 607 out=lmin.OR.lmax; IF(.NOT.out.OR.prt_level>100) RETURN 596 608 597 609 !--- SOME TOO LOW VALUES FOUND
Note: See TracChangeset
for help on using the changeset viewer.