SUEWS API Site
Documentation of SUEWS source code
suews_phys_snow.f95
Go to the documentation of this file.
2 USE evap_module, ONLY: cal_evap
4
5 IMPLICIT NONE
6
7CONTAINS
8 !This subroutine makes snow related calculations at the model time step. Needed for the
9 !available energy in LUMPS and SUEWS. Made by LJ in Dec 2012
10 !SUBROUTINES:
11 ! MeltHeat - Calculation of snow related energy processes
12 ! SnowCalc - Calculation of snow and soil storages
13 ! Evap_SUEWS_Snow - Calculation of evaporation from the SnowPack
14 ! snowRem - Removal of snow my snow clearing
15 ! SnowDepletionCurve - Calculation of snow fractions
16 !Last modified
17 ! TS 22 Sep 2019 - split `SnowUpdate` into `albedo` and `density` parts so they can be better integrated with `SUEWS_cal_Qn` and `Snow_cal_MeltHeat`
18 ! TS 17 Sep 2017 - added wrapper `Snow_cal_MeltHeat` for `SUEWS_driver`
19 ! TS 04 Sep 2017 - added `veg_fr_snow` to update VegFractions with snow effect included
20 ! TS 31 Aug 2017 - fixed the incomplete explicit interfaces
21 ! LJ 24 Aug 2017 - added explicit interfaces
22 ! LJ 3 May 2016 - Changed so that not all surface water freezes in 5-min timestep.
23 ! Re-organization of the snow routine due to this change
24 ! Calculation of albedo moved from MeltHeat to SnowCalc
25 ! LJ 27 Jan 2016 - Tabs removed, cleaning of the code
26 ! HCW 08 Dec 2015 - Added check for no Paved surfaces
27 ! LJ 14 July 2015 - Code fixed to work with tstep.
28 ! HCW 06 Mar 2015 - Unused variable 'i' removed.
29 ! LJ Jan 2015 - Change the calculation from hourly timestep to timestep defined by nsh
30 ! LJ May 2013 - Calculation of the energy balance for the SnowPack was modified
31 ! to use qn1_ind_snow(StoreDrainPrm)
32 !=======================================================================================
33 ! SUBROUTINE Snow_cal_MeltHeat( &
34 ! tstep, tau_r, SnowDensMax, & !input
35 ! lvS_J_kg, lv_J_kg, RadMeltFact, TempMeltFact, SnowAlbMax, &
36 ! SnowDensMin, Temp_C, Precip, PrecipLimit, PrecipLimitAlb, &
37 ! nsh_real, sfr_surf, Tsurf_ind, Tsurf_ind_snow, state_surf, qn1_ind_snow, &
38 ! kup_ind_snow, SnowWater, deltaQi, albedo_snow, &
39 ! SnowPack_in, SnowFrac_in, SnowAlb_in, SnowDens_in, SnowfallCum_in, & !input
40 ! SnowPack_out, SnowFrac_out, SnowAlb_out, SnowDens_out, SnowfallCum_out, & !output
41 ! mwh, Qm, QmFreez, QmRain, & ! output
42 ! snowCalcSwitch, Qm_melt, Qm_freezState, Qm_rain, FreezMelt, &
43 ! FreezState, FreezStateVol, rainOnSnow, SnowDepth, mw_ind, &
44 ! dataOutLineSnow) !output
45
46 ! IMPLICIT NONE
47 ! ! INTEGER, PARAMETER::nsurf = 7
48 ! ! INTEGER, PARAMETER::PavSurf = 1
49 ! ! INTEGER, PARAMETER::BldgSurf = 2
50 ! ! INTEGER, PARAMETER::WaterSurf = 7
51 ! INTEGER, PARAMETER :: ncolumnsDataOutSnow_notime = ncolumnsDataOutSnow - 5
52 ! REAL(KIND(1D0)), PARAMETER :: waterDens = 999.8395 !Density of water in 0 cel deg
53
54 ! !These are input to the module
55 ! ! INTEGER, INTENT(in) :: SnowUse
56 ! INTEGER, INTENT(in) :: tstep
57 ! ! INTEGER,INTENT(in)::bldgsurf
58 ! ! INTEGER,INTENT(in)::nsurf
59 ! ! INTEGER,INTENT(in)::PavSurf
60 ! ! INTEGER,INTENT(in)::WaterSurf
61
62 ! REAL(KIND(1D0)), INTENT(in) :: lvS_J_kg
63 ! REAL(KIND(1D0)), INTENT(in) :: lv_J_kg
64 ! REAL(KIND(1D0)), INTENT(in) :: RadMeltFact
65 ! REAL(KIND(1D0)), INTENT(in) :: TempMeltFact
66 ! REAL(KIND(1D0)), INTENT(in) :: SnowAlbMax
67 ! REAL(KIND(1D0)), INTENT(in) :: SnowDensMax
68 ! REAL(KIND(1D0)), INTENT(in) :: SnowDensMin
69 ! REAL(KIND(1D0)), INTENT(in) :: Temp_C
70 ! REAL(KIND(1D0)), INTENT(in) :: Precip
71 ! REAL(KIND(1D0)), INTENT(in) :: PrecipLimit
72 ! REAL(KIND(1D0)), INTENT(in) :: PrecipLimitAlb
73 ! REAL(KIND(1D0)), INTENT(in) :: nsh_real
74 ! REAL(KIND(1D0)), INTENT(in) :: albedo_snow
75 ! REAL(KIND(1D0)), INTENT(in) :: tau_r
76 ! ! REAL(KIND(1d0)),INTENT(in)::waterdens
77
78 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: sfr_surf
79 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: Tsurf_ind
80 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: Tsurf_ind_snow
81 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: state_surf
82 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: qn1_ind_snow
83 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: kup_ind_snow
84 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowWater
85 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: deltaQi
86
87 ! !Input and output as this is updated in this subroutine
88 ! REAL(KIND(1D0)), INTENT(in) :: SnowAlb_in
89 ! REAL(KIND(1D0)), INTENT(in) :: SnowfallCum_in
90 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowPack_in
91 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowFrac_in
92 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowDens_in
93 ! REAL(KIND(1D0)), INTENT(out) :: SnowAlb_out
94 ! REAL(KIND(1D0)), INTENT(out) :: SnowfallCum_out
95 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: SnowPack_out
96 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: SnowFrac_out
97 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: SnowDens_out
98
99 ! REAL(KIND(1D0)) :: SnowAlb
100 ! REAL(KIND(1D0)) :: SnowfallCum
101 ! REAL(KIND(1D0)), DIMENSION(nsurf) :: SnowPack
102 ! REAL(KIND(1D0)), DIMENSION(nsurf) :: SnowFrac
103 ! REAL(KIND(1D0)), DIMENSION(nsurf) :: SnowDens
104
105 ! !Output:
106 ! REAL(KIND(1D0)), INTENT(out) :: mwh
107 ! REAL(KIND(1D0)) :: fwh
108 ! REAL(KIND(1D0)), INTENT(out) :: Qm
109 ! REAL(KIND(1D0)), INTENT(out) :: QmFreez
110 ! REAL(KIND(1D0)), INTENT(out) :: QmRain
111
112 ! ! REAL(KIND(1D0)), INTENT(out) :: veg_fr
113
114 ! INTEGER, DIMENSION(nsurf), INTENT(out) :: snowCalcSwitch
115
116 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: Qm_melt
117 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: Qm_freezState
118 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: Qm_rain
119 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: FreezMelt
120 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: FreezState
121 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: FreezStateVol
122 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: rainOnSnow
123 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: SnowDepth
124 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: mw_ind
125
126 ! REAL(KIND(1D0)), DIMENSION(ncolumnsDataOutSnow_notime), INTENT(out) :: dataOutLineSnow
127
128 ! SnowPack = SnowPack_in
129 ! SnowFrac = SnowFrac_in
130 ! SnowAlb = SnowAlb_in
131 ! SnowDens = SnowDens_in
132 ! SnowfallCum = SnowfallCum_in
133
134 ! ! IF (SnowUse == 1) THEN
135 ! SnowDens = update_snow_dens( &
136 ! tstep, SnowFrac, SnowDens, &
137 ! tau_r, SnowDensMax, SnowDensMin)
138
139 ! CALL MeltHeat( &
140 ! lvS_J_kg, lv_J_kg, tstep*1D0, RadMeltFact, TempMeltFact, & !input
141 ! SnowAlbMax, SnowDensMin, Temp_C, Precip, PrecipLimit, PrecipLimitAlb, &
142 ! nsh_real, sfr_surf, Tsurf_ind, state_surf, qn1_ind_snow, &
143 ! SnowWater, deltaQi, &
144 ! SnowPack, SnowFrac, SnowAlb, SnowDens, SnowfallCum, & !inout
145 ! mwh, fwh, Qm, QmFreez, QmRain, snowCalcSwitch, & !output
146 ! Qm_melt, Qm_freezState, Qm_rain, FreezMelt, FreezState, FreezStateVol, &
147 ! rainOnSnow, SnowDepth, mw_ind)
148
149 ! ! ELSE ! no snow calculation
150 ! ! mwh = 0
151 ! ! fwh = 0
152 ! ! Qm = 0
153 ! ! QmFreez = 0
154 ! ! QmRain = 0
155 ! ! SnowfallCum = 0
156 ! ! snowCalcSwitch = 0
157 ! ! Qm_melt = 0
158 ! ! Qm_freezState = 0
159 ! ! Qm_rain = 0
160 ! ! FreezMelt = 0
161 ! ! FreezState = 0
162 ! ! FreezStateVol = 0
163 ! ! rainOnSnow = 0
164 ! ! SnowDepth = 0
165 ! ! mw_ind = 0
166 ! ! SnowFrac = 0
167
168 ! ! END IF
169
170 ! ! ! update veg_fr
171 ! ! CALL veg_fr_snow( &
172 ! ! sfr_surf, SnowFrac, & !input
173 ! ! veg_fr) !output
174
175 ! SnowPack_out = SnowPack
176 ! SnowFrac_out = SnowFrac
177 ! SnowAlb_out = SnowAlb
178 ! SnowfallCum_out = SnowfallCum
179 ! SnowDens_out = SnowDens
180
181 ! ! pack output into one line
182 ! dataOutLineSnow = [ &
183 ! SnowPack_out(1:nsurf), mw_ind(1:nsurf), Qm_melt(1:nsurf), & !26
184 ! Qm_rain(1:nsurf), Qm_freezState(1:nsurf), SnowFrac_out(1:(nsurf - 1)), & !46
185 ! rainOnSnow(1:nsurf), & !53
186 ! qn1_ind_snow(1:nsurf), kup_ind_snow(1:nsurf), freezMelt(1:nsurf), & !74
187 ! SnowWater(1:nsurf), SnowDens_out(1:nsurf), & !88
188 ! snowDepth(1:nsurf), Tsurf_ind_snow(1:nsurf), &
189 ! albedo_snow]
190 ! ! dataOutLineSnow=set_nan(dataOutLineSnow)
191
192 ! END SUBROUTINE Snow_cal_MeltHeat
193
194 SUBROUTINE meltheat( &
195 lvS_J_kg, & !input
196 lv_J_kg, &
197 tstep_real, &
198 RadMeltFact, &
199 TempMeltFact, &
200 SnowAlbMax, &
201 SnowDensMin, &
202 Temp_C, &
203 Precip, &
204 PrecipLimit, &
205 PrecipLimitAlb, &
206 nsh_real, &
207 sfr_surf, &
208 Tsurf_ind, &
209 state_id, &
210 qn1_ind_snow, &
211 SnowWater, &
212 deltaQi, &
213 SnowPack, & !inoout
214 SnowFrac, &
215 SnowAlb, &
216 SnowDens, &
217 SnowfallCum, &
218 mwh, & !output
219 fwh, &
220 Qm, &
221 QmFreez, &
222 QmRain, &
223 snowCalcSwitch, &
224 Qm_melt, &
225 Qm_freezState, &
226 Qm_rain, &
227 FreezMelt, &
228 FreezState, &
229 FreezStateVol, &
230 rainOnSnow, &
231 SnowDepth, &
232 mw_ind)
233
234 IMPLICIT NONE
235
236 !These are input to the module
237 ! INTEGER, INTENT(in)::bldgsurf
238 ! INTEGER, INTENT(in)::nsurf
239 ! INTEGER, INTENT(in)::PavSurf
240 ! INTEGER, INTENT(in)::WaterSurf
241 REAL(KIND(1D0)), PARAMETER :: waterDens = 999.8395 !Density of water in 0 cel deg
242
243 REAL(KIND(1D0)), INTENT(in) :: lvS_J_kg
244 REAL(KIND(1D0)), INTENT(in) :: lv_J_kg
245 REAL(KIND(1D0)), INTENT(in) :: tstep_real
246 REAL(KIND(1D0)), INTENT(in) :: RadMeltFact
247 REAL(KIND(1D0)), INTENT(in) :: TempMeltFact
248 REAL(KIND(1D0)), INTENT(in) :: SnowAlbMax
249 REAL(KIND(1D0)), INTENT(in) :: SnowDensMin
250 REAL(KIND(1D0)), INTENT(in) :: Temp_C
251 REAL(KIND(1D0)), INTENT(in) :: Precip
252 REAL(KIND(1D0)), INTENT(in) :: PrecipLimit
253 REAL(KIND(1D0)), INTENT(in) :: PrecipLimitAlb
254 REAL(KIND(1D0)), INTENT(in) :: nsh_real
255
256 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: sfr_surf
257 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: Tsurf_ind
258 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: state_id
259 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: qn1_ind_snow
260 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowWater
261 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: deltaQi
262
263 !Input and output as this is updated in this subroutine
264 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: SnowPack
265 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: SnowFrac
266 REAL(KIND(1D0)), INTENT(inout) :: SnowAlb
267 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: SnowDens
268 REAL(KIND(1D0)), INTENT(inout) :: SnowfallCum
269
270 !Output:
271 REAL(KIND(1D0)), INTENT(out) :: mwh
272 REAL(KIND(1D0)), INTENT(out) :: fwh
273 REAL(KIND(1D0)), INTENT(out) :: Qm
274 REAL(KIND(1D0)), INTENT(out) :: QmFreez
275 REAL(KIND(1D0)), INTENT(out) :: QmRain
276
277 !Output, dimension nsurf
278 INTEGER, DIMENSION(nsurf), INTENT(out) :: snowCalcSwitch
279
280 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: Qm_melt
281 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: Qm_freezState
282 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: Qm_rain
283 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: FreezMelt
284 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: FreezState
285 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: FreezStateVol
286 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: rainOnSnow
287 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: SnowDepth
288 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: mw_ind
289
290 ! local variables:
291 REAL(KIND(1D0)) :: AdjMeltFact
292 REAL(KIND(1D0)) :: Watfreeze
293
294 REAL(KIND(1D0)), PARAMETER :: cw = 4190 !,ci=2090 !Specific heat capacity of water
295
296 INTEGER :: is, xx
297
298 !Initialize snow variables
299 mwh = 0 !Initialize snow melt and heat related to snowmelt
300 fwh = 0
301 qm = 0
302 qmfreez = 0
303 qmrain = 0
304 snowcalcswitch = 0
305 qm_melt = 0
306 qm_freezstate = 0
307 qm_rain = 0
308 freezmelt = 0
309 freezstate = 0
310 freezstatevol = 0
311 rainonsnow = 0
312 snowdepth = 0
313 mw_ind = 0
314
315 !===dummy calculations===
316 ! xx = bldgsurf
317 ! xx = PavSurf
318 !===dummy calculations end===
319
320 !=========================================================================================
321 DO is = 1, nsurf !Go each surface type through
322 IF (sfr_surf(is) /= 0) THEN !If surface type existing,
323
324 IF (snowpack(is) > 0) THEN !If SnowPack existing, calculate meltwater related water flows
325
326 snowdepth(is) = (snowpack(is)/1000)*waterdens/snowdens(is) !Snow depth in m
327
328 !Calculate meltwater related water flows with hourly degree-day method.
329
330 !These are for snow melting
331 IF (temp_c >= 0) THEN
332 IF (qn1_ind_snow(is) < 0) THEN
333 mw_ind(is) = tempmeltfact*temp_c !(mm C−1 h−1)*(C) = in mm h-1
334 ELSE
335 mw_ind(is) = radmeltfact*(qn1_ind_snow(is)) !(mm m2 W−1 h−1)*(W m-2)= mm h-1 ??
336 END IF
337
338 ELSE !Freezing equations
339 adjmeltfact = 1 !Relationship between the temperature melt and freezing factors
340 mw_ind(is) = tempmeltfact*temp_c*adjmeltfact ! in mm h-1
341 END IF
342 !Previous equation give the hourly values, divide these with the timestep number
343 mw_ind(is) = mw_ind(is)/nsh_real
344
345 IF (mw_ind(is) > snowpack(is)) mw_ind(is) = snowpack(is) !Limited by the previous timestep SnowPack
346
347 !-----------------------------------------------------
348 ! Heat consumed to snowmelt/refreezing within Tstep.
349 ! Converted from mm nsh-1 to mm nsh-1 and to m s-1
350 qm_melt(is) = waterdens*((mw_ind(is)/tstep_real)/1000)*(lvs_j_kg - lv_j_kg)
351
352 !If melt is negative this means freezing water in the SnowPack
353 IF (mw_ind(is) < 0) THEN
354
355 freezmelt(is) = -mw_ind(is) !Save this to variable FreezMelt
356 mw_ind(is) = 0
357
358 !Freezing water cannot exceed meltwater store
359 IF (freezmelt(is) > snowwater(is)) freezmelt(is) = snowwater(is)
360
361 !Recalculate melt related energy
362 qm_melt(is) = waterdens*((-freezmelt(is)/tstep_real)/1000)*(lvs_j_kg - lv_j_kg)
363 END IF
364
365 !-----------------------------------------------------
366 ! If air temperature is above zero, precipitation causes advective heat to the
367 ! SnowPack. Eq (23) in Sun et al., 1999
368 ! Calculation done at resolution of the model timestep
369 IF (temp_c >= preciplimit .AND. precip > 0) THEN
370 qm_rain(is) = waterdens*cw*(temp_c - preciplimit)*(precip*0.001/tstep_real) !in W m-2
371 IF (qm_rain(is) < 0) THEN !Can only be positive
372 qm_rain(is) = 0
373 ELSE
374 rainonsnow(is) = precip !Save information on the rain on snow event
375 END IF
376 END IF
377
378 END IF !End if SnowPack
379
380 !=================================================================
381
382 !Freeze surface water state_id if cold enough.
383 IF (tsurf_ind(is) < 0 .AND. state_id(is) > 0) THEN
384
385 snowcalcswitch(is) = 1 !If water on ground this forms ice and snow calculations are made
386
387 !Other surfaces than water treated first
388 IF (is /= watersurf) THEN
389
390 !FreezState(is) = state_id(is)
391 !Previously all state_id could freeze in 5-min timestep. Now we calculate how much water
392 !can freeze in a timestep based on the same temperature freezing fraction.
393 freezstate(is) = -tempmeltfact*tsurf_ind(is)/nsh_real
394
395 !The amount of freezing water cannot be greater than the surface state_id
396 IF (freezstate(is) > state_id(is)) freezstate(is) = state_id(is)
397
398 IF (snowpack(is) == 0 .OR. snowfrac(is) == 0) THEN !SnowPack forms
399 freezstatevol(is) = freezstate(is)
400 ELSE !There is snow already on ground
401 freezstatevol(is) = freezstate(is)*(1 - snowfrac(is))/snowfrac(is)
402 END IF
403
404 ! If the amount of freezing water is very small and there is state_id left to the ground
405 ! no freezing of water will take place
406 IF (freezstatevol(is) < 0.00000000001 .AND. freezstate(is) < state_id(is)) THEN
407 freezstate(is) = 0
408 freezstatevol(is) = 0
409 END IF
410
411 !Calculate the heat exchange in W m-2
412 qm_freezstate(is) = -waterdens*(freezstate(is)/tstep_real/1000)*(lvs_j_kg - lv_j_kg)
413
414 !Water surface separately
415 ELSE
416 !Calculate average value how much water can freeze above the water areas
417 !Equation is -hA(T-T0) = rhoV(Cp+dT +Lf) in 5-min timestep
418 !h=convective heat trasnfer,A, area of water,rwo water density,V volume, dT temperature difference
419 !before and end of the 5-min period. dT equals zero, h=100 and when multiplied with Area, the equation
420 !simplyfies to the this. LJ 14 July 2015
421 watfreeze = 100*(0 - temp_c)/(waterdens*(lvs_j_kg - lv_j_kg))
422 freezstate(is) = watfreeze
423 qm_freezstate(is) = -waterdens*(watfreeze/tstep_real/1000)*(lvs_j_kg - lv_j_kg)
424 END IF
425
426 END IF
427
428 !======================================================================
429 ! Define if any snowmelt calculations are made: SnowPack existing,
430 ! freezing occuring on ground or from precip
431 IF (is /= watersurf) THEN
432 IF (snowpack(is) > 0 .OR. (precip > 0 .AND. tsurf_ind(is) < 0)) THEN
433 snowcalcswitch(is) = 1
434 END IF
435 ELSE !Water surface separately
436 IF (snowpack(watersurf) > 0 .OR. freezstate(watersurf) > 0) THEN
437 snowcalcswitch(watersurf) = 1
438 END IF
439 END IF
440
441 !Update snow density of each surface
442 IF (precip > 0 .AND. tsurf_ind(is) < 0 .AND. snowpack(is) > 0) THEN
443 snowdens(is) = snowdens(is)*snowpack(is)/(snowpack(is) + precip) + snowdensmin*precip/(snowpack(is) + precip)
444 END IF
445
446 !Weighted variables for the whole area
447 mwh = mwh + mw_ind(is)*sfr_surf(is)*snowfrac(is) !Snowmelt
448 fwh = fwh + freezmelt(is)*sfr_surf(is)*snowfrac(is) !Freezing water
449 qm = qm + qm_melt(is)*sfr_surf(is)*snowfrac(is) !Energy consumed to the melt/freezing.
450 qmrain = qmrain + qm_rain(is)*sfr_surf(is)*snowfrac(is) !Rain on snow
451 qmfreez = qmfreez + deltaqi(is)*sfr_surf(is)*snowfrac(is) + qm_freezstate(is)*sfr_surf(is)*(1 - snowfrac(is)) !Freezing water
452 END IF
453
454 END DO !End surface type
455
456 !Update snow albedo to its maximum value if precipitation exists
457 IF (precip > 0 .AND. sum(snowpack) > 0 .AND. temp_c < 0) THEN
458
459 snowfallcum = snowfallcum + precip
460
461 IF (snowfallcum > preciplimitalb) THEN
462
463 snowalb = snowalbmax
464 snowfallcum = 0
465 END IF
466 ELSE
467
468 snowfallcum = 0
469 END IF
470
471 END SUBROUTINE meltheat
472
473 !===============================================================================================
474 !===============================================================================================
475 SUBROUTINE snowcalc( &
476 tstep, imin, it, dectime, is, & !input
477 snowCalcSwitch, & !input
478 EvapMethod, CRWmin, CRWmax, nsh_real, lvS_J_kg, avdens, &
479 avRh, Press_hPa, Temp_C, RAsnow, psyc_hPa, avcp, sIce_hPa, &
480 PervFraction, vegfraction, addimpervious, &
481 vpd_hPa, qn_e, s_hPa, ResistSurf, RA, rb, tlv, snowdensmin, SnowProf_24hr, precip, &
482 PipeCapacity, RunoffToWater, &
483 addVeg, SnowLimPaved, SnowLimBldg, FlowChange, drain, &
484 WetThresh, stateOld, mw_ind, SoilStoreCap, rainonsnow, &
485 freezmelt, freezstate, freezstatevol, &
486 Qm_Melt, Qm_rain, Tsurf_ind, sfr_surf, dayofWeek_id, StoreDrainPrm, SnowPackLimit, &
487 AddWater, addwaterrunoff, &
488 soilstore_id, SnowPack, SurplusEvap, & !inout
489 SnowFrac, SnowWater, iceFrac, SnowDens, &
490 runoffAGimpervious, runoffAGveg, surplusWaterBody, &
491 ev_tot, qe_tot, runoff_tot, surf_chang_tot, chSnow_tot, & ! output
492 rss_surf, & ! output
493 runoff_snowfree, chang, changSnow, SnowToSurf, state_id, ev_snow, &
494 SnowRemoval, swe, &
495 runoffPipes, mwstore, runoffwaterbody)
496
497 !Calculation of snow and water balance on 5 min timestep. Treats snowfree and snow covered
498 !areas separately. Weighting is taken into account in the overall values.
499 !Last modified:
500 ! LJ in 6 May 2015 - Modified to run with timestep
501 ! HCW 06 Mar 2015 - Unused variable 'i' removed.
502 ! HCW 26 Jan 2015 - Added weekday/weekend option for snow clearing profiles
503 ! LJ in 24 May 2013
504 !========================================================================
506
507 IMPLICIT NONE
508 ! INTEGER, PARAMETER::nsurf = 7! number of surface types
509 ! INTEGER, PARAMETER::PavSurf = 1 !New surface classes: Grass = 5th/7 surfaces
510 ! INTEGER, PARAMETER::BldgSurf = 2 !New surface classes: Grass = 5th/7 surfaces
511 ! INTEGER, PARAMETER::ConifSurf = 3 !New surface classes: Grass = 5th/7 surfaces
512 ! INTEGER,PARAMETER::DecidSurf = 4 !New surface classes: Grass = 5th/7 surfaces
513 ! INTEGER,PARAMETER::GrassSurf = 5
514 ! INTEGER, PARAMETER::BSoilSurf = 6!New surface classes: Grass = 5th/7 surfaces
515 ! INTEGER, PARAMETER::WaterSurf = 7
516
517 INTEGER, PARAMETER :: snowfractionchoice = 2 ! this PARAMETER is used all through the model
518 REAL(KIND(1D0)), PARAMETER :: waterDens = 999.8395 !Density of water in 0 cel deg
519
520 ! INTEGER,INTENT(in)::id
521 ! INTEGER,INTENT(in)::nsurf
522 INTEGER, INTENT(in) :: tstep
523 INTEGER, INTENT(in) :: imin
524 INTEGER, INTENT(in) :: it
525 INTEGER, INTENT(in) :: is
526
527 INTEGER, DIMENSION(nsurf), INTENT(in) :: snowCalcSwitch
528
529 ! INTEGER,INTENT(in)::ConifSurf
530 ! INTEGER,INTENT(in)::BSoilSurf
531 ! INTEGER,INTENT(in)::BldgSurf
532 ! INTEGER,INTENT(in)::PavSurf
533 ! INTEGER,INTENT(in)::WaterSurf
534 INTEGER, INTENT(in) :: EvapMethod !Evaporation calculated according to Rutter (1) or Shuttleworth (2)
535 INTEGER, DIMENSION(3), INTENT(in) :: DayofWeek_id
536
537 REAL(KIND(1D0)), INTENT(in) :: dectime
538 REAL(KIND(1D0)), INTENT(in) :: CRWmin
539 REAL(KIND(1D0)), INTENT(in) :: CRWmax
540 REAL(KIND(1D0)), INTENT(in) :: nsh_real
541 REAL(KIND(1D0)), INTENT(in) :: lvS_J_kg
542 ! REAL(KIND(1d0)), INTENT(in)::lv_j_kg
543 REAL(KIND(1D0)), INTENT(in) :: avdens
544 REAL(KIND(1D0)), INTENT(in) :: vpd_hPa ! vapour pressure deficit [hPa]
545 REAL(KIND(1D0)), INTENT(in) :: qn_e !net available energy for evaporation
546 REAL(KIND(1D0)), INTENT(in) :: avRh
547 REAL(KIND(1D0)), INTENT(in) :: Press_hPa
548 REAL(KIND(1D0)), INTENT(in) :: Temp_C
549 REAL(KIND(1D0)), INTENT(in) :: RAsnow
550 REAL(KIND(1D0)), INTENT(in) :: psyc_hPa
551 REAL(KIND(1D0)), INTENT(in) :: avcp
552 REAL(KIND(1D0)), INTENT(in) :: sIce_hPa
553 REAL(KIND(1D0)), INTENT(in) :: PervFraction
554 REAL(KIND(1D0)), INTENT(in) :: vegfraction
555 REAL(KIND(1D0)), INTENT(in) :: addimpervious
556 ! REAL(KIND(1d0)),INTENT(in)::numPM
557 REAL(KIND(1D0)), INTENT(in) :: s_hPa
558 REAL(KIND(1D0)), INTENT(in) :: ResistSurf
559 ! REAL(KIND(1d0)),INTENT(in)::sp
560 REAL(KIND(1D0)), INTENT(in) :: RA
561 REAL(KIND(1D0)), INTENT(in) :: rb
562 REAL(KIND(1D0)), INTENT(in) :: tlv
563 REAL(KIND(1D0)), INTENT(in) :: snowdensmin
564 REAL(KIND(1D0)), INTENT(in) :: precip
565 REAL(KIND(1D0)), INTENT(in) :: PipeCapacity
566 REAL(KIND(1D0)), INTENT(in) :: RunoffToWater
567 REAL(KIND(1D0)), INTENT(in) :: addVeg
568 REAL(KIND(1D0)), INTENT(in) :: SnowLimPaved
569 REAL(KIND(1D0)), INTENT(in) :: SnowLimBldg
570 REAL(KIND(1D0)), INTENT(in) :: FlowChange
571
572 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: drain
573 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: WetThresh
574 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: stateOld
575 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: mw_ind
576 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SoilStoreCap
577 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: rainonsnow
578 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: freezmelt
579 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: freezstate
580 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: freezstatevol
581 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: Qm_Melt
582 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: Qm_rain
583 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: Tsurf_ind
584 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: sfr_surf
585 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowPackLimit
586 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: AddWater
587 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: addwaterrunoff
588 REAL(KIND(1D0)), DIMENSION(6, nsurf), INTENT(in) :: StoreDrainPrm
589 REAL(KIND(1D0)), DIMENSION(0:23, 2), INTENT(in) :: SnowProf_24hr
590
591 !Updated status: input and output
592 REAL(KIND(1D0)), INTENT(inout) :: runoffAGveg
593 REAL(KIND(1D0)), INTENT(inout) :: runoffAGimpervious
594 REAL(KIND(1D0)), INTENT(inout) :: surplusWaterBody
595
596 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: soilstore_id
597 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: SnowPack
598 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: SnowFrac
599 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: SnowWater
600 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: iceFrac
601 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(inout) :: SnowDens
602 REAL(KIND(1D0)), DIMENSION(2), INTENT(inout) :: SurplusEvap
603
604 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: rss_surf
605 REAL(KIND(1D0)), DIMENSION(nsurf) :: runoffSnow_surf !Initialize for runoff caused by snowmelting
606 REAL(KIND(1D0)), DIMENSION(nsurf) :: runoff_snowfree
607 ! REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: runoffSoil
608 REAL(KIND(1D0)), DIMENSION(nsurf) :: chang
609 REAL(KIND(1D0)), DIMENSION(nsurf) :: changSnow
610 REAL(KIND(1D0)), DIMENSION(nsurf) :: SnowToSurf
611 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: state_id
612 REAL(KIND(1D0)), DIMENSION(nsurf) :: SnowDepth
613 REAL(KIND(1D0)), DIMENSION(nsurf) :: ev_snow
614 REAL(KIND(1D0)), DIMENSION(2), INTENT(out) :: SnowRemoval
615
616 REAL(KIND(1D0)), INTENT(out) :: swe
617 REAL(KIND(1D0)) :: ev_snowfree
618 REAL(KIND(1D0)), INTENT(out) :: ev_tot
619 REAL(KIND(1D0)), INTENT(out) :: chSnow_tot
620 REAL(KIND(1D0)), INTENT(out) :: qe_tot
621 REAL(KIND(1D0)), INTENT(out) :: runoff_tot
622 REAL(KIND(1D0)), INTENT(out) :: surf_chang_tot
623 REAL(KIND(1D0)), INTENT(out) :: runoffPipes
624 REAL(KIND(1D0)), INTENT(out) :: mwstore
625 REAL(KIND(1D0)), INTENT(out) :: runoffwaterbody
626
627 REAL(KIND(1D0)) :: qe
628
629 ! REAL(KIND(1d0))::Evap_SUEWS_Snow
630 REAL(KIND(1D0)) :: MeltExcess !Excess melt water that needs to leave SnowPack
631 REAL(KIND(1D0)) :: snowTotInit
632 REAL(KIND(1D0)) :: EvPart
633 REAL(KIND(1D0)) :: runoffTest
634 REAL(KIND(1D0)) :: snowFracFresh1 !Snow fraction for newly formed SnowPack
635 REAL(KIND(1D0)) :: snowFracFresh2 !Snow fraction for newly formed SnowPack from state_id only
636 REAL(KIND(1D0)) :: snowFracOld
637 REAL(KIND(1D0)) :: WaterHoldCapFrac
638 REAL(KIND(1D0)) :: FWC !Water holding capacity of snow in mm
639 REAL(KIND(1D0)) :: tlv_sub
640 ! REAL(KIND(1d0)):: SnowDepletionCurve
641
642 INTEGER :: iu !1=weekday OR 2=weekend
643 REAL(KIND(1D0)), PARAMETER :: IPThreshold_mmhr = 10 !Threshold for intense precipitation [mm hr-1]
644
645 REAL(KIND(1D0)), DIMENSION(7) :: capStore ! current storage capacity [mm]
646
647 !========================================================================
648 !Initialize variables for the calculation of water storages and evaporation
649 ev_tot = 0
650 qe_tot = 0
651 runoff_tot = 0
652 surf_chang_tot = 0
653
654 !swe = 0
655 chsnow_tot = 0
656 !runoffPipes = 0
657 !mwstore = 0
658 !runoffwaterbody = 0
659 rss_surf = 0
660 state_id = stateold
661 snowdepth = 0
662 ev_snow = 0
663 !SnowRemoval = 0
664 tlv_sub = 0
665
666 ! Use weekday or weekend snow clearing profile
667 iu = 1 !Set to 1=weekday
668 IF (dayofweek_id(1) == 1 .OR. dayofweek_id(1) == 7) iu = 2 !Set to 2=weekend
669
670 !write(*,*) is
671 runoffsnow_surf(is) = 0 !Initialize for runoff caused by snowmelting
672 runoff_snowfree(is) = 0
673 ! runoffSoil(is) = 0
674 chang(is) = 0
675 changsnow(is) = 0
676 runofftest = 0
677 snowtosurf(is) = 0
678 evpart = 0
679 ev_snowfree = 0
680 snowfracfresh1 = 0
681 snowfracfresh2 = 0
682 snowfracold = 0
683
684 !Initial SnowPack + meltwater in it
685 snowtotinit = snowpack(is) + snowwater(is)
686
687 !Calculate water holding capacity (Jin et al. 1999)
688 IF (snowdens(is) >= 200) THEN
689 waterholdcapfrac = crwmin
690 ELSE
691 waterholdcapfrac = crwmin + (crwmax - crwmin)*(200 - snowdens(is))/200
692 END IF
693
694 !======================================================================
695 ! Calculate evaporation from SnowPack and snow free surfaces (in mm)
696 ! IF (SnowFrac(is)<1) CALL Evap_SUEWS !ev and qe for snow free surface out
697 capstore(is) = storedrainprm(6, is)
698 IF (snowfrac(is) < 1) CALL cal_evap( &
699 evapmethod, state_id(is), wetthresh(is), capstore(is), & !input
700 vpd_hpa, avdens, avcp, qn_e, s_hpa, psyc_hpa, resistsurf, ra, rb, tlv, &
701 rss_surf(is), ev_snowfree, qe) !output
702
703 IF (snowfrac(is) > 0 .AND. snowcalcswitch(is) > 0) THEN
704 CALL evap_suews_snow(qm_melt(is), qm_rain(is), lvs_j_kg, avdens, avrh, press_hpa, temp_c, rasnow, &
705 psyc_hpa, tstep, avcp, sice_hpa, dectime, ev_snow(is), tlv_sub)
706 END IF
707
708 !If not enough water for evaporation in impervious surfaces,
709 !evaporation is taken from pervious surfaces
710 IF (is > 2) THEN
711 IF (pervfraction /= 0) THEN
712 evpart = (surplusevap(pavsurf)*sfr_surf(pavsurf) + surplusevap(bldgsurf)*sfr_surf(bldgsurf))/pervfraction
713 END IF
714 END IF
715
716 !============================================================================
717 !Water surface is treated separately
718 IF (is == watersurf .AND. sfr_surf(watersurf) > 0) GO TO 606
719
720 !The calculations are divided into 2 main parts
721 ! 1) Surface is fully covered with snow at the beginning of the time step
722 ! 2) Surface is not fully covered with snow but rather part is snow free OR
723 ! surface not orginally covered with snow, but the snow forms at the current timestep
724
725 !1)------------------------------------------------------------------
726 ! ------------------------------------------------------------------
727 IF (snowcalcswitch(is) > 0) THEN
728 IF (snowpack(is) > 0 .AND. snowfrac(is) == 1) THEN
729
730 ev_snow(is) = ev_snow(is) + evpart !Evaporation surplus
731
732 !(Snowfall per interval+freezing of melt water and surface state_id) - (meltwater+evaporation from SnowPack)
733 changsnow(is) = (precip + freezmelt(is)) - (mw_ind(is) + ev_snow(is)) !Calculate change in SnowPack (in mm)
734
735 !If rain on snow event, add this water to SnowWater
736 IF (rainonsnow(is) > 0) THEN
737 changsnow(is) = changsnow(is) - precip
738 snowwater(is) = snowwater(is) + rainonsnow(is)
739 END IF
740
741 snowpack(is) = snowpack(is) + changsnow(is) !Update SnowPack
742
743 !---------If SnowPack exists after the state_id calculations
744 IF (snowpack(is) > 0) THEN
745
746 !Add melted water to meltstore and freeze water according to freezMelt(is)
747 snowwater(is) = snowwater(is) + mw_ind(is) - freezmelt(is)
748
749 !Calculate water holding capacity (FWC: Valeo and Ho, 2004) of the SnowPack
750 fwc = waterholdcapfrac*snowpack(is)
751
752 !If FWC is exceeded, excess meltwater (MeltExcess) will leave from the SnowPack
753 IF (snowwater(is) >= fwc) THEN
754 meltexcess = 0 !Initialize the excess meltwater
755 meltexcess = snowwater(is) - fwc !Calculate the exceess water
756 snowwater(is) = fwc !Update the SnowWater to the maximum it can hold
757 runoffsnow_surf(is) = runoffsnow_surf(is) + meltexcess
758 END IF
759
760 !At the end of the hour calculate possible snow removal
761 IF (snowprof_24hr(it, iu) == 1 .AND. is < 3 .AND. (imin == (nsh_real - 1)/nsh_real*60)) &
762 CALL snow_removal( &
763 is, &
764 snowfrac, sfr_surf, &
765 snowpack, snowremoval, &
766 snowlimpaved, snowlimbldg)
767 !----------If SnowPack is negative, it melts at this timestep
768 ELSEIF (snowpack(is) < 0) THEN
769
770 !If freezing meltwater inside this timestep, remove it from the SnowWater
771 snowwater(is) = snowwater(is) - freezmelt(is) + mw_ind(is) + snowpack(is)
772 snowpack(is) = 0.0 !Set the snow pack and snow
773 snowfracold = 1
774 snowfrac(is) = 0
775 snowdens(is) = 0
776
777 IF (snowwater(is) < 0) THEN !Not enough water in the meltwater store,
778 ev_snow(is) = ev_snow(is) + snowwater(is) !QUESTION: evaporation from snow is decreased?
779 IF (ev_snow(is) < 0) ev_snow(is) = 0
780 changsnow(is) = changsnow(is) + snowwater(is)
781 snowwater(is) = 0
782 ELSE
783 chang(is) = snowwater(is) !Meltwater goes to surface state_id as no snow exists anymore
784 state_id(is) = state_id(is) + chang(is)
785 snowwater(is) = 0
786 END IF
787 END IF !SnowPack negative or positive
788
789 !2)------Surface not fully covered with snow-------------------------------------------
790 ! ------------------------------------------------------------------------------------
791 ELSEIF (snowfrac(is) < 1) THEN
792
793 !Snow calculations: SnowPack can either exist or form at the current timestep
794 IF (snowpack(is) > 0) THEN
795 ev_snow(is) = ev_snow(is) + evpart !Evaporation surplus
796
797 !----SnowPack water balance for the whole surface area. In reality snow depth = SnowPack/SnowFrac(is)
798 !(Snowfall per interval+freezing of melt water and surface state_id) - (meltwater+evaporation from SnowPack)
799 changsnow(is) = (precip + freezmelt(is) + freezstatevol(is)) - (mw_ind(is) + ev_snow(is)) !Calculate change in SnowPack (in mm)
800
801 !If rain on snow event, add this water to SnowWater
802 IF (rainonsnow(is) > 0) THEN
803 changsnow(is) = changsnow(is) - precip
804 snowwater(is) = snowwater(is) + rainonsnow(is)
805 END IF
806 snowpack(is) = snowpack(is) + changsnow(is)
807
808 !The fraction of snow will update when:
809 !a) Surface state_id is dry but precipitation occurs =1
810 !b) There is both precipitation and all surface state_id freezes =1
811 !c) No precipitation but all state_id freezes at a single timestep =2
812 !d) Part of the surface freezes
813 IF (precip > 0 .AND. freezstate(is) == state_id(is)) THEN !both a) and b)
814 snowfracfresh1 = 1
815 ELSEIF (precip == 0 .AND. freezstate(is) > 0 .AND. freezstate(is) == state_id(is)) THEN
816 snowfracfresh1 = 1
817
818 !snowFracFresh1=SnowDepletionCurve(is,SnowPack(is),SnowPackLimit(is))
819 !if (snowFracFresh1<0.001) snowFracFresh1=0.001
820 ELSEIF (freezstate(is) > 0 .AND. freezstate(is) < state_id(is)) THEN !This if not all water freezes
821 snowfracfresh1 = 0.95 !Now this fraction set to something close to one. Should be improved in the future at some point
822 !if (is==1)then
823 ! write(*,*) id,it,imin,SnowFrac(is),FreezState(is),state_id(is)
824 ! pause
825 !endif
826 END IF
827
828 !SnowPack can also form at the current timestep (2). If this forms purely from snowfall or/and all water at surface freezes,
829 !the whole surface will be covered with snow. If there is water on ground this snowfall can immediately melt
830 !and in this case the snow fraction is not necessarily 1 but its information is saved to snowFracFresh that
831 !is taken into account in snow fraction after calculation of state_id.
832 ELSEIF (snowpack(is) == 0 .AND. tsurf_ind(is) < 0) THEN
833
834 !The fraction of snow will get a value of 1 (ie full snow cover):
835 !Surface state_id is dry but precipitation occurs, no precipitation but all state_id freezes at a single timestep,
836 !There is both precipitation and all surface state_id freezes
837 IF ((precip > 0 .AND. state_id(is) == 0) .OR. (precip == 0 .AND. freezstate(is) == state_id(is)) .OR. &
838 (precip > 0 .AND. freezstate(is) == state_id(is))) THEN
839
840 !ev=ev+EvPart
841 changsnow(is) = precip + freezstatevol(is)
842 snowpack(is) = snowpack(is) + changsnow(is) !Update SnowPack
843
844 snowfracfresh1 = 1
845 icefrac(is) = freezstate(is)/(freezstate(is) + precip)
846 snowdens(is) = snowdensmin
847 END IF
848
849 IF (freezstate(is) > 0 .AND. freezstate(is) < state_id(is)) THEN
850
851 changsnow(is) = precip + freezstatevol(is)
852 snowpack(is) = snowpack(is) + changsnow(is) !Update SnowPack
853 snowfracfresh2 = 0.95 !Now this fraction set to something close to one. Should be improved in the future at some point
854
855 !snowFracFresh2=SnowDepletionCurve(is,SnowPack(is),SnowPackLimit(is))
856 !if (snowFracFresh2<0.001) snowFracFresh2=0.001
857 icefrac(is) = 1
858 snowdens(is) = snowdensmin
859 !write(*,*) 2,is,id,it,imin,SnowFrac(is),FreezState(is),state_id(is),state_id(is)+Precip
860 !pause
861
862 END IF
863 END IF
864
865 !---------If SnowPack exists after the state_id calculations
866 IF (snowpack(is) > 0) THEN
867
868 !Add melted water to meltstore and freeze water according to freezMelt(is)
869 snowwater(is) = snowwater(is) + mw_ind(is) - freezmelt(is)
870
871 !Calculate water holding capacity (FWC: Valeo and Ho, 2004) of the SnowPack
872 fwc = waterholdcapfrac*snowpack(is)
873
874 !If FWC is exceeded, excess meltwater (MeltExcess) will leave from the SnowPack
875 IF (snowwater(is) >= fwc) THEN
876 meltexcess = 0 !Initialize the excess meltwater
877 meltexcess = snowwater(is) - fwc !Calculate the exceess water
878 snowwater(is) = fwc !Update the SnowWater to the maximum it can hold
879
880 !If the fraction of snow is greater than 0.8 or if the surface is is buildings,
881 !the excess water will directly go to runoff. Otherwise it will flow to the
882 !snow free area via SnowToSurf(is)
883 IF ((snowfrac(is) > 0.9 .AND. is /= bldgsurf) .OR. (is == bldgsurf)) THEN
884 runoffsnow_surf(is) = runoffsnow_surf(is) + meltexcess
885 ELSE
886 snowtosurf(is) = snowtosurf(is) + meltexcess*snowfrac(is)/(1 - snowfrac(is))
887 END IF
888 END IF
889
890 !At the end of the hour calculate possible snow removal
891 IF (snowprof_24hr(it, iu) == 1 .AND. is < 3 .AND. (imin == (nsh_real - 1)/nsh_real*60)) &
892 CALL snow_removal( &
893 is, &
894 snowfrac, sfr_surf, &
895 snowpack, snowremoval, &
896 snowlimpaved, snowlimbldg)
897
898 !----------If SnowPack is negative, it melts at this timestep
899 ELSEIF (snowpack(is) < 0) THEN
900
901 !If freezing meltwater inside this timestep, remove it from the SnowWater
902 snowwater(is) = snowwater(is) - freezmelt(is) + mw_ind(is) + snowpack(is)
903
904 snowpack(is) = 0.0 !Set the snow pack and snow
905 snowfracfresh1 = 0
906 snowfracfresh2 = 0
907 snowdens(is) = 0
908
909 IF (snowwater(is) < 0) THEN !Not enough water in the meltwater store,
910 ev_snow(is) = ev_snow(is) + snowwater(is) !QUESTION: evaporation from snow is decreased.?
911 IF (ev_snow(is) < 0) ev_snow(is) = 0
912 changsnow(is) = changsnow(is) + snowwater(is)
913 snowwater(is) = 0
914 ELSE
915 snowtosurf(is) = snowtosurf(is) + snowwater(is)*snowfrac(is)/(1 - snowfrac(is))
916 snowwater(is) = 0
917 END IF
918 END IF !SnowPack negative or positive
919
920 !--------
921 !Next the snow free surface (3). Calculations only done if snowfraction is smaller than 1
922 IF ((is == pavsurf .OR. is == bldgsurf) .AND. snowfrac(is) < 1) THEN !Impervious surfaces (paved, buildings)
923
924 !Surface store update. If precipitation is greater than the threshold, the exceeding water
925 !goes directly to runoff
926 IF (precip > ipthreshold_mmhr/nsh_real) THEN
927 !runoff = runoff + (precipitation+water from the snow surface+water from other surfaces-the thereshold limit)
928 runoff_snowfree(is) = runoff_snowfree(is) + (precip + snowtosurf(is) + addwater(is) - ipthreshold_mmhr/nsh_real)
929 chang(is) = ipthreshold_mmhr/nsh_real - (drain(is) + ev_snowfree + freezstate(is))
930 ELSE
931 !Add precip and water from other surfaces and remove drainage, evap and freezing of state_id
932 chang(is) = precip + snowtosurf(is) + addwater(is) - (drain(is) + ev_snowfree + freezstate(is))
933 END IF
934
935 state_id(is) = state_id(is) + chang(is) !Change in state_id (for whole surface area areasfr(is))
936
937 !Add water from impervious grids
938 ! Check sfr_surf/=0 added HCW 08 Dec 2015
939 IF (is == pavsurf .AND. sfr_surf(pavsurf) > 0) state_id(is) = state_id(is) + (addimpervious)/sfr_surf(pavsurf)
940
941 runoff_snowfree(is) = runoff_snowfree(is) + drain(is)*addwaterrunoff(is) !Drainage (not flowing to other surfaces) goes to runoff
942
943 IF (state_id(is) < 0.0) THEN !Surface state_id cannot be negative
944 surplusevap(is) = abs(state_id(is)) !take evaporation from other surfaces in mm
945 ev_snowfree = ev_snowfree - surplusevap(is)
946 state_id(is) = 0.0
947 END IF
948
949 ELSEIF (is >= 3 .AND. snowfrac(is) < 1) THEN ! Pervious surfaces (conif, decid, grass unirr, grass irr)
950
951 ev_snowfree = ev_snowfree + evpart
952
953 !Change in water stores
954 IF (vegfraction > 0) THEN
955 IF (precip + addveg*(sfr_surf(is)/vegfraction) > (ipthreshold_mmhr/nsh_real)) THEN !if 5min precipitation is larger than 10 mm
956 runoff_snowfree(is) = runoff_snowfree(is) + (precip + addveg*(sfr_surf(is)/vegfraction) + &
957 snowtosurf(is) + addwater(is) - (ipthreshold_mmhr/nsh_real))
958 chang(is) = (ipthreshold_mmhr/nsh_real) - (drain(is) + ev_snowfree + freezstate(is))
959 ELSE
960 chang(is) = precip + addveg*(sfr_surf(is)/vegfraction) + snowtosurf(is) + &
961 addwater(is) - (drain(is) + ev_snowfree + freezstate(is))
962 END IF
963 ELSE
964 chang(is) = precip + snowtosurf(is) + addwater(is) - (drain(is) + ev_snowfree + freezstate(is))
965 END IF
966
967 state_id(is) = state_id(is) + chang(is)
968
969 !Add water in soil store only if ground is not frozen
970 IF (temp_c > 0) THEN
971 soilstore_id(is) = soilstore_id(is) + drain(is)*addwaterrunoff(is)*(1 - snowfrac(is))
972 ELSE
973 runoff_snowfree(is) = runoff_snowfree(is) + drain(is)*addwaterrunoff(is)
974 END IF
975
976 !If state_id of the surface is negative, remove water from soilstore
977 IF (state_id(is) < 0.0) THEN
978
979 IF ((soilstore_id(is) + state_id(is)) >= 0 .AND. temp_c > 0) THEN !If water in soilstore, water is removed
980
981 soilstore_id(is) = soilstore_id(is) + state_id(is)*(1 - snowfrac(is))
982 state_id(is) = 0.0
983
984 ELSE !If not water in the soilstore evaporation does not occur
985 chang(is) = chang(is) + state_id(is)
986 ev_snowfree = ev_snowfree + state_id(is)
987 state_id(is) = 0.0
988 END IF
989 END IF !state_id is negative
990
991 !If soilstorage is full at this point, excess will go to surface runoff
992 IF (soilstore_id(is) > soilstorecap(is)) THEN
993 runofftest = runofftest + (soilstore_id(is) - soilstorecap(is))
994 soilstore_id(is) = soilstorecap(is)
995 ELSEIF (soilstore_id(is) < 0) THEN
996 soilstore_id(is) = 0
997 END IF
998
999 END IF !Surface type
1000
1001 END IF !Surface fraction
1002 !-------------------------------------------------------------------------------------------------------------------
1003
1004 !Calculate change in SnowPack and state_id for the respective surface areas
1005 !Here the case where not all surface state_id freezes is handled
1006 IF (snowfracfresh2 > 0) THEN
1007 surf_chang_tot = (state_id(is) - stateold(is))*sfr_surf(is)*(1 - snowfrac(is)) &
1008 - precip*sfr_surf(is)*(1 - snowfracfresh2)
1009 chsnow_tot = ((snowpack(is) + snowwater(is)) - snowtotinit)*sfr_surf(is)*(1 - snowfrac(is)) &
1010 - precip*sfr_surf(is)*snowfracfresh2
1011 ELSE
1012 surf_chang_tot = (state_id(is) - stateold(is))*sfr_surf(is)*(1 - snowfrac(is))
1013 chsnow_tot = ((snowpack(is) + snowwater(is)) - snowtotinit)*sfr_surf(is)*max(snowfrac(is), snowfracold)
1014 END IF
1015
1016 !===Update snow depth, weighted SWE, and Mwstore
1017 IF (snowdens(is) /= 0) THEN
1018 snowdepth(is) = snowpack(is)*waterdens/snowdens(is)
1019 END IF
1020
1021 ! Calculate overall snow water equivalent
1022 swe = swe + snowpack(is)*sfr_surf(is)*max(snowfrac(is), snowfracold)
1023 mwstore = mwstore + snowwater(is)*sfr_surf(is)*max(snowfrac(is), snowfracold)
1024
1025 !if (id==6.and.it==13.and.imin==20) then!
1026 !if (id==85.and.it==3.and.imin==10) then!
1027 ! if (id==92.and.it==21.and.imin==35) then!
1028 ! write(*,*) ((SnowPack(is)+SnowWater(is))-snowTotInit)*sfr_surf(is)*(1-SnowFrac(is)),&
1029 ! runoff(is)*sfr_surf(is)*(1-SnowFrac(is)),&
1030 ! ev*sfr_surf(is)*(1-SnowFrac(is)),&
1031 ! (state_id(is)-stateOld(is))*sfr_surf(is)*(1-SnowFrac(is)),Precip*sfr_surf(is)
1032 ! write(*,*) changSnow(is),runoff(is),ev,chang(is),runoffTest,FreezState(is) !changSnow(is)-freezMelt(is)
1033 ! write(*,*) is,Precip,runoff_per_tstep,ev_per_tstep,surf_chang_per_tstep,chSnow_per_interval
1034 ! write(*,*) is,Precip-runoff_per_tstep-ev_per_tstep,surf_chang_per_tstep+chSnow_per_interval
1035 ! write(*,*) is,SnowFrac(is),sfr_surf(is),sfr_surf(is)*ev_snow(is)
1036 ! pause
1037 ! endif
1038
1039 !Only now update the new snow fractions both in the case that snow existing already on ground
1040 !and snow forms at the current timestep
1041 IF (snowfracfresh1 > 0) snowfrac(is) = snowfracfresh1
1042 IF (snowfracfresh2 > 0) snowfrac(is) = snowfracfresh2
1043
1044 !Calculate new snow fraction here.
1045 !Tässä ongelmana että snow fraction muuttuu vain kun on sulamisvettä ja on vika tunti.
1046 !Tämä ei juuri koskaan toteudu johtuen lämpötilan vuorokausisyklistä
1047 !Kokeile tässä ajaa kahdella tavalla 1) ei tarvita Mw:tä
1048 ! 2) päivitys voi tapahtua millon vain
1049 !if (SnowFractionChoice==2.and.imin==(nsh_real-1)/nsh_real*60) then
1050 IF (snowfractionchoice == 2) THEN
1051 IF (snowpack(is) > 0 .AND. mw_ind(is) > 0) THEN
1052 snowfrac(is) = snowdepletioncurve(is, snowpack(is), snowpacklimit(is))
1053 IF (snowfrac(is) < 0.001) snowfrac(is) = 0.001 !The snow fraction minimum is 1% of the surface
1054 ELSEIF (snowpack(is) == 0) THEN
1055 snowfrac(is) = 0
1056 END IF
1057 END IF
1058 END IF !end snowCalcSwitch
1059
1060 !Add evaporation to total
1061 IF (is == bldgsurf .OR. is == pavsurf) THEN
1062 ev_tot = ev_snowfree*sfr_surf(is)*(1 - snowfrac(is)) + ev_snow(is)*sfr_surf(is)*max(snowfrac(is), snowfracold)
1063 qe_tot = ev_snow(is)*tlv_sub*sfr_surf(is)*snowfrac(is) + ev_snowfree*tlv*sfr_surf(is)*(1 - snowfrac(is))
1064 ELSE
1065 ev_tot = ev_snowfree*sfr_surf(is)*(1 - snowfrac(is)) + ev_snow(is)*sfr_surf(is)*max(snowfrac(is), snowfracold)
1066 qe_tot = ev_snow(is)*tlv_sub*sfr_surf(is)*max(snowfrac(is), snowfracold) + ev_snowfree*tlv*sfr_surf(is)*(1 - snowfrac(is))
1067 END IF
1068
1069 !========RUNOFF=======================
1070
1071 !Add runoff to pipes
1072 runoffpipes = runoffpipes &
1073 + runoffsnow_surf(is)*sfr_surf(is)*max(snowfrac(is), snowfracold) &
1074 + runoff_snowfree(is)*sfr_surf(is)*(1 - snowfrac(is)) &
1075 + runofftest*sfr_surf(is)
1076 CALL updateflood( &
1077 is, runoff_snowfree, & ! input:
1078 sfr_surf, pipecapacity, runofftowater, &
1079 runoffagimpervious, surpluswaterbody, runoffagveg, runoffpipes) ! inout:
1080
1081 runoff_tot = runoffsnow_surf(is)*sfr_surf(is)*max(snowfrac(is), snowfracold) &
1082 + runoff_snowfree(is)*sfr_surf(is)*(1 - snowfrac(is)) &
1083 + runofftest*sfr_surf(is)
1084
1085 ! !===Update snow depth, weighted SWE, and Mwstore
1086 ! IF (SnowDens(is) /= 0) THEN
1087 ! SnowDepth(is) = SnowPack(is)*waterDens/SnowDens(is)
1088 ! END IF
1089
1090 ! ! Calculate overall snow water equivalent
1091 ! swe = swe + SnowPack(is)*sfr_surf(is)*MAX(SnowFrac(is), snowfracOld)
1092 ! MwStore = MwStore + SnowWater(is)*sfr_surf(is)*MAX(SnowFrac(is), snowfracOld)
1093
1094 ! !if (id==6.and.it==13.and.imin==20) then!
1095 ! !if (id==85.and.it==3.and.imin==10) then!
1096 ! ! if (id==92.and.it==21.and.imin==35) then!
1097 ! ! write(*,*) ((SnowPack(is)+SnowWater(is))-snowTotInit)*sfr_surf(is)*(1-SnowFrac(is)),&
1098 ! ! runoff(is)*sfr_surf(is)*(1-SnowFrac(is)),&
1099 ! ! ev*sfr_surf(is)*(1-SnowFrac(is)),&
1100 ! ! (state_id(is)-stateOld(is))*sfr_surf(is)*(1-SnowFrac(is)),Precip*sfr_surf(is)
1101 ! ! write(*,*) changSnow(is),runoff(is),ev,chang(is),runoffTest,FreezState(is) !changSnow(is)-freezMelt(is)
1102 ! ! write(*,*) is,Precip,runoff_per_tstep,ev_per_tstep,surf_chang_per_tstep,chSnow_per_interval
1103 ! ! write(*,*) is,Precip-runoff_per_tstep-ev_per_tstep,surf_chang_per_tstep+chSnow_per_interval
1104 ! ! write(*,*) is,SnowFrac(is),sfr_surf(is),sfr_surf(is)*ev_snow(is)
1105 ! ! pause
1106 ! ! endif
1107
1108 ! !Only now update the new snow fractions both in the case that snow existing already on ground
1109 ! !and snow forms at the current timestep
1110 ! IF (snowFracFresh1 > 0) SnowFrac(is) = snowFracFresh1
1111 ! IF (snowFracFresh2 > 0) SnowFrac(is) = snowFracFresh2
1112
1113 ! !Calculate new snow fraction here.
1114 ! !Tässä ongelmana että snow fraction muuttuu vain kun on sulamisvettä ja on vika tunti.
1115 ! !Tämä ei juuri koskaan toteudu johtuen lämpötilan vuorokausisyklistä
1116 ! !Kokeile tässä ajaa kahdella tavalla 1) ei tarvita Mw:tä
1117 ! ! 2) päivitys voi tapahtua millon vain
1118 ! !if (SnowFractionChoice==2.and.imin==(nsh_real-1)/nsh_real*60) then
1119 ! IF (SnowFractionChoice == 2) THEN
1120 ! IF (SnowPack(is) > 0 .AND. mw_ind(is) > 0) THEN
1121 ! SnowFrac(is) = SnowDepletionCurve(is, SnowPack(is), SnowPackLimit(is))
1122 ! IF (SnowFrac(is) < 0.001) SnowFrac(is) = 0.001 !The snow fraction minimum is 1% of the surface
1123 ! ELSEIF (SnowPack(is) == 0) THEN
1124 ! SnowFrac(is) = 0
1125 ! END IF
1126 ! END IF
1127
1128 RETURN
1129
1130 !==========================================================================
1131 !WATERBODY is treated separately as state_id always below ice if ice existing
1132 !Calculate change in SnowPack
1133606 changsnow(watersurf) = (precip + freezmelt(watersurf) + freezstate(watersurf)) - &
1134 (mw_ind(watersurf) + ev_snow(watersurf))
1135
1136 snowpack(watersurf) = snowpack(watersurf) + changsnow(watersurf) !Update SnowPack
1137 state_id(watersurf) = state_id(watersurf) + flowchange - freezstate(watersurf) !Update state_id below ice
1138
1139 !If SnowPack exists
1140 IF (snowpack(watersurf) > 0) THEN
1141
1142 !Add melted water to meltstore and freeze water according to freezMelt(is)
1143 snowwater(watersurf) = snowwater(watersurf) + mw_ind(watersurf) - freezmelt(watersurf)
1144
1145 !Calculate water holding capacity (FWC: Valeo and Ho, 2004) of the SnowPack
1146 fwc = waterholdcapfrac*snowpack(watersurf)
1147
1148 !If FWC is exceeded, add meltwater to state_id
1149 IF (snowwater(watersurf) >= fwc .AND. temp_c >= 0) THEN
1150 state_id(watersurf) = state_id(watersurf) + (snowwater(watersurf) - fwc)
1151 snowwater(watersurf) = fwc
1152 END IF
1153
1154 !If SnowPack is negative, it melts at this timestep
1155 ELSEIF (snowpack(is) < 0) THEN
1156
1157 !Add water to the meltwater store
1158 !If freezing meltwater inside this hour, remove it from the SnowWater
1159 snowwater(watersurf) = snowwater(watersurf) - freezmelt(watersurf) &
1160 + mw_ind(watersurf)
1161
1162 state_id(watersurf) = state_id(watersurf) + snowwater(watersurf) + snowpack(watersurf) !Add meltwater to state_id
1163 snowpack(watersurf) = 0
1164 IF (state_id(watersurf) < 0) ev_snow(watersurf) = ev_snow(watersurf) + state_id(watersurf)
1165
1166 END IF !SnowPack negative or positive
1167
1168 !Check water state_id separately
1169 IF (state_id(watersurf) > storedrainprm(5, watersurf)) THEN
1170 runoff_snowfree(watersurf) = runoff_snowfree(watersurf) + (state_id(watersurf) - storedrainprm(5, watersurf))
1171 state_id(watersurf) = storedrainprm(5, watersurf)
1172 runoffwaterbody = runoffwaterbody + runoff_snowfree(watersurf)*sfr_surf(watersurf)
1173 ELSE
1174 state_id(watersurf) = state_id(watersurf) + surpluswaterbody
1175
1176 IF (state_id(watersurf) > storedrainprm(5, watersurf)) THEN
1177 runoffwaterbody = runoffwaterbody + (state_id(watersurf) - storedrainprm(5, watersurf))*sfr_surf(watersurf)
1178 state_id(watersurf) = storedrainprm(5, watersurf)
1179 END IF
1180 END IF
1181
1182 !Change state_id of snow and surface
1183 chsnow_tot = ((snowpack(watersurf) + snowwater(watersurf)) - snowtotinit)*sfr_surf(watersurf)
1184 !ch_per_interval=ch_per_interval+(state_id(WaterSurf)-stateOld(WaterSurf))*sfr_surf(WaterSurf)
1185 surf_chang_tot = (state_id(watersurf) - stateold(watersurf))*sfr_surf(watersurf)
1186
1187 !Evaporation
1188 ev_tot = ev_snowfree*sfr_surf(watersurf) + ev_snow(watersurf)*sfr_surf(watersurf)
1189 qe_tot = ev_snow(watersurf)*tlv_sub*sfr_surf(watersurf) + ev_snowfree*tlv*sfr_surf(watersurf)
1190 runoff_tot = runoff_snowfree(is) !The total runoff from the area
1191
1192 IF (snowpack(watersurf) > 0) THEN !Fraction only 1 or 0
1193 snowfrac(watersurf) = 1
1194 ELSE
1195 snowfrac(watersurf) = 0
1196 END IF
1197
1198 END SUBROUTINE snowcalc
1199
1200 !==========================================================================
1201 !==========================================================================
1202 !Calculates evaporation from snow surface (ev_snow).
1203 !Last update: LJ/Jan 2019 Function changed to subroutine. tlv_sub added to output
1204 SUBROUTINE evap_suews_snow(Qm, QP, lvS_J_kg, avdens, avRh, Press_hPa, Temp_C, RAsnow, psyc_hPa, &
1205 tstep, avcp, sIce_hPa, dectime, ev_snow, tlv_sub)
1206
1207 USE meteo, ONLY: sat_vap_pressice
1208
1209 IMPLICIT NONE
1210
1211 !INPUT
1212 REAL(KIND(1D0)), INTENT(in) :: Qm !melt heat,
1213 REAL(KIND(1D0)), INTENT(in) :: QP !advect. heat
1214 REAL(KIND(1D0)), INTENT(in) :: lvS_J_kg !latent heat of sublimation
1215 REAL(KIND(1D0)), INTENT(in) :: avdens !air density
1216 REAL(KIND(1D0)), INTENT(in) :: avRh !relative humidity
1217 REAL(KIND(1D0)), INTENT(in) :: Press_hPa !air pressure
1218 REAL(KIND(1D0)), INTENT(in) :: Temp_C !air temperature
1219 REAL(KIND(1D0)), INTENT(in) :: RAsnow !aerodyn res snow
1220 REAL(KIND(1D0)), INTENT(in) :: psyc_hPa !psychometric constant
1221 REAL(KIND(1D0)), INTENT(in) :: avcp !spec. heat,
1222 REAL(KIND(1D0)), INTENT(in) :: sIce_hPa !satured curve on snow
1223 REAL(KIND(1D0)), INTENT(in) :: dectime
1224 INTEGER, INTENT(in) :: tstep
1225
1226 REAL(KIND(1D0)), INTENT(out) :: ev_snow !Evaporation
1227 REAL(KIND(1D0)), INTENT(out) :: tlv_sub !Latent heat for sublimation
1228
1229 !OTHER VARIABLES
1230 REAL(KIND(1D0)) :: e_snow, & !PM equation obe line
1231 sae_snow, & !s * (Available energy)
1232 qe_snow, & !Latent heat flux
1233 vdrcIce, & !Vapour pressure deficit
1234 esIce_hPa, & !Saturation vapor pressure over ice
1235 EaIce_hPa, & !Vapour pressure
1236 tstep_real !timestep as real
1237
1238 INTEGER :: from = 1
1239 !-----------------------------------------------------
1240
1241 tstep_real = real(tstep, kind(1d0))
1242
1243 sae_snow = sice_hpa*(qp - qm) !Calculate the driving parameter in calculation of evaporation. Järvi et al. (2015)
1244
1245 esice_hpa = sat_vap_pressice(temp_c, press_hpa, from, dectime) !Saturation vapor pressure over ice
1246 eaice_hpa = avrh/100*esice_hpa !Vapour pressure of water
1247 vdrcice = (esice_hpa - eaice_hpa)*avdens*avcp !Vapour pressure deficit
1248 tlv_sub = lvs_j_kg/tstep_real !Latent heat for sublimation
1249 e_snow = sae_snow + vdrcice/rasnow !PM equation
1250 qe_snow = e_snow/(sice_hpa + psyc_hpa) !Latent heat (W/m^2)
1251 ev_snow = qe_snow/tlv_sub !Evaporation (in mm)
1252
1253 RETURN
1254
1255 END SUBROUTINE evap_suews_snow
1256
1257 !==========================================================================
1258 !==========================================================================
1259 ! Calculates mechanical removal of snow from roofs ans roads
1260 SUBROUTINE snow_removal( &
1261 is, &
1262 SnowFrac, sfr_surf, &
1263 SnowPack, SnowRemoval, &
1264 SnowLimPaved, SnowLimBldg)
1265
1266 IMPLICIT NONE
1267 INTEGER, INTENT(in) :: is
1268 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowFrac, sfr_surf
1269 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: SnowPack
1270 REAL(KIND(1D0)), DIMENSION(2), INTENT(out) :: SnowRemoval
1271 REAL(KIND(1D0)), INTENT(in) :: SnowLimPaved, SnowLimBldg
1272 !write(*,*) is, SnowPack(is),SnowLimPaved,SnowLimBldg
1273
1274 IF (is == pavsurf) THEN
1275 IF (snowpack(pavsurf) > snowlimpaved) THEN
1276 snowremoval(pavsurf) = (snowpack(pavsurf) - snowlimpaved)*sfr_surf(pavsurf)*snowfrac(pavsurf)
1277 snowpack(pavsurf) = snowlimpaved
1278 !SnowPack(PavSurf)=SnowPack(PavSurf)/SnowFrac(PavSurf)
1279 END IF
1280 END IF
1281 IF (is == bldgsurf) THEN
1282 IF (snowpack(bldgsurf) > snowlimbldg) THEN
1283 snowremoval(2) = (snowpack(bldgsurf) - snowlimbldg)*sfr_surf(bldgsurf)*snowfrac(bldgsurf)
1284 snowpack(bldgsurf) = snowlimbldg
1285 !SnowPack(BldgSurf)=SnowPack(BldgSurf)/SnowFrac(BldgSurf)
1286 END IF
1287 END IF
1288 !write(*,*) is, SnowPack(is),SnowLimPaved,SnowLimBldg
1289 !pause
1290 END SUBROUTINE snow_removal
1291
1292 !----------------------------------------------------------------------------
1293 !----------------------------------------------------------------------------
1294 FUNCTION snowdepletioncurve(is, swe, sweD) RESULT(asc)
1295 !This function calculates surface coverage of snow according to the
1296 !depletion curves in Valeo and Ho (2004).
1297 !INPUT: is Surface type number
1298 ! swe Snow water content
1299 ! sweD Limit for
1300
1301 USE allocatearray
1302
1303 IMPLICIT NONE
1304
1305 INTEGER :: is
1306 REAL(kind(1d0)) :: asc, swed, swe
1307
1308 ! initialisation
1309 asc = 1
1310 !Impervious surface
1311 IF (is == pavsurf) THEN
1312
1313 IF (swe <= swed) THEN !Snow water equivalent below threshold
1314 asc = ((swe/swed))**2
1315 ELSE
1316 asc = 1
1317 END IF
1318
1319 !Bldgs surface
1320 ELSEIF (is == bldgsurf) THEN
1321
1322 IF (swe <= swed) THEN
1323 IF ((swe/swed) < 0.9) THEN
1324 asc = (swe/swed)*0.5
1325 ELSE
1326 asc = (swe/swed)**8
1327 END IF
1328 ELSE
1329 asc = 1
1330 END IF
1331 ELSEIF (is == watersurf) THEN
1332 IF (swe > 0) asc = 1
1333
1334 !Vegetion surfaces
1335 ELSE
1336 IF (swe <= swed) THEN
1337
1338 asc = 1 - ((1/3.1416)*acos(2*(swe/swed) - 1))**1.7
1339 ELSE
1340 asc = 1
1341 END IF
1342
1343 END IF
1344
1345 !asc=real(int(10000.*asc))/10000 !4 decimal precision
1346
1347 RETURN
1348 END FUNCTION snowdepletioncurve
1349
1350 SUBROUTINE veg_fr_snow( &
1351 sfr_surf, SnowFrac, & !input
1352 veg_fr) !output
1353
1354 IMPLICIT NONE
1355
1356 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: sfr_surf
1357 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowFrac
1358
1359 REAL(KIND(1D0)), INTENT(out) :: veg_fr
1360
1361 veg_fr = dot_product(sfr_surf(3:7), 1 - snowfrac(3:7))
1362
1363 END SUBROUTINE veg_fr_snow
1364
1365 !In this subroutine the snow properties are updated. The aging functions work for hourly air
1366 !temperature (dt=1). As the code timestep is typically smaller than one hour, the new albedo
1367 !and density are calculated using the timestep air temperature and then these are scaled to timestep
1368 !according to NSH. Made by LJ in sprint 2014
1369 !Last update:
1370 ! TS 17 Sep 2017 - Improve the explicit interface
1371 ! LJ 7 July 2015 - Changed to work with shorter timestep: defined by tstep. Cleaning of the code.
1372 !
1373 !========================================================================
1374
1375 SUBROUTINE snowupdate( &
1376 tstep, & !input
1377 Temp_C, &
1378 tau_a, &
1379 tau_f, &
1380 tau_r, &
1381 SnowDensMax, &
1382 SnowDensMin, &
1383 SnowAlbMax, &
1384 SnowAlbMin, &
1385 SnowPack_prev, SnowAlb_prev, SnowDens_prev, &
1386 SnowAlb_next, SnowDens_next & ! output
1387 )
1388
1389 IMPLICIT NONE
1390
1391 ! INTEGER, INTENT(in)::nsurf
1392 INTEGER, INTENT(in) :: tstep
1393
1394 REAL(KIND(1D0)), INTENT(in) :: Temp_C !Air temperature
1395 REAL(KIND(1D0)), INTENT(in) :: tau_a
1396 REAL(KIND(1D0)), INTENT(in) :: tau_f
1397 REAL(KIND(1D0)), INTENT(in) :: tau_r
1398 REAL(KIND(1D0)), INTENT(in) :: SnowDensMax
1399 REAL(KIND(1D0)), INTENT(in) :: SnowDensMin
1400 REAL(KIND(1D0)), INTENT(in) :: SnowAlbMax
1401 REAL(KIND(1D0)), INTENT(in) :: SnowAlbMin
1402
1403 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowPack_prev
1404
1405 REAL(KIND(1D0)), INTENT(in) :: SnowAlb_prev
1406 REAL(KIND(1D0)), INTENT(out) :: SnowAlb_next
1407
1408 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(in) :: SnowDens_prev
1409 REAL(KIND(1D0)), DIMENSION(nsurf), INTENT(out) :: SnowDens_next
1410
1411 ! INTEGER::is
1412 REAL(KIND(1D0)) :: alb_change !Change in snow albedo
1413 REAL(KIND(1D0)) :: dens_change !Change in snow density
1414 REAL(KIND(1D0)), PARAMETER :: tau_1 = 24*60*60 !Number of seconds in a day
1415
1416 !Initialize
1417 alb_change = 0
1418 dens_change = 0
1419
1420 !==========================================================
1421 !Calculation of snow albedo by Lemonsu et al. 2010
1422 !(org: Verseghy (1991)&Baker et al.(1990))
1423 ! IF (SUM(SnowPack_prev) > 0) THEN !Check if snow on any of the surfaces
1424 ! IF (Temp_C < 0) THEN
1425 ! !alb_change = tau_a*(60*60)/tau_1
1426 ! alb_change = tau_a*(tstep)/tau_1
1427 ! SnowAlb_next = SnowAlb_prev - alb_change
1428 ! ELSE
1429 ! !alb_change = exp(-tau_f*(60*60)/tau_1)
1430 ! alb_change = EXP(-tau_f*(tstep)/tau_1)
1431 ! SnowAlb_next = (SnowAlb_prev - SnowAlbMin)*alb_change + SnowAlbMin
1432 ! ENDIF
1433 ! IF (SnowAlb_next < SnowAlbMin) SnowAlb_next = SnowAlbMin !Albedo cannot be smaller than the min albedo
1434 ! IF (SnowAlb_next > SnowAlbMax) SnowAlb_next = SnowAlbMax !Albedo cannot be larger than the max albedo
1435 ! if (SnowAlb_next < 0) print *, 'SnowAlbMin/max in SnowUpdate', SnowAlbMin, SnowAlbMax, SnowAlb_next
1436 ! ELSE
1437 ! SnowAlb_next = 0
1438 ! ENDIF
1439 ! if (SnowAlb_next < 0) print *, 'SnowAlb in SnowUpdate', SnowAlb_next
1440 snowalb_next = update_snow_albedo( &
1441 tstep, snowpack_prev, snowalb_prev, temp_c, &
1442 tau_a, tau_f, snowalbmax, snowalbmin)
1443
1444 !Update snow density: There is a mistake in Järvi et al. (2014): tau_h should be tau_1
1445 ! DO is = 1, nsurf
1446 ! !If SnowPack existing
1447 ! IF (SnowPack_prev(is) > 0) THEN
1448 ! dens_change = EXP(-tau_r*(tstep)/tau_1)
1449 ! IF (SnowPack_prev(is) > 0) SnowDens_next(is) = (SnowDens_prev(is) - SnowDensMax)*dens_change + SnowDensMax
1450 ! IF (SnowDens_next(is) > SnowDensMax) SnowDens_next(is) = SnowDensMax
1451 ! ELSE
1452 ! SnowDens_next(is) = SnowDensMin
1453 ! ENDIF
1454 ! ENDDO
1455
1456 snowdens_next = update_snow_dens( &
1457 tstep, snowpack_prev, snowdens_prev, &
1458 tau_r, snowdensmax, snowdensmin)
1459
1460 END SUBROUTINE snowupdate
1461
1463 tstep, SnowPack_prev, SnowAlb_prev, Temp_C, &
1464 tau_a, tau_f, SnowAlbMax, SnowAlbMin) &
1465 result(snowalb_next)
1466 IMPLICIT NONE
1467 INTEGER, INTENT(in) :: tstep
1468
1469 REAL(kind(1d0)), DIMENSION(7), INTENT(in) :: snowpack_prev
1470 REAL(kind(1d0)), INTENT(in) :: temp_c
1471 REAL(kind(1d0)), INTENT(in) :: snowalb_prev
1472 REAL(kind(1d0)), INTENT(in) :: tau_a
1473 REAL(kind(1d0)), INTENT(in) :: tau_f
1474 REAL(kind(1d0)), INTENT(in) :: snowalbmax
1475 REAL(kind(1d0)), INTENT(in) :: snowalbmin
1476
1477 REAL(kind(1d0)) :: snowalb_next
1478
1479 REAL(kind(1d0)) :: alb_change !Change in snow albedo
1480 REAL(kind(1d0)), PARAMETER :: tau_1 = 24*60*60 !Number of seconds in a day
1481
1482 !==========================================================
1483 !Calculation of snow albedo by Lemonsu et al. 2010
1484 !(org: Verseghy (1991)&Baker et al.(1990))
1485 IF (sum(snowpack_prev) > 0) THEN !Check if snow on any of the surfaces
1486 IF (temp_c < 0) THEN
1487 !alb_change = tau_a*(60*60)/tau_1
1488 alb_change = tau_a*(tstep)/tau_1
1489 snowalb_next = snowalb_prev - alb_change
1490 ELSE
1491 !alb_change = exp(-tau_f*(60*60)/tau_1)
1492 alb_change = exp(-tau_f*(tstep)/tau_1)
1493 snowalb_next = (snowalb_prev - snowalbmin)*alb_change + snowalbmin
1494 END IF
1495 IF (snowalb_next < snowalbmin) snowalb_next = snowalbmin !Albedo cannot be smaller than the min albedo
1496 IF (snowalb_next > snowalbmax) snowalb_next = snowalbmax !Albedo cannot be larger than the max albedo
1497 IF (snowalb_next < 0) print *, 'SnowAlbMin/max in SnowUpdate', snowalbmin, snowalbmax, snowalb_next
1498 ELSE
1499 snowalb_next = 0
1500 END IF
1501 IF (snowalb_next < 0) print *, 'SnowAlb in SnowUpdate', snowalb_next
1502
1503 END FUNCTION update_snow_albedo
1504
1506 tstep, SnowPack_prev, SnowDens_prev, &
1507 tau_r, SnowDensMax, SnowDensMin) &
1508 result(snowdens_next)
1509 IMPLICIT NONE
1510 REAL(kind(1d0)), DIMENSION(nsurf), INTENT(in) :: snowpack_prev
1511 REAL(kind(1d0)), DIMENSION(nsurf), INTENT(in) :: snowdens_prev
1512 REAL(kind(1d0)), INTENT(in) :: snowdensmax
1513 REAL(kind(1d0)), INTENT(in) :: snowdensmin
1514 REAL(kind(1d0)), INTENT(in) :: tau_r
1515 INTEGER, INTENT(in) :: tstep
1516
1517 ! REAL(KIND(1d0)), DIMENSION(nsurf), INTENT(out)::SnowDens_next
1518
1519 REAL(kind(1d0)), DIMENSION(nsurf) :: snowdens_next
1520 REAL(kind(1d0)) :: dens_change
1521
1522 INTEGER :: is
1523
1524 REAL(kind(1d0)), PARAMETER :: tau_1 = 24*60*60
1525 ! INTEGER,parameter::nsurf=7
1526
1527 !Update snow density: There is a mistake in Järvi et al. (2014): tau_h should be tau_1
1528 DO is = 1, nsurf
1529
1530 !If SnowPack existing
1531 IF (snowpack_prev(is) > 0) THEN
1532 dens_change = exp(-tau_r*(tstep)/tau_1)
1533 IF (snowpack_prev(is) > 0) snowdens_next(is) = (snowdens_prev(is) - snowdensmax)*dens_change + snowdensmax
1534 IF (snowdens_next(is) > snowdensmax) snowdens_next(is) = snowdensmax
1535 ELSE
1536 snowdens_next(is) = snowdensmin
1537 END IF
1538 END DO
1539
1540 END FUNCTION update_snow_dens
1541
1542END MODULE snow_module
integer, parameter bldgsurf
integer, parameter conifsurf
integer, parameter ncolumnsdataoutsnow
integer, parameter watersurf
integer, parameter bsoilsurf
integer, parameter nsurf
integer, parameter pavsurf
subroutine cal_evap(evapmethod, state_is, wetthresh_is, capstore_is, vpd_hpa, avdens, avcp, qn_e, s_hpa, psyc_hpa, rs, ra, rb, tlv, rss, ev, qe)
real(kind(1d0)) function sat_vap_pressice(temp_c, press_hpa, from, dectime)
subroutine snowupdate(tstep, temp_c, tau_a, tau_f, tau_r, snowdensmax, snowdensmin, snowalbmax, snowalbmin, snowpack_prev, snowalb_prev, snowdens_prev, snowalb_next, snowdens_next)
real(kind(1d0)) function, dimension(nsurf) update_snow_dens(tstep, snowpack_prev, snowdens_prev, tau_r, snowdensmax, snowdensmin)
subroutine snow_removal(is, snowfrac, sfr_surf, snowpack, snowremoval, snowlimpaved, snowlimbldg)
real(kind(1d0)) function update_snow_albedo(tstep, snowpack_prev, snowalb_prev, temp_c, tau_a, tau_f, snowalbmax, snowalbmin)
real(kind(1d0)) function snowdepletioncurve(is, swe, swed)
subroutine veg_fr_snow(sfr_surf, snowfrac, veg_fr)
subroutine evap_suews_snow(qm, qp, lvs_j_kg, avdens, avrh, press_hpa, temp_c, rasnow, psyc_hpa, tstep, avcp, sice_hpa, dectime, ev_snow, tlv_sub)
subroutine snowcalc(tstep, imin, it, dectime, is, snowcalcswitch, evapmethod, crwmin, crwmax, nsh_real, lvs_j_kg, avdens, avrh, press_hpa, temp_c, rasnow, psyc_hpa, avcp, sice_hpa, pervfraction, vegfraction, addimpervious, vpd_hpa, qn_e, s_hpa, resistsurf, ra, rb, tlv, snowdensmin, snowprof_24hr, precip, pipecapacity, runofftowater, addveg, snowlimpaved, snowlimbldg, flowchange, drain, wetthresh, stateold, mw_ind, soilstorecap, rainonsnow, freezmelt, freezstate, freezstatevol, qm_melt, qm_rain, tsurf_ind, sfr_surf, dayofweek_id, storedrainprm, snowpacklimit, addwater, addwaterrunoff, soilstore_id, snowpack, surplusevap, snowfrac, snowwater, icefrac, snowdens, runoffagimpervious, runoffagveg, surpluswaterbody, ev_tot, qe_tot, runoff_tot, surf_chang_tot, chsnow_tot, rss_surf, runoff_snowfree, chang, changsnow, snowtosurf, state_id, ev_snow, snowremoval, swe, runoffpipes, mwstore, runoffwaterbody)
subroutine meltheat(lvs_j_kg, lv_j_kg, tstep_real, radmeltfact, tempmeltfact, snowalbmax, snowdensmin, temp_c, precip, preciplimit, preciplimitalb, nsh_real, sfr_surf, tsurf_ind, state_id, qn1_ind_snow, snowwater, deltaqi, snowpack, snowfrac, snowalb, snowdens, snowfallcum, mwh, fwh, qm, qmfreez, qmrain, snowcalcswitch, qm_melt, qm_freezstate, qm_rain, freezmelt, freezstate, freezstatevol, rainonsnow, snowdepth, mw_ind)
subroutine updateflood(is, runoff, sfr_surf, pipecapacity, runofftowater, runoffagimpervious, surpluswaterbody, runoffagveg, runoffpipes)