SUEWS API Site
Documentation of SUEWS source code
suews_phys_spartacus.f95
Go to the documentation of this file.
2 !==============================================================================
3 !NET ALL WAVE RADIATION PARAMETERIZATION ROUTINES
4 !B. OFFERLE
5 !DEPT OF GEOGRAPHY
6 !INDIANA UNIVERSITY
7 !bofferle@indiana.edu
8 !
9 !MODIFIED: 19 DEC 2002
10 !CURRENTLY THE SMITH GRID IS ONLY VALID FOR THE N. HEMISPHERE
11 !
12 !Thomas Loridan, May 2008
13 !4.1: MODIFICATION FOR CLOUD FRACTION PARAMETERIZATION AT NIGHT USING THE RATE OF COOLING.
14 ! EOSHIFT INTRINSIC FUNCTION WAS ALSO REMOVED BECAUSE IT IS COMPILER DEPENDENT.
15 !
16 !6.0 T. Loridan - June 2009
17 ! Different longwave down options (ldown_option)
18 ! 1 - LDOWN Observed (add data as last column in met file)
19 ! 2 - LDOWN modelled from observed FCLD (add data as last column in met file)
20 ! 3 - LDOWN modelled from FCLD(RH,TA)
21 ! 4 - LDOWN modelled from FCLD(Kdown); i.e. day FCLD only
22 ! cloud fraction is kept constant throught the night (Offerle et al. 2003, JAM)
23 ! 5 - Option 3 at night and 4 during the day (might cause discontinuities in LDOWN)
24
25 !SUEWS L. Jarvi - Oct 2010
26 !Currently LDOWN options 4 and 5 commented out in order to reduce input files.
27 !Last modified:
28 ! TS 06 Aug 2017 - interface modified to receive explict input and output arguments
29 ! LJ 27 Jan 2016 - Removal of tabs, cleaning of the code
30 ! FL July 2014 - Variables are moved to modules in NARP subroutine. Snow related should also in future.
31 ! FL Nov 2013 - A new sun postion algorithm added
32 ! LJ May 2013 - Main program NARP changed to take subsurfaces and snow into account here and not
33 ! in the main program
34 ! LJ Oct 2012 - Zenith angle change in the calculation of albedo added
35 ! sg feb 2012 - Allocatable array module added
36
37 !==============================================================================================
38 USE allocatearray, ONLY: nsurf, nvegsurf, nspec, nsw, nlw, ncol, &
40 USE physconstants, ONLY: sbconst
41
42 IMPLICIT NONE
43
44CONTAINS
46 USE data_in, ONLY: fileinputpath
48 IMPLICIT NONE
49 ! INTEGER :: n_vegetation_region_urban, &
50 ! n_stream_sw_urban, n_stream_lw_urban
51 ! REAL(KIND(1D0)) :: sw_dn_direct_frac, air_ext_sw, air_ssa_sw, &
52 ! veg_ssa_sw, air_ext_lw, air_ssa_lw, veg_ssa_lw, &
53 ! veg_fsd_const, veg_contact_fraction_const, &
54 ! ground_albedo_dir_mult_fact
55 ! LOGICAL :: use_sw_direct_albedo
56 namelist /spartacus_settings/ use_sw_direct_albedo, n_vegetation_region_urban, &
58 /spartacus_constant_parameters/ sw_dn_direct_frac, air_ext_sw, air_ssa_sw, veg_ssa_sw, air_ext_lw, &
60
61 ! Bring in SUEWS-SPARTACUS.nml settings and parameters
62 OPEN (511, file=trim(fileinputpath)//'SUEWS_SPARTACUS.nml', status='old')
63 READ (511, nml=spartacus_settings)
64 READ (511, nml=spartacus_constant_parameters)
65 CLOSE (511)
66
67 END SUBROUTINE spartacus_initialise
68
69 SUBROUTINE spartacus( &
70 DiagQN, & !input:
71 sfr_surf, zenith_deg, nlayer, & !input:
72 tsfc_surf, tsfc_roof, tsfc_wall, &
73 kdown, ldown, Tair_C, alb_surf, emis_surf, LAI_id, &
74 n_vegetation_region_urban, &
75 n_stream_sw_urban, n_stream_lw_urban, &
76 sw_dn_direct_frac, air_ext_sw, air_ssa_sw, &
77 veg_ssa_sw, air_ext_lw, air_ssa_lw, veg_ssa_lw, &
78 veg_fsd_const, veg_contact_fraction_const, &
79 ground_albedo_dir_mult_fact, use_sw_direct_albedo, &
80 height, building_frac, veg_frac, sfr_roof, sfr_wall, &
81 building_scale, veg_scale, & !input:
82 alb_roof, emis_roof, alb_wall, emis_wall, &
83 roof_albedo_dir_mult_fact, wall_specular_frac, &
84 qn, kup, lup, qn_roof, qn_wall, qn_surf, & !output:
85 dataOutLineSPARTACUS)
86 USE parkind1, ONLY: jpim, jprb
87 USE radsurf_interface, ONLY: radsurf
88 USE radsurf_config, ONLY: config_type
89 ! USE spartacus_surface_config, ONLY: read_config_from_namelist, driver_config_type
90 USE radsurf_canopy_properties, ONLY: canopy_properties_type
91 USE radsurf_sw_spectral_properties, ONLY: sw_spectral_properties_type
92 USE radsurf_lw_spectral_properties, ONLY: lw_spectral_properties_type
93 USE radsurf_boundary_conds_out, ONLY: boundary_conds_out_type
94 USE radsurf_canopy_flux, ONLY: canopy_flux_type
95 USE radsurf_simple_spectrum, ONLY: calc_simple_spectrum_lw
96 ! USE data_in, ONLY: fileinputpath
98
99 IMPLICIT NONE
100
101 !!!!!!!!!!!!!! Set objects and variables !!!!!!!!!!!!!!
102
103 ! Input parameters and variables from SUEWS
104 REAL(KIND(1D0)), INTENT(IN) :: zenith_deg
105 INTEGER, INTENT(IN) :: DiagQN
106 INTEGER, INTENT(IN) :: nlayer
107
108 ! TODO: tsurf_0 and temp_C need to be made vertically distributed
109 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: tsfc_roof, tsfc_wall
110 REAL(KIND(1D0)), INTENT(IN) :: Tair_C
111
112 REAL(KIND(1D0)), INTENT(IN) :: kdown
113 REAL(KIND(1D0)), INTENT(IN) :: ldown
114 REAL(KIND(1D0)), DIMENSION(NSURF), INTENT(IN) :: tsfc_surf
115
116 REAL(KIND(1D0)), DIMENSION(NSURF), INTENT(IN) :: sfr_surf, alb_surf, emis_surf
117 REAL(KIND(1D0)), DIMENSION(NVegSurf), INTENT(IN) :: LAI_id
118
119 ! SPARTACUS configuration parameters
120 INTEGER, INTENT(IN) :: n_vegetation_region_urban, &
121 n_stream_sw_urban, n_stream_lw_urban
122 REAL(KIND(1D0)), INTENT(IN) :: sw_dn_direct_frac, air_ext_sw, air_ssa_sw, &
123 veg_ssa_sw, air_ext_lw, air_ssa_lw, veg_ssa_lw, &
124 veg_fsd_const, veg_contact_fraction_const, &
125 ground_albedo_dir_mult_fact
126 ! INTEGER(kind=jpim) :: ncol
127 ! INTEGER(kind=jpim) :: nlayer
128 INTEGER(kind=jpim), ALLOCATABLE :: i_representation(:)
129 INTEGER(kind=jpim), ALLOCATABLE :: nlay(:)
130 INTEGER :: istartcol, iendcol
131 INTEGER :: jrepeat, ilay, jlay, jcol
132
133 ! --------------------------------------------------------------------------------
134 ! output variables
135 ! --------------------------------------------------------------------------------
136 ! these will be used by other SUEWS calculations
137 REAL(KIND(1D0)), INTENT(OUT) :: qn, kup, lup
138 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(OUT) :: qn_roof
139 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(OUT) :: qn_wall
140 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(OUT) :: qn_surf
141 REAL(KIND(1D0)) :: sw_net_grnd
142 REAL(KIND(1D0)) :: lw_net_grnd
143 REAL(KIND(1D0)) :: sw_dn_grnd
144 REAL(KIND(1D0)) :: lw_dn_grnd
145 REAL(KIND(1D0)) :: lw_up_grnd
146 REAL(KIND(1D0)), DIMENSION(NSURF - 1) :: qn_grnd_ind
147 REAL(KIND(1D0)), DIMENSION(NSURF - 1) :: alb_grnd_ind
148 REAL(KIND(1D0)), DIMENSION(NSURF - 1) :: emis_grnd_ind
149 REAL(KIND(1D0)), DIMENSION(NSURF - 1) :: sfr_grnd_ind
150 REAL(KIND(1D0)), DIMENSION(nsurf - 1) :: sw_net_grnd_ind
151 REAL(KIND(1D0)), DIMENSION(nsurf - 1) :: lw_net_grnd_ind
152 REAL(KIND(1D0)), DIMENSION(NSURF - 1) :: tsfc_grnd_ind_K
153 ! --------------------------------------------------------------------------------
154 ! these will be in the SPARTACUS output array
155 REAL(KIND(1D0)) :: alb_spc, emis_spc, lw_emission_spc, lw_up_spc, sw_up_spc, qn_spc
156 REAL(KIND(1D0)) :: top_net_lw_spc
157 REAL(KIND(1D0)) :: grnd_net_lw_spc
158 REAL(KIND(1D0)) :: top_dn_lw_spc
159 REAL(KIND(1D0)) :: top_dn_dir_sw_spc
160 REAL(KIND(1D0)) :: top_net_sw_spc
161 REAL(KIND(1D0)) :: grnd_dn_dir_sw_spc
162 REAL(KIND(1D0)) :: grnd_net_sw_spc
163 REAL(KIND(1D0)) :: grnd_vertical_diff
164 REAL(KIND(1D0)), DIMENSION(15) :: clear_air_abs_lw_spc
165 REAL(KIND(1D0)), DIMENSION(15) :: clear_air_abs_sw_spc
166 REAL(KIND(1D0)), DIMENSION(15) :: roof_in_sw_spc
167 REAL(KIND(1D0)), DIMENSION(15) :: roof_in_lw_spc
168 REAL(KIND(1D0)), DIMENSION(15) :: roof_net_sw_spc
169 REAL(KIND(1D0)), DIMENSION(15) :: roof_net_lw_spc
170 REAL(KIND(1D0)), DIMENSION(15) :: wall_in_sw_spc
171 REAL(KIND(1D0)), DIMENSION(15) :: wall_in_lw_spc
172 REAL(KIND(1D0)), DIMENSION(15) :: wall_net_sw_spc
173 REAL(KIND(1D0)), DIMENSION(15) :: wall_net_lw_spc
174 REAL(KIND(1D0)), DIMENSION(15) :: sfr_roof_spc
175 REAL(KIND(1D0)), DIMENSION(15) :: sfr_wall_spc
176 ! --------------------------------------------------------------------------------
177
178 REAL(KIND(1D0)), DIMENSION(ncolumnsDataOutSPARTACUS - 5), INTENT(OUT) :: dataOutLineSPARTACUS
179
180 ! Derived types for the inputs to the radiation scheme
181 TYPE(config_type) :: config
182 TYPE(canopy_properties_type) :: canopy_props
183 TYPE(sw_spectral_properties_type) :: sw_spectral_props
184 TYPE(lw_spectral_properties_type) :: lw_spectral_props
185 TYPE(boundary_conds_out_type) :: bc_out
186 TYPE(canopy_flux_type) :: sw_norm_dir ! SW fluxes normalized by top-of-canopy direct
187 TYPE(canopy_flux_type) :: sw_norm_diff ! SW fluxes normalized by top-of-canopy diffuse
188 TYPE(canopy_flux_type) :: lw_internal ! LW fluxes from internal emission
189 TYPE(canopy_flux_type) :: lw_norm ! LW fluxes normalized by top-of-canopy down
190 TYPE(canopy_flux_type) :: lw_flux ! Total lw canopy fluxes
191 TYPE(canopy_flux_type) :: sw_flux ! Total sw canopy fluxes
192
193 ! Top-of-canopy downward radiation, all dimensioned (nspec, ncol)
194 REAL(KIND(1D0)), ALLOCATABLE :: top_flux_dn_sw(:, :) ! Total shortwave (direct+diffuse)
195 REAL(KIND(1D0)), ALLOCATABLE :: top_flux_dn_direct_sw(:, :) ! ...diffuse only
196 REAL(KIND(1D0)), ALLOCATABLE :: top_flux_dn_lw(:, :) ! longwave
197
198 ! surface temperature and air temperature in Kelvin
199 REAL(KIND(1D0)), DIMENSION(nlayer) :: tsfc_roof_K, tsfc_wall_K
200 REAL(KIND(1D0)), DIMENSION(nsurf) :: tsfc_surf_K
201 REAL(KIND(1D0)) :: tair_K
202 ! top-of-canopy diffuse sw downward
203 REAL(KIND(1D0)) :: top_flux_dn_diffuse_sw
204 ! plan area weighted albedo and emissivity of surfaces not including buildings and trees
205 REAL(KIND(1D0)) :: alb_no_tree_bldg, emis_no_tree_bldg
206 ! vegetation emissivity
207 ! REAL(KIND(1D0)) :: veg_emis
208 ! area weighted LAI of trees
209 REAL(KIND(1D0)), ALLOCATABLE :: LAI_av(:)
210 ! area weighted LAI of trees in each layer
211 REAL(KIND(1D0)), ALLOCATABLE :: LAI_av_z(:)
212 REAL(KIND(1D0)), ALLOCATABLE :: veg_ext(:)
213 ! depth of the vegetated layer
214 REAL(KIND(1D0)), ALLOCATABLE :: veg_depth(:)
215
216 LOGICAL, INTENT(IN) :: use_sw_direct_albedo
217
218 REAL(KIND(1D0)), DIMENSION(nlayer + 1), INTENT(IN) :: height
219 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: building_frac ! cumulative building fraction at each layer
220 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: veg_frac
221 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: sfr_roof ! individual surface fraction of roofs at each layer
222 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: sfr_wall ! individual surface fraction of walls at each layer
223 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: building_scale
224 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: veg_scale
225 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: alb_roof
226 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: emis_roof
227 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: alb_wall
228 REAL(KIND(1D0)), DIMENSION(nlayer), INTENT(IN) :: emis_wall
229 REAL(KIND(1D0)), DIMENSION(nspec, nlayer), INTENT(IN) :: roof_albedo_dir_mult_fact
230 REAL(KIND(1D0)), DIMENSION(nspec, nlayer), INTENT(IN) :: wall_specular_frac
231
232 ! parameters to pass into the radiation scheme
233 REAL(KIND(1D0)), DIMENSION(nspec, nlayer) :: roof_albedo
234 REAL(KIND(1D0)), DIMENSION(nspec, nlayer) :: wall_albedo
235 REAL(KIND(1D0)), DIMENSION(nspec, nlayer) :: roof_emissivity
236 REAL(KIND(1D0)), DIMENSION(nspec, nlayer) :: wall_emissivity
237 REAL(KIND(1D0)), DIMENSION(nlayer) :: veg_fsd, veg_contact_fraction
238 ! INTEGER :: i
239 ! REAL(KIND(1D0)) :: debug1, debug2
240
241 IF (diagqn == 1) print *, 'in SPARTACUS, starting ...'
242 ! initialize the output variables
243 dataoutlinespartacus = -999.
244
245 sfr_roof_spc = -999.
246 sfr_roof_spc(1:nlayer) = sfr_roof
247 sfr_wall_spc = -999.
248 sfr_wall_spc(1:nlayer) = sfr_wall
249
250 ALLOCATE (nlay(ncol))
251 ! nlay = [nlayers] ! modified to follow ESTM_ext convention
252 nlay = [nlayer]
253 ALLOCATE (veg_ext(nlayer))
254
255 !Set the values of profiles that are implemented as being constant with height
256 ! veg_frac(:) = veg_frac_const
257 veg_fsd(:) = veg_fsd_const
258 veg_contact_fraction(:) = veg_contact_fraction_const
259
260 ! Set the values of the albedo/emissivity profiles; note the dimension
261 roof_albedo(nspec, :) = alb_roof
262 wall_albedo(nspec, :) = alb_wall
263 roof_emissivity(nspec, :) = emis_roof
264 wall_emissivity(nspec, :) = emis_wall
265 ! print *, 'emis_wall in su', emis_wall
266 ! print *, 'wall_emissivity(nspec, :) in su', wall_emissivity(nspec, :)
267
268 !!!!!!!!!!!!!! Model configuration !!!!!!!!!!!!!!
269 IF (diagqn == 1) print *, 'in SPARTACUS, setting up model ...'
270 ! CALL config%READ(file_name=TRIM(FileInputPath)//'SUEWS_SPARTACUS.nml')
271 config%do_sw = .true.
272 config%do_lw = .true.
273 config%use_sw_direct_albedo = use_sw_direct_albedo
274 ALLOCATE (i_representation(ncol))
275 IF (sfr_surf(conifsurf) + sfr_surf(decidsurf) > 0.0 .AND. sfr_surf(bldgsurf) > 0.0) THEN
276 config%do_vegetation = .true.
277 i_representation = [3]
278 config%do_urban = .true.
279 ELSE IF (sfr_surf(conifsurf) + sfr_surf(decidsurf) == 0.0 .AND. sfr_surf(bldgsurf) > 0.0) THEN
280 config%do_vegetation = .false.
281 i_representation = [2]
282 config%do_urban = .true.
283 ELSE IF (sfr_surf(conifsurf) + sfr_surf(decidsurf) > 0.0 .AND. sfr_surf(bldgsurf) == 0.0) THEN
284 config%do_vegetation = .true.
285 i_representation = [1]
286 config%do_urban = .false.
287 ELSE
288 config%do_vegetation = .false.
289 i_representation = [0]
290 config%do_urban = .false.
291 END IF
292 config%iverbose = 3
293 config%n_vegetation_region_urban = n_vegetation_region_urban
294 config%n_vegetation_region_forest = n_vegetation_region_urban ! use the same complexity for urban as forests
295 config%nsw = nsw
296 config%nlw = nlw
297 config%n_stream_sw_urban = n_stream_sw_urban
298 config%n_stream_lw_urban = n_stream_lw_urban
299 config%n_stream_sw_forest = n_stream_sw_urban ! use the same complexity for urban as forests
300 config%n_stream_lw_forest = n_stream_lw_urban ! use the same complexity for urban as forests
301 CALL config%consolidate()
302
303 !!!!!!!!!!!!!! allocate and set canopy_props !!!!!!!!!!!!!!
304
305 ! allocate
306 CALL canopy_props%DEALLOCATE()
307 CALL canopy_props%ALLOCATE(config, ncol, nlayer, i_representation)
308
309 ! set cos_sza, nlay, ncol, ntotlay
310 canopy_props%cos_sza = cos(zenith_deg*3.1415927/180)
311 canopy_props%nlay = nlay
312 canopy_props%ncol = ncol
313 canopy_props%ntotlay = nlayer
314
315 IF (diagqn == 1) print *, 'in SPARTACUS, calculating dz array ...'
316 ! calculate dz array
317 ilay = 1
318 DO jcol = 1, ncol
319 canopy_props%dz(ilay:ilay + canopy_props%nlay(jcol) - 1) &
320 & = height(ilay + 1:ilay + canopy_props%nlay(jcol)) &
321 & - height(ilay:ilay + canopy_props%nlay(jcol) - 1)
322 canopy_props%istartlay(jcol) = ilay
323 ilay = ilay + canopy_props%nlay(jcol)
324 END DO
325
326 ALLOCATE (lai_av(ncol))
327 ALLOCATE (veg_depth(ncol))
328 ALLOCATE (lai_av_z(nlayer))
329 !Calculate the area weighted LAI of trees
330 DO jcol = 1, ncol
331 ! the 10.**-10 stops the equation blowing up when there are no trees
332 lai_av(jcol) = &
333 (sfr_surf(conifsurf)*lai_id(1) + sfr_surf(decidsurf)*lai_id(2)) &
334 /(sfr_surf(conifsurf) + sfr_surf(decidsurf) + 10.**(-10))
335 END DO
336 ! print *, 'height in spartacus', height
337 ! print *, 'building_frac in spartacus', building_frac
338 ! print *, 'veg_frac in spartacus', veg_frac
339 ! print *, 'building_scale in spartacus', building_scale
340 ! print *, 'veg_scale in spartacus', veg_scale
341 ! find veg_depth
342 DO jcol = 1, ncol
343 ilay = canopy_props%istartlay(jcol)
344 veg_depth(jcol) = 0.
345 DO jlay = 0, nlay(jcol) - 1
346 IF (veg_frac(ilay + jlay) > 0.) THEN
347 veg_depth(jcol) = veg_depth(jcol) + canopy_props%dz(ilay + jlay)
348 END IF
349 END DO
350 END DO
351 ! find LAV_av_z and veg_ext. Assume the LAI is uniform with height within the vegetation layer.
352 DO jcol = 1, ncol
353 ilay = canopy_props%istartlay(jcol)
354 ! PRINT *, 'jcol', jcol
355 ! PRINT *, 'ilay', ilay
356 DO jlay = 0, nlay(jcol) - 1
357 ! PRINT *, 'jlay', jlay
358 ! PRINT *, 'veg_frac(ilay + jlay)', veg_frac(ilay + jlay)
359 ! PRINT *, 'LAI_av(jcol)', LAI_av(jcol)
360 ! PRINT *, 'canopy_props%dz(ilay + jlay)', canopy_props%dz(ilay + jlay)
361 IF (veg_frac(ilay + jlay) > 0.) THEN
362 lai_av_z(ilay + jlay) = lai_av(jcol)*canopy_props%dz(ilay + jlay)/veg_depth(jcol)
363 veg_ext(ilay + jlay) = lai_av_z(ilay + jlay)/(2*canopy_props%dz(ilay))
364 END IF
365 END DO
366 END DO
367
368 ! set temperature
369 tsfc_surf_k = tsfc_surf + 273.15 ! convert surface temperature to Kelvin
370 tsfc_roof_k = tsfc_roof + 273.15 ! convert surface temperature to Kelvin
371 tsfc_wall_k = tsfc_wall + 273.15 ! convert surface temperature to Kelvin
372 tair_k = tair_c + 273.15 ! convert air temperature to Kelvin
373
374 ! set ground temperature as the area-weighted average of the surface temperature of all land covers but buildings
375 canopy_props%ground_temperature = (dot_product(tsfc_surf_k, sfr_surf) - tsfc_surf_k(bldgsurf)*sfr_surf(bldgsurf)) &
376 /(1 - sfr_surf(bldgsurf))
377
378 canopy_props%roof_temperature = tsfc_roof_k
379 canopy_props%wall_temperature = tsfc_wall_k
380 canopy_props%clear_air_temperature = tair_k
381 IF (sfr_surf(conifsurf) + sfr_surf(decidsurf) > 0.0) THEN
382 canopy_props%veg_temperature = dot_product(tsfc_surf_k(conifsurf:decidsurf), sfr_surf(conifsurf:decidsurf))
383 canopy_props%veg_air_temperature = tair_k
384 END IF
385
386 ! set building and vegetation properties
387 canopy_props%i_representation = i_representation
388 canopy_props%building_scale = building_scale(:) ! diameter of buildings (m). The only L method for buildings is Eq. 19 Hogan et al. 2018.
389 canopy_props%building_fraction = building_frac(:) ! building fraction
390 IF (sfr_surf(conifsurf) + sfr_surf(decidsurf) > 0.0) THEN
391 canopy_props%veg_fraction = veg_frac(:) ! evergreen + deciduous fractions
392 canopy_props%veg_scale = veg_scale(:) ! scale of tree crowns (m). Using the default use_symmetric_vegetation_scale_urban=.TRUE. so that Eq. 20 Hogan et al. 2018 is used for L.
393 canopy_props%veg_ext = veg_ext(:)
394 canopy_props%veg_fsd = veg_fsd(:)
395 canopy_props%veg_contact_fraction = veg_contact_fraction(:)
396 END IF
397
398 !!!!!!!!!!!!!! allocate and set canopy top forcing !!!!!!!!!!!!!!
399 IF (diagqn == 1) print *, 'in SPARTACUS, setting canopy top forcing ...'
400 ALLOCATE (top_flux_dn_sw(nspec, ncol))
401 ALLOCATE (top_flux_dn_direct_sw(nspec, ncol))
402 ALLOCATE (top_flux_dn_lw(nspec, ncol))
403 top_flux_dn_sw = kdown ! diffuse + direct
404 top_flux_dn_direct_sw = sw_dn_direct_frac*kdown ! Berrizbeitia et al. 2020 say the ratio diffuse/direct is 0.55 for Berlin and Brussels on av annually
405 top_flux_dn_diffuse_sw = top_flux_dn_sw(nspec, ncol) - top_flux_dn_direct_sw(nspec, ncol)
406 top_flux_dn_lw = ldown
407
408 !!!!!!!!!!!!!! allocate and set sw_spectral_props !!!!!!!!!!!!!!
409
410 CALL sw_spectral_props%DEALLOCATE()
411 CALL sw_spectral_props%ALLOCATE(config, ncol, nlayer, nspec, canopy_props%i_representation)
412
413 ! albedo of the ground
414 alb_no_tree_bldg = (alb_surf(1)*sfr_surf(pavsurf) + alb_surf(5)*sfr_surf(grasssurf) + &
415 alb_surf(6)*sfr_surf(bsoilsurf) + alb_surf(7)*sfr_surf(watersurf))/ &
416 (sfr_surf(pavsurf) + sfr_surf(grasssurf) + sfr_surf(bsoilsurf) + sfr_surf(watersurf))
417 sw_spectral_props%air_ext = air_ext_sw
418 sw_spectral_props%air_ssa = air_ssa_sw
419 IF (sfr_surf(conifsurf) + sfr_surf(decidsurf) > 0.0) THEN
420 sw_spectral_props%veg_ssa = veg_ssa_sw
421 END IF
422 sw_spectral_props%ground_albedo = alb_no_tree_bldg ! albedo excluding buildings and trees
423 sw_spectral_props%roof_albedo = roof_albedo(nspec, ncol) ! albedo of buildings
424 sw_spectral_props%wall_albedo = wall_albedo(nspec, ncol) ! albedo of buildings
425 sw_spectral_props%wall_specular_frac = wall_specular_frac(nspec, ncol)
426 IF (config%use_sw_direct_albedo) THEN
427 sw_spectral_props%ground_albedo_dir = alb_no_tree_bldg*ground_albedo_dir_mult_fact
428 sw_spectral_props%roof_albedo_dir = roof_albedo(nspec, ncol)*roof_albedo_dir_mult_fact(nspec, ncol)
429 END IF
430
431 !!!!!!!!!!!!!! allocate and set lw_spectral_props !!!!!!!!!!!!!!
432
433 CALL lw_spectral_props%DEALLOCATE()
434 CALL lw_spectral_props%ALLOCATE(config, nspec, ncol, nlayer, canopy_props%i_representation)
435
436 emis_no_tree_bldg = (emis_surf(1)*sfr_surf(pavsurf) + emis_surf(5)*sfr_surf(grasssurf) + &
437 emis_surf(6)*sfr_surf(bsoilsurf) + emis_surf(7)*sfr_surf(watersurf))/ &
438 (sfr_surf(pavsurf) + sfr_surf(grasssurf) + sfr_surf(bsoilsurf) + sfr_surf(watersurf)) ! emissivity of the ground
439 lw_spectral_props%air_ext = air_ext_lw
440 lw_spectral_props%air_ssa = air_ssa_lw
441 IF (sfr_surf(conifsurf) + sfr_surf(decidsurf) > 0.0) THEN
442 lw_spectral_props%veg_ssa = veg_ssa_lw
443 END IF
444 lw_spectral_props%ground_emissivity = emis_no_tree_bldg ! emissivity excluding buildings and trees
445 lw_spectral_props%roof_emissivity = roof_emissivity(nspec, ncol) ! emissivity of buildings
446 lw_spectral_props%wall_emissivity = wall_emissivity(nspec, ncol) ! emissivity of buildings
447
448 ! print *, 'roof_emissivity in suews-su ', roof_emissivity(nspec,:)
449 ! print *, 'wall_emissivity in suews-su ', wall_emissivity(nspec,:)
450 ! print *, 'lw_spectral_props%wall_emissivity in suews-su ', lw_spectral_props%wall_emissivity
451 ! print *, 'lw_spectral_props%wall_emissivity in suews-su ', lw_spectral_props%wall_emissivity
452
453 !!!!!!!!!!!!!! allocate sw !!!!!!!!!!!!!!
454
455 IF (config%do_sw) THEN
456 CALL sw_norm_dir%ALLOCATE(config, ncol, nlayer, config%nsw, use_direct=.true.)
457 CALL sw_norm_diff%ALLOCATE(config, ncol, nlayer, config%nsw, use_direct=.true.)
458
459 CALL sw_norm_dir%zero_all()
460 CALL sw_norm_diff%zero_all()
461
462 CALL sw_flux%ALLOCATE(config, ncol, nlayer, config%nsw, use_direct=.true.)
463 END IF
464
465 !!!!!!!!!!!!!! allocate lw !!!!!!!!!!!!!!
466
467 IF (config%do_lw) THEN
468 CALL lw_internal%ALLOCATE(config, ncol, nlayer, config%nlw, use_direct=.true.)
469 CALL lw_norm%ALLOCATE(config, ncol, nlayer, config%nlw, use_direct=.true.)
470
471 CALL lw_internal%zero_all()
472 CALL lw_norm%zero_all()
473
474 CALL lw_flux%ALLOCATE(config, ncol, nlayer, config%nlw, use_direct=.true.)
475 END IF
476
477 !!!!!!!!!!!!!! allocate bc_out !!!!!!!!!!!!!!
478
479 CALL bc_out%ALLOCATE(ncol, config%nsw, config%nlw)
480
481 !!!!!!!!!!!!!! run calc_monochromatic_emission !!!!!!!!!!!!!!
482
483 CALL lw_spectral_props%calc_monochromatic_emission(canopy_props)
484
485 !!!!!!!!!!!!!! CALL radsurf !!!!!!!!!!!!!!
486
487 istartcol = 1
488 iendcol = 1
489 ! Option of repeating calculation multiple time for more accurate profiling
490 DO jrepeat = 1, 3
491 IF (config%do_lw) THEN
492 ! Gas optics and spectral emission
493 CALL calc_simple_spectrum_lw(config, canopy_props, lw_spectral_props, &
494 & istartcol, iendcol)
495 END IF
496 ! Call the SPARTACUS-Surface radiation scheme
497 CALL radsurf(config, canopy_props, &
498 & sw_spectral_props, lw_spectral_props, &
499 & bc_out, &
500 & istartcol, iendcol, &
501 & sw_norm_dir, sw_norm_diff, &
502 & lw_internal, lw_norm)
503 IF (config%do_sw) THEN
504 ! Scale the normalized fluxes
505 CALL sw_norm_dir%SCALE(canopy_props%nlay, &
506 & top_flux_dn_direct_sw)
507 CALL sw_norm_diff%SCALE(canopy_props%nlay, &
508 & top_flux_dn_sw - top_flux_dn_direct_sw)
509 CALL sw_flux%SUM(sw_norm_dir, sw_norm_diff)
510 END IF
511 IF (config%do_lw) THEN
512 CALL lw_norm%SCALE(canopy_props%nlay, top_flux_dn_lw)
513 CALL lw_flux%SUM(lw_internal, lw_norm)
514 END IF
515 END DO
516
517 ! albedo
518 IF (top_flux_dn_diffuse_sw + top_flux_dn_direct_sw(nspec, ncol) > 0.1) THEN
519 alb_spc = ((top_flux_dn_diffuse_sw + 10.**(-10))*(bc_out%sw_albedo(nspec, ncol)) & ! the 10.**-10 stops the equation blowing up when kdwn=0
520 + (top_flux_dn_direct_sw(nspec, ncol) + 10.**(-10))*(bc_out%sw_albedo_dir(nspec, ncol))) &
521 /(top_flux_dn_diffuse_sw + top_flux_dn_direct_sw(nspec, ncol) + 10.**(-10))
522 IF (alb_spc < 0.0) alb_spc = 0
523 ELSE
524 alb_spc = 0.0
525 END IF
526
527 !!! Output arrays !!!
528
529 ! emissivity
530 emis_spc = bc_out%lw_emissivity(nspec, ncol)
531 ! longwave emission
532 lw_emission_spc = bc_out%lw_emission(nspec, ncol)
533 ! lowngwave upward = emitted as blackbody + reflected
534 lw_up_spc = lw_emission_spc + (1 - emis_spc)*ldown
535 ! shortwave upward = downward diffuse * diffuse albedo + downward direct * direct albedo
536 sw_up_spc = 0.0
537 sw_up_spc = kdown*alb_spc ! or more simply: alb_spc*avKdn
538 ! net all = net sw + net lw
539 qn_spc = sw_flux%top_net(nspec, ncol) + lw_flux%top_net(nspec, ncol)
540
541 ! lw arrays
542 clear_air_abs_lw_spc = -999
543 clear_air_abs_lw_spc(:nlayer) = lw_flux%clear_air_abs(nspec, :nlayer)
544 wall_net_lw_spc = -999
545 wall_net_lw_spc(:nlayer) = lw_flux%wall_net(nspec, :nlayer)
546 wall_in_lw_spc = -999
547 wall_in_lw_spc(:nlayer) = lw_flux%wall_in(nspec, :nlayer)
548 ! PRINT *, 'wall_net_lw_spc in suews-su', lw_flux%wall_net
549 roof_net_lw_spc = -999
550 roof_net_lw_spc(:nlayer) = lw_flux%roof_net(nspec, :nlayer)
551 ! PRINT *, 'roof_net_lw_spc in suews-su', lw_flux%roof_net
552 roof_in_lw_spc = -999
553 roof_in_lw_spc(:nlayer) = lw_flux%roof_in(nspec, :nlayer)
554 top_net_lw_spc = lw_flux%top_net(nspec, ncol)
555 grnd_net_lw_spc = lw_flux%ground_net(nspec, ncol)
556 top_dn_lw_spc = lw_flux%top_dn(nspec, ncol)
557
558 ! sw arrays
559 clear_air_abs_sw_spc = -999
560 clear_air_abs_sw_spc(:nlayer) = sw_flux%clear_air_abs(nspec, :nlayer)
561 wall_net_sw_spc = -999
562 wall_net_sw_spc(:nlayer) = sw_flux%wall_net(nspec, :nlayer)
563 wall_in_sw_spc = -999
564 wall_in_sw_spc(:nlayer) = sw_flux%wall_in(nspec, :nlayer)
565 ! PRINT *, 'wall_net_sw_spc in suews-su', wall_net_sw_spc(:nlayer), sw_flux%wall_net
566 roof_net_sw_spc = -999
567 roof_net_sw_spc(:nlayer) = sw_flux%roof_net(nspec, :nlayer)
568 ! PRINT *, 'roof_net_sw_spc in suews-su', roof_net_sw_spc(:nlayer)
569 ! PRINT *, 'roof_net_sw_spc in suews-su', sw_flux%roof_net
570 roof_in_sw_spc = -999
571 roof_in_sw_spc(:nlayer) = sw_flux%roof_in(nspec, :nlayer)
572 ! PRINT *, 'roof sw in in suews-su', roof_in_sw_spc(:nlayer)
573 ! PRINT *, 'roof sw in in suews-su', sw_flux%roof_in
574 ! print *, ''
575 top_dn_dir_sw_spc = sw_flux%top_dn_dir(nspec, ncol)
576 top_net_sw_spc = sw_flux%top_net(nspec, ncol)
577 grnd_dn_dir_sw_spc = sw_flux%ground_dn_dir(nspec, ncol)
578 grnd_net_sw_spc = sw_flux%ground_net(nspec, ncol)
579 grnd_vertical_diff = sw_flux%ground_vertical_diff(nspec, ncol)
580
581 !!!!!!!!!!!!!! Bulk KUP, LUP, QSTAR for SUEWS !!!!!!!!!!!!!!
582
583 lup = lw_up_spc
584 ! print *, 'lw_up_spc', lw_up_spc
585 kup = sw_up_spc
586 ! print *, 'sw_up_spc', sw_up_spc
587 ! limit the lower limit of qn to avoid issue when used with OHM
588 qn = max(qn_spc, -600d0)
589 ! print *, 'qn_spc', qn_spc
590
591 ! ============================================================
592 ! net radiation for roof/wall
593 ! note these fluxes are NOT de-normalised
594 qn_roof = roof_net_lw_spc(:nlayer) + roof_net_sw_spc(:nlayer)
595 qn_wall = wall_net_lw_spc(:nlayer) + wall_net_sw_spc(:nlayer)
596
597 ! de-normalise net radiation for roof/wall - these will be used in other SUEWS calculations
598 ! note the orignal results from above SS calcuations are normalised by the whole grid area
599 ! roof: need to de-normalise by dividing the building/roof fraction
600 qn_roof = qn_roof/sfr_roof(:nlayer)
601 ! wall: need to de-normalise by dividing the building/wall fraction
602 qn_wall = qn_wall/sfr_wall(:nlayer)
603
604 ! ============================================================
605 ! net radiation for ground surfaces
606 ! retrieve the surface temperatures/properties of all ground land covers except for buildings
607 sfr_grnd_ind = sfr_surf([pavsurf, conifsurf, decidsurf, grasssurf, bsoilsurf, watersurf])
608 tsfc_grnd_ind_k = tsfc_surf_k([pavsurf, conifsurf, decidsurf, grasssurf, bsoilsurf, watersurf])
609 emis_grnd_ind = emis_surf([pavsurf, conifsurf, decidsurf, grasssurf, bsoilsurf, watersurf])
610 alb_grnd_ind = alb_surf([pavsurf, conifsurf, decidsurf, grasssurf, bsoilsurf, watersurf])
611
612 ! note the ground here includes all surfaces that are not roof/wall
613 ! de-normalise net radiation for ground surfaces - these will be used in other SUEWS calculations:
614 sw_net_grnd = grnd_net_sw_spc/(1 - building_frac(1))
615 lw_net_grnd = grnd_net_lw_spc/(1 - building_frac(1))
616
617 ! net shortwave radiation for individual ground surfaces
618 sw_dn_grnd = sw_net_grnd/dot_product(alb_grnd_ind, sfr_grnd_ind)/sum(sfr_grnd_ind)
619 sw_net_grnd_ind = sw_net_grnd*(1 - alb_surf([pavsurf, conifsurf, decidsurf, grasssurf, bsoilsurf, watersurf]))
620
621 ! net longwave radiation for individual ground surfaces
622 lw_up_grnd = sbconst*dot_product(emis_grnd_ind*tsfc_grnd_ind_k**4, sfr_grnd_ind)/sum(sfr_grnd_ind)
623
624 ! assume that the downward longwave radiation incident on the ground is the same between all surfaces
625 lw_dn_grnd = lw_up_grnd + lw_net_grnd
626 lw_net_grnd_ind = lw_dn_grnd - sbconst*emis_grnd_ind*tsfc_grnd_ind_k**4
627
628 ! net all-wave radiation for individual ground surfaces
629 qn_grnd_ind = lw_net_grnd_ind + sw_net_grnd_ind
630
631 ! combine with all surfaces
632 qn_surf([pavsurf, conifsurf, decidsurf, grasssurf, bsoilsurf, watersurf]) = qn_grnd_ind
633
634 ! average between roof and wall for the building surface: a simple treatment
635 ! qn_surf(BldgSurf) = (DOT_PRODUCT(qn_roof, sfr_roof)/SUM(sfr_roof) + DOT_PRODUCT(qn_wall, sfr_wall)/SUM(sfr_wall))
636 qn_surf(bldgsurf) = (qn_spc - dot_product(qn_grnd_ind, sfr_grnd_ind))/sfr_surf(bldgsurf)
637
638 dataoutlinespartacus = &
639 [alb_spc, emis_spc, &
640 top_dn_dir_sw_spc, &
641 sw_up_spc, &
642 top_dn_lw_spc, &
643 lw_up_spc, &
644 qn_spc, &
645 top_net_sw_spc, &
646 top_net_lw_spc, &
647 lw_emission_spc, &
648 grnd_dn_dir_sw_spc, &
649 grnd_vertical_diff, &
650 grnd_net_sw_spc, &
651 grnd_net_lw_spc, &
652 roof_in_sw_spc, &
653 roof_net_sw_spc, &
654 wall_in_sw_spc, &
655 wall_net_sw_spc, &
656 clear_air_abs_sw_spc, &
657 roof_in_lw_spc, &
658 roof_net_lw_spc, &
659 wall_in_lw_spc, &
660 wall_net_lw_spc, &
661 sfr_roof_spc, &
662 sfr_wall_spc, &
663 clear_air_abs_lw_spc &
664 ]
665
666 !!!!!!!!!!!!!! Clear from memory !!!!!!!!!!!!!
667
668 CALL canopy_props%DEALLOCATE()
669 CALL sw_spectral_props%DEALLOCATE()
670 CALL lw_spectral_props%DEALLOCATE()
671 CALL bc_out%DEALLOCATE()
672 CALL sw_norm_dir%DEALLOCATE()
673 CALL sw_norm_diff%DEALLOCATE()
674 CALL lw_internal%DEALLOCATE()
675 CALL lw_norm%DEALLOCATE()
676 CALL sw_flux%DEALLOCATE()
677 CALL lw_flux%DEALLOCATE()
678
679 ! DEALLOCATE (height)
680 DEALLOCATE (top_flux_dn_sw)
681 DEALLOCATE (top_flux_dn_direct_sw)
682 DEALLOCATE (top_flux_dn_lw)
683 ! DEALLOCATE (building_frac)
684 ! DEALLOCATE (veg_frac)
685 ! DEALLOCATE (building_scale)
686 ! DEALLOCATE (veg_scale)
687 DEALLOCATE (veg_depth)
688 DEALLOCATE (veg_ext)
689 DEALLOCATE (lai_av)
690 DEALLOCATE (lai_av_z)
691 ! DEALLOCATE (veg_fsd)
692 ! DEALLOCATE (veg_contact_fraction)
693 ! DEALLOCATE (roof_albedo)
694 ! DEALLOCATE (wall_albedo)
695 ! DEALLOCATE (roof_albedo_dir_mult_fact)
696 ! DEALLOCATE (wall_specular_frac)
697 ! DEALLOCATE (roof_emissivity)
698 ! DEALLOCATE (wall_emissivity)
699
700 END SUBROUTINE spartacus
701
702END MODULE spartacus_module
integer, parameter nsw
integer, parameter bldgsurf
integer, parameter conifsurf
real(kind(1d0)) ground_albedo_dir_mult_fact
integer n_vegetation_region_urban
real(kind(1d0)) veg_ssa_lw
real(kind(1d0)) air_ext_sw
real(kind(1d0)) air_ssa_sw
integer, parameter nlw
real(kind(1d0)) veg_ssa_sw
real(kind(1d0)) air_ssa_lw
integer, parameter nspec
integer, parameter ncolumnsdataoutspartacus
integer, parameter watersurf
integer, parameter grasssurf
integer, parameter nvegsurf
real(kind(1d0)) veg_fsd_const
integer, parameter bsoilsurf
integer, parameter ncol
integer, parameter nsurf
integer, parameter pavsurf
real(kind(1d0)) air_ext_lw
real(kind(1d0)) sw_dn_direct_frac
integer, parameter decidsurf
real(kind(1d0)) veg_contact_fraction_const
character(len=150) fileinputpath
real(kind(1d0)), parameter sbconst
subroutine spartacus(diagqn, sfr_surf, zenith_deg, nlayer, tsfc_surf, tsfc_roof, tsfc_wall, kdown, ldown, tair_c, alb_surf, emis_surf, lai_id, n_vegetation_region_urban, n_stream_sw_urban, n_stream_lw_urban, sw_dn_direct_frac, air_ext_sw, air_ssa_sw, veg_ssa_sw, air_ext_lw, air_ssa_lw, veg_ssa_lw, veg_fsd_const, veg_contact_fraction_const, ground_albedo_dir_mult_fact, use_sw_direct_albedo, height, building_frac, veg_frac, sfr_roof, sfr_wall, building_scale, veg_scale, alb_roof, emis_roof, alb_wall, emis_wall, roof_albedo_dir_mult_fact, wall_specular_frac, qn, kup, lup, qn_roof, qn_wall, qn_surf, dataoutlinespartacus)