Changeset 2428 for LMDZ5/trunk/libf/phylmd/cosp/radar_simulator.F90
- Timestamp:
- Jan 27, 2016, 10:42:32 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
LMDZ5/trunk/libf/phylmd/cosp/radar_simulator.F90
r1907 r2428 1 subroutine radar_simulator(freq,k2,do_ray,use_gas_abs,use_mie_table,mt, & 2 nhclass,hp,nprof,ngate,nsizes,D,hgt_matrix,hm_matrix,re_matrix,p_matrix,t_matrix, & 3 rh_matrix,Ze_non,Ze_ray,h_atten_to_vol,g_atten_to_vol,dBZe, & 1 subroutine radar_simulator( & 2 hp, & 3 nprof,ngate, & 4 undef, & 5 hgt_matrix,hm_matrix,re_matrix,Np_matrix, & 6 p_matrix,t_matrix,rh_matrix, & 7 Ze_non,Ze_ray,a_to_vol,g_to_vol,dBZe, & 4 8 g_to_vol_in,g_to_vol_out) 5 6 ! rh_matrix,Ze_non,Ze_ray,kr_matrix,g_atten_to_vol,dBZe)7 9 8 10 use m_mrgrnk … … 11 13 use optics_lib 12 14 use radar_simulator_types 15 use scale_LUTs_io 13 16 implicit none 14 17 15 18 ! Purpose: 19 ! 16 20 ! Simulates a vertical profile of radar reflectivity 17 ! Part of QuickBeam v1.04 by John Haynes & Roger Marchand 21 ! Originally Part of QuickBeam v1.04 by John Haynes & Roger Marchand. 22 ! but has been substantially modified since that time by 23 ! Laura Fowler and Roger Marchand (see modifications below). 18 24 ! 19 25 ! Inputs: 20 ! [freq] radar frequency (GHz), can be anything unless 21 ! use_mie_table=1, in which case one of 94,35,13.8,9.6,3 22 ! [k2] |K|^2, the dielectric constant, set to -1 to use the 23 ! frequency dependent default 24 ! [do_ray] 1=do Rayleigh calcs, 0=not 25 ! [use_gas_abs] 1=do gaseous abs calcs, 0=not, 26 ! 2=use same as first profile (undocumented) 27 ! [use_mie_table] 1=use Mie tables, 0=not 28 ! [mt] Mie look up table 29 ! [nhclass] number of hydrometeor types 30 ! [hp] structure that defines hydrometeor types 26 ! 27 ! [hp] structure that defines hydrometeor types and other radar properties 28 ! 31 29 ! [nprof] number of hydrometeor profiles 32 30 ! [ngate] number of vertical layers 33 ! [nsizes] number of discrete particles in [D] 34 ! [D] array of discrete particles (um) 35 ! 31 ! 32 ! [undef] missing data value 36 33 ! (The following 5 arrays must be in order from closest to the radar 37 34 ! to farthest...) 35 ! 38 36 ! [hgt_matrix] height of hydrometeors (km) 37 ! [p_matrix] pressure profile (hPa) 38 ! [t_matrix] temperature profile (K) 39 ! [rh_matrix] relative humidity profile (%) -- only needed if gaseous aborption calculated. 40 ! 39 41 ! [hm_matrix] table of hydrometeor mixing rations (g/kg) 40 ! [re_matrix] OPTIONAL table of hydrometeor effective radii (microns) 41 ! [p_matrix] pressure profile (hPa) 42 ! [t_matrix] temperature profile (C) 43 ! [rh_matrix] relative humidity profile (%) 42 ! [re_matrix] table of hydrometeor effective radii. 0 ==> use defaults. (units=microns) 43 ! [Np_matrix] table of hydrometeor number concentration. 0 ==> use defaults. (units = 1/kg) 44 44 ! 45 45 ! Outputs: 46 ! 46 47 ! [Ze_non] radar reflectivity without attenuation (dBZ) 47 48 ! [Ze_ray] Rayleigh reflectivity (dBZ) … … 59 60 ! Created: 60 61 ! 11/28/2005 John Haynes (haynes@atmos.colostate.edu) 62 ! 61 63 ! Modified: 62 ! 09/2006 placed into subroutine form , scaling factors(Roger Marchand,JMH)64 ! 09/2006 placed into subroutine form (Roger Marchand,JMH) 63 65 ! 08/2007 added equivalent volume spheres, Z and N scalling most distrubtion types (Roger Marchand) 64 66 ! 01/2008 'Do while' to determine if hydrometeor(s) present in volume 65 67 ! changed for vectorization purposes (A. Bodas-Salcedo) 66 68 ! 69 ! 07/2010 V3.0 ... Modified to load or save scale factors to disk as a Look-Up Table (LUT) 70 ! ... All hydrometeor and radar simulator properties now included in hp structure 71 ! ... hp structure should be initialized by call to radar_simulator_init prior 72 ! ... to calling this subroutine. 73 ! Also ... Support of Morrison 2-moment style microphyscis (Np_matrix) added 74 ! ... Changes implement by Roj Marchand following work by Laura Fowler 75 ! 76 ! 10/2011 Modified ngate loop to go in either direction depending on flag 77 ! hp%radar_at_layer_one. This affects the direction in which attenuation is summed. 78 ! 79 ! Also removed called to AVINT for gas and hydrometeor attenuation and replaced with simple 80 ! summation. (Roger Marchand) 81 ! 82 ! 67 83 ! ----- INPUTS ----- 68 type(mie), intent(in) :: mt 84 85 logical, parameter :: DO_LUT_TEST = .false. 86 logical, parameter :: DO_NP_TEST = .false. 87 69 88 type(class_param), intent(inout) :: hp 70 real*8, intent(in) :: freq,k2 71 integer, intent(in) :: do_ray,use_gas_abs,use_mie_table, & 72 nhclass,nprof,ngate,nsizes 73 real*8, dimension(nsizes), intent(in) :: D 74 real*8, dimension(nprof,ngate), intent(in) :: hgt_matrix, p_matrix, & 75 t_matrix,rh_matrix 76 real*8, dimension(nhclass,nprof,ngate), intent(in) :: hm_matrix 77 real*8, dimension(nhclass,nprof,ngate), intent(inout) :: re_matrix 78 89 90 integer, intent(in) :: nprof,ngate 91 92 real undef 93 real*8, dimension(nprof,ngate), intent(in) :: & 94 hgt_matrix, p_matrix,t_matrix,rh_matrix 95 96 real*8, dimension(hp%nhclass,nprof,ngate), intent(in) :: hm_matrix 97 real*8, dimension(hp%nhclass,nprof,ngate), intent(inout) :: re_matrix 98 real*8, dimension(hp%nhclass,nprof,ngate), intent(in) :: Np_matrix 99 79 100 ! ----- OUTPUTS ----- 80 101 real*8, dimension(nprof,ngate), intent(out) :: Ze_non,Ze_ray, & 81 g_atten_to_vol,dBZe,h_atten_to_vol102 g_to_vol,dBZe,a_to_vol 82 103 83 104 ! ----- OPTIONAL ----- 84 real*8, optional, dimension(n gate,nprof) :: &105 real*8, optional, dimension(nprof,ngate) :: & 85 106 g_to_vol_in,g_to_vol_out ! integrated atten due to gases, r>v (dB). This allows to output and then input 86 107 ! the same gaseous absorption in different calls. Optional to allow compatibility 87 108 ! with original version. A. Bodas April 2008. 88 89 109 ! real*8, dimension(nprof,ngate) :: kr_matrix 90 110 91 111 ! ----- INTERNAL ----- 112 113 real, parameter :: one_third = 1.0/3.0 114 real*8 :: t_kelvin 92 115 integer :: & 93 phase, & ! 0=liquid, 1=ice 94 ns ! number of discrete drop sizes 95 96 integer*4, dimension(ngate) :: & 97 hydro ! 1=hydrometeor in vol, 0=none 116 phase, & ! 0=liquid, 1=ice 117 ns ! number of discrete drop sizes 118 119 logical :: hydro ! true=hydrometeor in vol, false=none 98 120 real*8 :: & 99 rho_a, & 100 gases 121 rho_a, & ! air density (kg m^-3) 122 gases ! function: 2-way gas atten (dB/km) 101 123 102 124 real*8, dimension(:), allocatable :: & 103 Di, Deq, & 104 Ni, Ntemp, &! discrete concentrations (cm^-3 um^-1)105 rhoi 106 107 real*8, dimension(n gate) :: &108 z_vol, & 125 Di, Deq, & ! discrete drop sizes (um) 126 Ni, & ! discrete concentrations (cm^-3 um^-1) 127 rhoi ! discrete densities (kg m^-3) 128 129 real*8, dimension(nprof, ngate) :: & 130 z_vol, & ! effective reflectivity factor (mm^6/m^3) 109 131 z_ray, & ! reflectivity factor, Rayleigh only (mm^6/m^3) 110 kr_vol, & ! attenuation coefficient hydro (dB/km) 111 g_vol, & ! attenuation coefficient gases (dB/km) 112 a_to_vol, & ! integrated atten due to hydometeors, r>v (dB) 113 g_to_vol ! integrated atten due to gases, r>v (dB) 114 115 132 kr_vol, & ! attenuation coefficient hydro (dB/km) 133 g_vol ! attenuation coefficient gases (dB/km) 134 135 116 136 integer,parameter :: KR8 = selected_real_kind(15,300) 117 137 real*8, parameter :: xx = -1.0_KR8 118 138 real*8, dimension(:), allocatable :: xxa 119 real*8 :: kr, ze, zr, pi, scale_factor, tc, Re, ld, tmp1, ze2, kr2,apm,bpm 139 real*8 :: kr, ze, zr, pi, scale_factor, tc, Re, ld, tmp1, ze2, kr2, apm, bpm 140 real*8 :: half_a_atten_current,half_a_atten_above 141 real*8 :: half_g_atten_current,half_g_atten_above 120 142 integer*4 :: tp, i, j, k, pr, itt, iff 121 143 122 real*8 bin_length,step,base,step_list(25),base_list(25)144 real*8 step,base, Np 123 145 integer*4 iRe_type,n,max_bin 124 146 147 integer start_gate,end_gate,d_gate 148 125 149 logical :: g_to_vol_in_present, g_to_vol_out_present 126 150 127 151 ! Logicals to avoid calling present within the loops 128 152 g_to_vol_in_present = present(g_to_vol_in) 129 153 g_to_vol_out_present = present(g_to_vol_out) 130 131 ! set up Re bins for z_scalling 132 bin_length=50; 133 max_bin=25 134 135 step_list(1)=1 136 base_list(1)=75 137 do j=2,max_bin 138 step_list(j)=3*(j-1); 139 if(step_list(j)>bin_length) then 140 step_list(j)=bin_length; 141 endif 142 base_list(j)=base_list(j-1)+floor(bin_length/step_list(j-1)); 143 enddo 144 154 155 ! 156 ! load scaling matricies from disk -- but only the first time this subroutine is called 157 ! 158 if(hp%load_scale_LUTs) then 159 call load_scale_LUTs(hp) 160 hp%load_scale_LUTs=.false. 161 hp%Z_scale_added_flag = .false. ! will be set true if scaling Look Up Tables are modified during run 162 endif 145 163 146 164 pi = acos(-1.0) 147 if (use_mie_table == 1) iff = infind(mt%freq,freq,sort=1) 148 149 165 166 ! ----- Initialisation ----- 167 g_to_vol = 0.0 168 a_to_vol = 0.0 169 z_vol = 0.0 170 z_ray = 0.0 171 kr_vol = 0.0 172 173 ! // loop over each range gate (ngate) ... starting with layer closest to the radar ! 174 if(hp%radar_at_layer_one) then 175 start_gate=1 176 end_gate=ngate 177 d_gate=1 178 else 179 start_gate=ngate 180 end_gate=1 181 d_gate=-1 182 endif 183 do k=start_gate,end_gate,d_gate 150 184 ! // loop over each profile (nprof) 151 do pr=1,nprof 152 153 ! ----- calculations for each volume ----- 154 z_vol(:) = 0 155 z_ray(:) = 0 156 kr_vol(:) = 0 157 hydro(:) = 0 158 159 ! // loop over eacho range gate (ngate) 160 do k=1,ngate 161 185 do pr=1,nprof 186 t_kelvin = t_matrix(pr,k) 162 187 ! :: determine if hydrometeor(s) present in volume 163 hydro (k) = 0164 do j=1, nhclass ! Do while changed for vectorization purposes (A. B-S)188 hydro = .false. 189 do j=1,hp%nhclass 165 190 if ((hm_matrix(j,pr,k) > 1E-12) .and. (hp%dtype(j) > 0)) then 166 hydro (k) = 1191 hydro = .true. 167 192 exit 168 193 endif 169 194 enddo 170 195 171 if (hydro(k) == 1) then 172 ! :: if there is hydrometeor in the volume 173 174 rho_a = (p_matrix(pr,k)*100.)/(287*(t_matrix(pr,k)+273.15)) 175 196 ! :: if there is hydrometeor in the volume 197 if (hydro) then 198 199 rho_a = (p_matrix(pr,k)*100.)/(287.0*(t_kelvin)) 176 200 ! :: loop over hydrometeor type 177 do tp=1,nhclass 178 201 do tp=1,hp%nhclass 179 202 if (hm_matrix(tp,pr,k) <= 1E-12) cycle 180 181 phase = hp%phase(tp) 182 if(phase==0) then 183 itt = infind(mt_ttl,t_matrix(pr,k)) 184 else 185 itt = infind(mt_tti,t_matrix(pr,k)) 203 phase = hp%phase(tp) 204 if (phase==0) then 205 itt = infind(hp%mt_ttl,t_kelvin) 206 else 207 itt = infind(hp%mt_tti,t_kelvin) 208 endif 209 if (re_matrix(tp,pr,k).eq.0) then 210 call calc_Re(hm_matrix(tp,pr,k),Np_matrix(tp,pr,k),rho_a, & 211 hp%dtype(tp),hp%dmin(tp),hp%dmax(tp),hp%apm(tp),hp%bpm(tp), & 212 hp%rho(tp),hp%p1(tp),hp%p2(tp),hp%p3(tp),Re) 213 re_matrix(tp,pr,k)=Re 214 else 215 if (Np_matrix(tp,pr,k)>0) then 216 print *, 'Warning: Re and Np set for the same ', & 217 'volume & hydrometeor type. Np is being ignored.' 218 endif 219 Re = re_matrix(tp,pr,k) 220 endif 221 222 iRe_type=1 223 if(Re.gt.0) then 224 ! determine index in to scale LUT 225 ! 226 ! distance between Re points (defined by "base" and "step") for 227 ! each interval of size Re_BIN_LENGTH 228 ! Integer asignment, avoids calling floor intrinsic 229 n=Re/Re_BIN_LENGTH 230 if (n>=Re_MAX_BIN) n=Re_MAX_BIN-1 231 step=hp%step_list(n+1) 232 base=hp%base_list(n+1) 233 iRe_type=Re/step 234 if (iRe_type.lt.1) iRe_type=1 235 236 Re=step*(iRe_type+0.5) ! set value of Re to closest value allowed in LUT. 237 iRe_type=iRe_type+base-int(n*Re_BIN_LENGTH/step) 238 239 ! make sure iRe_type is within bounds 240 if (iRe_type.ge.nRe_types) then 241 ! write(*,*) 'Warning: size of Re exceed value permitted ', & 242 ! 'in Look-Up Table (LUT). Will calculate. ' 243 ! no scaling allowed 244 iRe_type=nRe_types 245 hp%Z_scale_flag(tp,itt,iRe_type)=.false. 246 else 247 ! set value in re_matrix to closest values in LUT 248 if (.not. DO_LUT_TEST) re_matrix(tp,pr,k)=Re 249 endif 250 endif 251 ! use Ze_scaled, Zr_scaled, and kr_scaled ... if know them 252 ! if not we will calculate Ze, Zr, and Kr from the distribution parameters 253 if( (.not. hp%Z_scale_flag(tp,itt,iRe_type)) .or. DO_LUT_TEST) then 254 ! :: create a distribution of hydrometeors within volume 255 select case(hp%dtype(tp)) 256 case(4) 257 ns = 1 258 allocate(Di(ns),Ni(ns),rhoi(ns),xxa(ns),Deq(ns)) 259 Di = hp%p1(tp) 260 Ni = 0. 261 case default 262 ns = nd ! constant defined in radar_simulator_types.f90 263 allocate(Di(ns),Ni(ns),rhoi(ns),xxa(ns),Deq(ns)) 264 Di = hp%D 265 Ni = 0. 266 end select 267 call dsd(hm_matrix(tp,pr,k),re_matrix(tp,pr,k),Np_matrix(tp,pr,k), & 268 Di,Ni,ns,hp%dtype(tp),rho_a,t_kelvin, & 269 hp%dmin(tp),hp%dmax(tp),hp%apm(tp),hp%bpm(tp), & 270 hp%rho(tp),hp%p1(tp),hp%p2(tp),hp%p3(tp)) 271 272 ! calculate particle density 273 if (phase == 1) then 274 if (hp%rho(tp) < 0) then 275 ! Use equivalent volume spheres. 276 hp%rho_eff(tp,1:ns,iRe_type) = 917 ! solid ice == equivalent volume approach 277 Deq = ( ( 6/pi*hp%apm(tp)/917 ) ** (1.0/3.0) ) * ( (Di*1E-6) ** (hp%bpm(tp)/3.0) ) * 1E6 278 ! alternative is to comment out above two lines and use the following block 279 ! MG Mie approach - adjust density of sphere with D = D_characteristic to match particle density 280 ! 281 ! hp%rho_eff(tp,1:ns,iRe_type) = (6/pi)*hp%apm(tp)*(Di*1E-6)**(hp%bpm(tp)-3) !MG Mie approach 282 283 ! as the particle size gets small it is possible that the mass to size relationship of 284 ! (given by power law in hclass.data) can produce impossible results 285 ! where the mass is larger than a solid sphere of ice. 286 ! This loop ensures that no ice particle can have more mass/density larger than an ice sphere. 287 ! do i=1,ns 288 ! if(hp%rho_eff(tp,i,iRe_type) > 917 ) then 289 ! hp%rho_eff(tp,i,iRe_type) = 917 290 ! endif 291 ! enddo 292 else 293 ! Equivalent volume sphere (solid ice rho_ice=917 kg/m^3). 294 hp%rho_eff(tp,1:ns,iRe_type) = 917 295 Deq=Di * ((hp%rho(tp)/917)**(1.0/3.0)) 296 ! alternative ... coment out above two lines and use the following for MG-Mie 297 ! hp%rho_eff(tp,1:ns,iRe_type) = hp%rho(tp) !MG Mie approach 298 endif 299 else 300 ! I assume here that water phase droplets are spheres. 301 ! hp%rho should be ~ 1000 or hp%apm=524 .and. hp%bpm=3 302 Deq = Di 303 endif 304 305 ! calculate effective reflectivity factor of volume 306 xxa = -9.9 307 rhoi = hp%rho_eff(tp,1:ns,iRe_type) 308 call zeff(hp%freq,Deq,Ni,ns,hp%k2,t_kelvin,phase,hp%do_ray, & 309 ze,zr,kr,xxa,xxa,rhoi) 310 311 ! test code ... compare Np value input to routine with sum of DSD 312 ! NOTE: if .not. DO_LUT_TEST, then you are checking the LUT approximation 313 ! not just the DSD representation given by Ni 314 if(Np_matrix(tp,pr,k)>0 .and. DO_NP_TEST ) then 315 Np = path_integral(Ni,Di,1,ns-1)/rho_a*1E6 316 ! Note: Representation is not great or small Re < 2 317 if( (Np_matrix(tp,pr,k)-Np)/Np_matrix(tp,pr,k)>0.1 ) then 318 write(*,*) 'Error: Np input does not match sum(N)' 319 write(*,*) tp,pr,k,Re,Ni(1),Ni(ns),10*log10(ze) 320 write(*,*) Np_matrix(tp,pr,k),Np,(Np_matrix(tp,pr,k)-Np)/Np_matrix(tp,pr,k) 321 write(*,*) 322 endif 323 endif 324 325 deallocate(Di,Ni,rhoi,xxa,Deq) 326 327 ! LUT test code 328 ! This segment of code compares full calculation to scaling result 329 if ( hp%Z_scale_flag(tp,itt,iRe_type) .and. DO_LUT_TEST ) then 330 scale_factor=rho_a*hm_matrix(tp,pr,k) 331 ! if more than 2 dBZe difference print error message/parameters. 332 if ( abs(10*log10(ze) - 10*log10(hp%Ze_scaled(tp,itt,iRe_type) * & 333 scale_factor)) > 2 ) then 334 write(*,*) 'Roj Error: ',tp,itt,iRe_type,hp%Z_scale_flag(tp,itt,iRe_type),n,step,base 335 write(*,*) 10*log10(ze),10*log10(hp%Ze_scaled(tp,itt,iRe_type) * scale_factor) 336 write(*,*) hp%Ze_scaled(tp,itt,iRe_type),scale_factor 337 write(*,*) re_matrix(tp,pr,k),Re 338 write(*,*) 339 endif 340 endif 341 342 else ! can use z scaling 343 scale_factor=rho_a*hm_matrix(tp,pr,k) 344 zr = hp%Zr_scaled(tp,itt,iRe_type) * scale_factor 345 ze = hp%Ze_scaled(tp,itt,iRe_type) * scale_factor 346 kr = hp%kr_scaled(tp,itt,iRe_type) * scale_factor 347 endif ! end z_scaling 348 349 kr_vol(pr,k) = kr_vol(pr,k) + kr 350 z_vol(pr,k) = z_vol(pr,k) + ze 351 z_ray(pr,k) = z_ray(pr,k) + zr 352 353 ! construct Ze_scaled, Zr_scaled, and kr_scaled ... if we can 354 if ( .not. hp%Z_scale_flag(tp,itt,iRe_type) ) then 355 if (iRe_type>1) then 356 scale_factor=rho_a*hm_matrix(tp,pr,k) 357 hp%Ze_scaled(tp,itt,iRe_type) = ze/ scale_factor 358 hp%Zr_scaled(tp,itt,iRe_type) = zr/ scale_factor 359 hp%kr_scaled(tp,itt,iRe_type) = kr/ scale_factor 360 hp%Z_scale_flag(tp,itt,iRe_type) = .true. 361 hp%Z_scale_added_flag(tp,itt,iRe_type)=.true. 362 endif 363 endif 364 365 enddo ! end loop of tp (hydrometeor type) 366 367 else 368 ! :: volume is hydrometeor-free 369 kr_vol(pr,k) = 0 370 z_vol(pr,k) = undef 371 z_ray(pr,k) = undef 186 372 endif 187 373 188 ! calculate Re if we have an exponential distribution with fixed No ... precipitation type particle 189 if( hp%dtype(tp)==2 .and. abs(hp%p2(tp)+1) < 1E-8) then 190 191 apm=hp%apm(tp) 192 bpm=hp%bpm(tp) 193 194 if ((hp%rho(tp) > 0) .and. (apm < 0)) then 195 apm = (pi/6)*hp%rho(tp) 196 bpm = 3. 197 endif 198 199 tmp1 = 1./(1.+bpm) 200 ld = ((apm*gamma(1.+bpm)*hp%p1(tp))/(rho_a*hm_matrix(tp,pr,k)*1E-3))**tmp1 201 202 Re = 1.5E6/ld 203 204 re_matrix(tp,pr,k) = Re; 205 206 endif 207 208 if(re_matrix(tp,pr,k).eq.0) then 209 210 iRe_type=1 211 Re=0 212 else 213 iRe_type=1 214 Re=re_matrix(tp,pr,k) 215 216 n=floor(Re/bin_length) 217 if(n==0) then 218 if(Re<25) then 219 step=0.5 220 base=0 221 else 222 step=1 223 base=25 224 endif 225 else 226 if(n>max_bin) then 227 n=max_bin 228 endif 229 230 step=step_list(n) 231 base=base_list(n) 232 endif 233 234 iRe_type=floor(Re/step) 235 236 if(iRe_type.lt.1) then 237 iRe_type=1 238 endif 239 240 Re=step*(iRe_type+0.5) 241 iRe_type=iRe_type+base-floor(n*bin_length/step) 242 243 ! make sure iRe_type is within bounds 244 if(iRe_type.ge.nRe_types) then 245 246 ! print *, tp, re_matrix(tp,pr,k), Re, iRe_type 247 248 ! no scaling allowed 249 Re=re_matrix(tp,pr,k) 250 251 iRe_type=nRe_types 252 hp%z_flag(tp,itt,iRe_type)=.false. 253 hp%scaled(tp,iRe_type)=.false. 254 endif 255 endif 256 257 ! use Ze_scaled, Zr_scaled, and kr_scaled ... if know them 258 ! if not we will calculate Ze, Zr, and Kr from the distribution parameters 259 if( .not. hp%z_flag(tp,itt,iRe_type) ) then 260 261 ! :: create a distribution of hydrometeors within volume 262 select case(hp%dtype(tp)) 263 case(4) 264 ns = 1 265 allocate(Di(ns),Ni(ns),rhoi(ns),xxa(ns),Deq(ns)) 266 if (use_mie_table == 1) allocate(mt_qext(ns),mt_qbsca(ns),Ntemp(ns)) 267 Di = hp%p1(tp) 268 Ni = 0. 269 case default 270 ns = nsizes 271 allocate(Di(ns),Ni(ns),rhoi(ns),xxa(ns),Deq(ns)) 272 if (use_mie_table == 1) allocate(mt_qext(ns),mt_qbsca(ns),Ntemp(ns)) 273 Di = D 274 Ni = 0. 275 end select 276 277 ! :: create a DSD (using scaling factor if applicable) 278 ! hp%scaled(tp,iRe_type)=.false. ! turn off N scaling 279 280 call dsd(hm_matrix(tp,pr,k),Re,Di,Ni,ns,hp%dtype(tp),rho_a, & 281 t_matrix(pr,k),hp%dmin(tp),hp%dmax(tp),hp%apm(tp),hp%bpm(tp), & 282 hp%rho(tp),hp%p1(tp),hp%p2(tp),hp%p3(tp),hp%fc(tp,1:ns,iRe_type), & 283 hp%scaled(tp,iRe_type)) 284 285 ! :: calculate particle density 286 ! if ((hp%rho_eff(tp,1,iRe_type) < 0) .and. (phase == 1)) then 287 if (phase == 1) then 288 if (hp%rho(tp) < 0) then 289 290 ! MG Mie approach - adjust density of sphere with D = D_characteristic to match particle density 291 ! hp%rho_eff(tp,1:ns,iRe_type) = (6/pi)*hp%apm(tp)*(Di*1E-6)**(hp%bpm(tp)-3) !MG Mie approach 292 293 ! as the particle size gets small it is possible that the mass to size relationship of 294 ! (given by power law in hclass.data) can produce impossible results 295 ! where the mass is larger than a solid sphere of ice. 296 ! This loop ensures that no ice particle can have more mass/density larger than an ice sphere. 297 ! do i=1,ns 298 ! if(hp%rho_eff(tp,i,iRe_type) > 917 ) then 299 ! hp%rho_eff(tp,i,iRe_type) = 917 300 !endif 301 !enddo 302 303 ! alternative is to use equivalent volume spheres. 304 hp%rho_eff(tp,1:ns,iRe_type) = 917 ! solid ice == equivalent volume approach 305 Deq = ( ( 6/pi*hp%apm(tp)/917 ) ** (1.0/3.0) ) * & 306 ( (Di*1E-6) ** (hp%bpm(tp)/3.0) ) * 1E6 ! Di now really Deq in microns. 307 374 ! :: attenuation due to hydrometeors between radar and volume 375 ! 376 ! NOTE old scheme integrates attenuation only for the layers ABOVE 377 ! the current layer ... i.e. 1 to k-1 rather than 1 to k ... 378 ! which may be a problem. ROJ 379 ! in the new scheme I assign half the attenuation to the current layer 380 if(d_gate==1) then 381 ! dheight calcuations assumes hgt_matrix points are the cell mid-points. 382 if (k>2) then 383 ! add to previous value to half of above layer + half of current layer 384 a_to_vol(pr,k)= a_to_vol(pr,k-1) + & 385 (kr_vol(pr,k-1)+kr_vol(pr,k))*(hgt_matrix(pr,k-1)-hgt_matrix(pr,k)) 386 else 387 a_to_vol(pr,k)= kr_vol(pr,k)*(hgt_matrix(pr,k)-hgt_matrix(pr,k+1)) 388 endif 389 else ! d_gate==-1 390 if(k<ngate) then 391 ! add to previous value half of above layer + half of current layer 392 a_to_vol(pr,k) = a_to_vol(pr,k+1) + & 393 (kr_vol(pr,k+1)+kr_vol(pr,k))*(hgt_matrix(pr,k+1)-hgt_matrix(pr,k)) 394 else 395 a_to_vol(pr,k)= kr_vol(pr,k)*(hgt_matrix(pr,k)-hgt_matrix(pr,k-1)) 396 endif 397 endif 398 399 ! :: attenuation due to gaseous absorption between radar and volume 400 if (g_to_vol_in_present) then 401 g_to_vol(pr,k) = g_to_vol_in(pr,k) 402 else 403 if ( (hp%use_gas_abs == 1) .or. ((hp%use_gas_abs == 2) .and. (pr == 1)) ) then 404 g_vol(pr,k) = gases(p_matrix(pr,k),t_kelvin,rh_matrix(pr,k),hp%freq) 405 if (d_gate==1) then 406 if (k>1) then 407 ! add to previous value to half of above layer + half of current layer 408 g_to_vol(pr,k) = g_to_vol(pr,k-1) + & 409 0.5*(g_vol(pr,k-1)+g_vol(pr,k))*(hgt_matrix(pr,k-1)-hgt_matrix(pr,k)) 308 410 else 309 310 ! hp%rho_eff(tp,1:ns,iRe_type) = hp%rho(tp) !MG Mie approach 311 312 ! Equivalent volume sphere (solid ice rho_ice=917 kg/m^3). 313 hp%rho_eff(tp,1:ns,iRe_type) = 917 314 Deq=Di * ((hp%rho(tp)/917)**(1.0/3.0)) 315 316 endif 317 318 ! if using equivalent volume spheres 319 if (use_mie_table == 1) then 320 321 Ntemp=Ni 322 323 ! Find N(Di) from N(Deq) which we know 324 do i=1,ns 325 j=infind(Deq,Di(i)) 326 Ni(i)=Ntemp(j) 327 enddo 328 else 329 ! just use Deq and D variable input to mie code 330 Di=Deq; 331 endif 332 333 endif 334 rhoi = hp%rho_eff(tp,1:ns,iRe_type) 335 336 ! :: calculate effective reflectivity factor of volume 337 if (use_mie_table == 1) then 338 339 if ((hp%dtype(tp) == 4) .and. (hp%idd(tp) < 0)) then 340 hp%idd(tp) = infind(mt%D,Di(1)) 341 endif 342 343 if (phase == 0) then 344 345 ! itt = infind(mt_ttl,t_matrix(pr,k)) 346 select case(hp%dtype(tp)) 347 case(4) 348 mt_qext(1) = mt%qext(hp%idd(tp),itt,1,iff) 349 mt_qbsca(1) = mt%qbsca(hp%idd(tp),itt,1,iff) 350 case default 351 mt_qext = mt%qext(:,itt,1,iff) 352 mt_qbsca = mt%qbsca(:,itt,1,iff) 353 end select 354 355 call zeff(freq,Di,Ni,ns,k2,mt_ttl(itt),0,do_ray, & 356 ze,zr,kr,mt_qext,mt_qbsca,xx) 357 358 else 359 360 ! itt = infind(mt_tti,t_matrix(pr,k)) 361 select case(hp%dtype(tp)) 362 case(4) 363 if (hp%ifc(tp,1,iRe_type) < 0) then 364 hp%ifc(tp,1,iRe_type) = infind(mt%f,rhoi(1)/917.) 365 endif 366 mt_qext(1) = & 367 mt%qext(hp%idd(tp),itt+cnt_liq,hp%ifc(tp,1,iRe_type),iff) 368 mt_qbsca(1) = & 369 mt%qbsca(hp%idd(tp),itt+cnt_liq,hp%ifc(tp,1,iRe_type),iff) 370 case default 371 do i=1,ns 372 if (hp%ifc(tp,i,iRe_type) < 0) then 373 hp%ifc(tp,i,iRe_type) = infind(mt%f,rhoi(i)/917.) 374 endif 375 mt_qext(i) = mt%qext(i,itt+cnt_liq,hp%ifc(tp,i,iRe_type),iff) 376 mt_qbsca(i) = mt%qbsca(i,itt+cnt_liq,hp%ifc(tp,i,iRe_type),iff) 377 enddo 378 end select 379 380 call zeff(freq,Di,Ni,ns,k2,mt_tti(itt),1,do_ray, & 381 ze,zr,kr,mt_qext,mt_qbsca,xx) 382 383 endif 384 385 else 386 387 xxa = -9.9 388 call zeff(freq,Di,Ni,ns,k2,t_matrix(pr,k),phase,do_ray, & 389 ze,zr,kr,xxa,xxa,rhoi) 390 391 392 endif ! end of use mie table 393 394 ! xxa = -9.9 395 !call zeff(freq,Di,Ni,ns,k2,t_matrix(pr,k),phase,do_ray, & 396 ! ze2,zr,kr2,xxa,xxa,rhoi) 397 398 ! if(abs(ze2-ze)/ze2 > 0.1) then 399 ! if(abs(kr2-kr)/kr2 > 0.1) then 400 401 ! write(*,*) pr,k,tp,ze2,ze2-ze,abs(ze2-ze)/ze2,itt+cnt_liq,iff 402 ! write(*,*) pr,k,tp,ze2,kr2,kr2-kr,abs(kr2-kr)/kr2 403 ! stop 404 405 !endif 406 407 deallocate(Di,Ni,rhoi,xxa,Deq) 408 if (use_mie_table == 1) deallocate(mt_qext,mt_qbsca,Ntemp) 409 410 else ! can use z scaling 411 412 if( hp%dtype(tp)==2 .and. abs(hp%p2(tp)+1) < 1E-8 ) then 413 414 ze = hp%Ze_scaled(tp,itt,iRe_type) 415 zr = hp%Zr_scaled(tp,itt,iRe_type) 416 kr = hp%kr_scaled(tp,itt,iRe_type) 417 418 else 419 scale_factor=rho_a*hm_matrix(tp,pr,k) 420 421 zr = hp%Zr_scaled(tp,itt,iRe_type) * scale_factor 422 ze = hp%Ze_scaled(tp,itt,iRe_type) * scale_factor 423 kr = hp%kr_scaled(tp,itt,iRe_type) * scale_factor 424 endif 425 426 endif ! end z_scaling 427 428 ! kr=0 429 430 kr_vol(k) = kr_vol(k) + kr 431 z_vol(k) = z_vol(k) + ze 432 z_ray(k) = z_ray(k) + zr 433 434 ! construct Ze_scaled, Zr_scaled, and kr_scaled ... if we can 435 if( .not. hp%z_flag(tp,itt,iRe_type) .and. 1.eq.1 ) then 436 437 if( ( (hp%dtype(tp)==1 .or. hp%dtype(tp)==5 .or. hp%dtype(tp)==2) .and. abs(hp%p1(tp)+1) < 1E-8 ) .or. & 438 ( hp%dtype(tp)==3 .or. hp%dtype(tp)==4 ) & 439 ) then 440 441 scale_factor=rho_a*hm_matrix(tp,pr,k) 442 443 hp%Ze_scaled(tp,itt,iRe_type) = ze/ scale_factor 444 hp%Zr_scaled(tp,itt,iRe_type) = zr/ scale_factor 445 hp%kr_scaled(tp,itt,iRe_type) = kr/ scale_factor 446 447 hp%z_flag(tp,itt,iRe_type)=.True. 448 449 elseif( hp%dtype(tp)==2 .and. abs(hp%p2(tp)+1) < 1E-8 ) then 450 451 hp%Ze_scaled(tp,itt,iRe_type) = ze 452 hp%Zr_scaled(tp,itt,iRe_type) = zr 453 hp%kr_scaled(tp,itt,iRe_type) = kr 454 455 hp%z_flag(tp,itt,iRe_type)=.True. 456 endif 457 458 endif 459 460 enddo ! end loop of tp (hydrometeor type) 461 411 g_to_vol(pr,k)= 0.5*g_vol(pr,k)*(hgt_matrix(pr,k)-hgt_matrix(pr,k+1)) 412 endif 413 else ! d_gate==-1 414 if (k<ngate) then 415 ! add to previous value to half of above layer + half of current layer 416 g_to_vol(pr,k) = g_to_vol(pr,k+1) + & 417 0.5*(g_vol(pr,k+1)+g_vol(pr,k))*(hgt_matrix(pr,k+1)-hgt_matrix(pr,k)) 418 else 419 g_to_vol(pr,k)= 0.5*g_vol(pr,k)*(hgt_matrix(pr,k)-hgt_matrix(pr,k-1)) 420 endif 421 endif 422 elseif(hp%use_gas_abs == 2) then 423 ! using value calculated for the first column 424 g_to_vol(pr,k) = g_to_vol(1,k) 425 elseif (hp%use_gas_abs == 0) then 426 g_to_vol(pr,k) = 0 427 endif 428 endif 429 430 ! Compute Rayleigh reflectivity, and full, attenuated reflectivity 431 if ((hp%do_ray == 1) .and. (z_ray(pr,k) > 0)) then 432 Ze_ray(pr,k) = 10*log10(z_ray(pr,k)) 462 433 else 463 ! :: volume is hydrometeor-free 464 465 kr_vol(k) = 0 466 z_vol(k) = -999 467 z_ray(k) = -999 468 434 Ze_ray(pr,k) = undef 469 435 endif 470 471 ! :: attenuation due to hydrometeors between radar and volume 472 a_to_vol(k) = 2*path_integral(kr_vol,hgt_matrix(pr,:),1,k-1) 473 474 ! :: attenuation due to gaseous absorption between radar and volume 475 if (g_to_vol_in_present) then 476 g_to_vol(k) = g_to_vol_in(k,pr) 436 if (z_vol(pr,k) > 0) then 437 Ze_non(pr,k) = 10*log10(z_vol(pr,k)) 438 dBZe(pr,k) = Ze_non(pr,k)-a_to_vol(pr,k)-g_to_vol(pr,k) 477 439 else 478 if ( (use_gas_abs == 1) .or. ((use_gas_abs == 2) .and. (pr == 1)) ) then 479 g_vol(k) = gases(p_matrix(pr,k),t_matrix(pr,k)+273.15, & 480 rh_matrix(pr,k),freq) 481 g_to_vol(k) = path_integral(g_vol,hgt_matrix(pr,:),1,k-1) 482 elseif (use_gas_abs == 0) then 483 g_to_vol(k) = 0 484 endif 440 dBZe(pr,k) = undef 441 Ze_non(pr,k) = undef 485 442 endif 486 487 ! kr_matrix(pr,:)=kr_vol 488 489 ! :: store results in matrix for return to calling program 490 h_atten_to_vol(pr,k)=a_to_vol(k) 491 g_atten_to_vol(pr,k)=g_to_vol(k) 492 if ((do_ray == 1) .and. (z_ray(k) > 0)) then 493 Ze_ray(pr,k) = 10*log10(z_ray(k)) 494 else 495 Ze_ray(pr,k) = -999 496 endif 497 if (z_vol(k) > 0) then 498 dBZe(pr,k) = 10*log10(z_vol(k))-a_to_vol(k)-g_to_vol(k) 499 Ze_non(pr,k) = 10*log10(z_vol(k)) 500 else 501 dBZe(pr,k) = -999 502 Ze_non(pr,k) = -999 503 endif 504 505 enddo ! end loop of k (range gate) 506 ! Output array with gaseous absorption 507 if (g_to_vol_out_present) g_to_vol_out(:,pr) = g_to_vol 508 enddo ! end loop over pr (profile) 443 444 enddo ! end loop over pr (profile) 445 446 enddo ! end loop of k (range gate) 447 448 ! Output array with gaseous absorption 449 if (g_to_vol_out_present) g_to_vol_out = g_to_vol 450 451 ! save any updates made 452 if (hp%update_scale_LUTs) call save_scale_LUTs(hp) 509 453 510 454 end subroutine radar_simulator 511
Note: See TracChangeset
for help on using the changeset viewer.