SURFEX v8.1
General documentation of Surfex
prep_perm_snow.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 ! #########
6 SUBROUTINE prep_perm_snow (IO, KK, PK, PEK)
7 ! ################################################
8 !
9 !
10 !!**** *PREP_PERM_SNOW* - takes into account permanent snow into prognostic snow
11 !!
12 !! PURPOSE
13 !! -------
14 !
15 !!** METHOD
16 !! ------
17 !!
18 !! REFERENCE
19 !! ---------
20 !!
21 !!
22 !! AUTHOR
23 !! ------
24 !! V. Masson
25 !!
26 !! MODIFICATIONS
27 !! -------------
28 !! Original 01/2004
29 !! B. Decharme 03/2009: Consistency with Arpege permanent
30 !! snow/ice treatment
31 !! B. Decharme 07/2012: 3-L or Crocus adjustments
32 !! M. Lafaysse 09/2012: adaptation with new snow age in Crocus
33 !!------------------------------------------------------------------
34 !
35 USE modd_surfex_mpi, ONLY : nrank, npio, ncomm, nproc
36 !
39 !
41 USE modd_csts, ONLY : xtt
42 USE modd_data_cover_par, ONLY : nvt_snow
43 USE modd_snow_par, ONLY : xrhosmax, xansmax, xansmin, &
44  xaglamax, xaglamin, xhgla, &
45  xrhosmax_es
46 USE modd_surf_par, ONLY : xundef
47 !
48 USE modd_isba_par, ONLY : xwgmin
49 !
50 USE modi_vegtype_to_patch
53 USE modi_mkflag_snow
55 USE mode_snow3l
56 !
57 USE yomhook ,ONLY : lhook, dr_hook
58 USE parkind1 ,ONLY : jprb
59 !
60 IMPLICIT NONE
61 !
62 #ifdef SFX_MPI
63 include "mpif.h"
64 #endif
65 !
66 !* 0.1 declarations of arguments
67 !
68 !
69 TYPE(isba_options_t), INTENT(INOUT) :: IO
70 TYPE(isba_k_t), INTENT(INOUT) :: KK
71 TYPE(isba_p_t), INTENT(INOUT) :: PK
72 TYPE(isba_pe_t), INTENT(INOUT) :: PEK
73 !
74 !* 0.2 declarations of local parameter
75 !
76 REAL, PARAMETER :: ZRHOL1 = 150.
77 !
78 !* 0.3 declarations of local variables
79 !
80 INTEGER :: JL ! loop counter on snow layers
81 REAL, DIMENSION(:), ALLOCATABLE :: ZWSNOW_PERM ! snow total reservoir due to perm. snow
82 REAL, DIMENSION(:), ALLOCATABLE :: ZWSNOW ! initial snow total reservoir
83 REAL, DIMENSION(:), ALLOCATABLE :: ZD ! new snow total depth
84 REAL, DIMENSION(:,:), ALLOCATABLE :: ZDEPTH ! depth of each layer
85 REAL, DIMENSION(:,:), ALLOCATABLE :: ZT ! new snow temperature profile
86 REAL, DIMENSION(:), ALLOCATABLE :: ZPSN ! permanent snow fraction
87 REAL, DIMENSION(:,:), ALLOCATABLE :: ZWAT !
88 !
89 LOGICAL, DIMENSION(:,:), ALLOCATABLE :: GWORK
90 INTEGER :: IWORK
91 !
92 #ifdef SFX_MPI
93 INTEGER, DIMENSION(MPI_STATUS_SIZE) :: ISTATUS
94 #endif
95 INTEGER :: INFOMPI
96 INTEGER :: ISNOW ! patch number where permanent snow is
97 !
98 REAL, DIMENSION(0:NPROC-1) :: ZPSN0
99 REAL :: ZSUM_PSN
100 REAL ::ZRHOSMAX
101 REAL ::ZAGE_NOW
102 !
103 REAL(KIND=JPRB) :: ZHOOK_HANDLE
104 !
105 !-------------------------------------------------------------------------------------
106 !
107 !* 1. Snow where permanent snow is
108 ! ----------------------------
109 !
110 !* snow fraction must be at least equal to permanent snow fraction
111 ! The snow fraction is computed as Wsnow/(Wsnow+XWCRN)
112 !
113 !
114 IF (lhook) CALL dr_hook('PREP_PERM_SNOW',0,zhook_handle)
115 !
116 zrhosmax=xrhosmax
117 IF(pek%TSNOW%SCHEME=='3-L'.OR.pek%TSNOW%SCHEME=='CRO')THEN
118  zrhosmax=xrhosmax_es
119 ENDIF
120 !
121 ALLOCATE(zpsn(SIZE(pek%XTG,1)))
122 
123 zpsn(:) = min( pk%XVEGTYPE_PATCH(:,nvt_snow) , 0.9999 )
124 !
125 !* if no permanent snow present
126 !
127 zsum_psn = sum(zpsn(:))
128 IF (nproc>1) THEN
129 #ifdef SFX_MPI
130  CALL mpi_allgather(zsum_psn,kind(zsum_psn)/4,mpi_real,&
131  zpsn0,kind(zpsn0)/4,mpi_real,ncomm,infompi)
132 #endif
133 ELSE
134  zpsn0(:) = zsum_psn
135 ENDIF
136 
137 IF (all(zpsn0(:)==0.)) THEN
138  DEALLOCATE(zpsn)
139  IF (lhook) CALL dr_hook('PREP_PERM_SNOW',1,zhook_handle)
140  RETURN
141 END IF
142 !
143 !* total snow amount due to permanent snow
144 !
145 ALLOCATE(zwsnow_perm(SIZE(pek%XTG,1)))
146 zwsnow_perm(:) = wsnow_from_snow_frac_ground(zpsn)
147 !
148 !* limitation of maximum snow amount
149 !
150 IF(io%LGLACIER)THEN
151 ! limited to 33.3 meters of aged snow
152  zwsnow_perm(:) = min(zwsnow_perm(:),xhgla * zrhosmax )
153 ELSE
154 ! limited to 2. meters of aged snow
155  zwsnow_perm(:) = min(zwsnow_perm(:),2.0 * zrhosmax )
156 ENDIF
157 !
158 !* permanent snow can be added only if deep soil temperature is below 5 C
159 ! (glaciers on subgrid mountains tops that are contained in the grid mesh are neglected)
160 !
161 IF(.NOT.io%LGLACIER)THEN
162  WHERE(pek%XTG(:,SIZE(pek%XTG,2))>xtt+5.) zwsnow_perm(:) = 0.
163 ENDIF
164 !
165 !-------------------------------------------------------------------------------------
166 !
167 !* 2. Other parameters of new snow, except temperature
168 ! ------------------------------------------------
169 !
170 !* rho must be defined for snow 3-L before temperature and heat computations
171 !
172 ALLOCATE(gwork(SIZE(pek%XTG,1),pek%TSNOW%NLAYER))
173 !
174 DO jl=1,pek%TSNOW%NLAYER
175 !
176  gwork(:,jl)=.false.
177 !
178  IF(io%LGLACIER)THEN
179  WHERE(zwsnow_perm(:)>0.)gwork(:,jl)=.true.
180  ELSE
181  WHERE(zwsnow_perm(:)>0..AND.pek%TSNOW%WSNOW(:,jl)==0.)gwork(:,jl)=.true.
182  ENDIF
183 !
184 !* rho
185 !
186  WHERE(gwork(:,jl))
187  pek%TSNOW%RHO(:,jl) = zrhosmax
188  END WHERE
189 !
190 !* albedo
191 !
192  IF(io%LGLACIER)THEN
193  WHERE(gwork(:,jl))
194  pek%TSNOW%ALB(:) = (xaglamax+xaglamin)/2.0
195  END WHERE
196  ELSE
197  WHERE(gwork(:,jl))
198  pek%TSNOW%ALB(:) = (xansmax+xansmin)/2.0
199  END WHERE
200  ENDIF
201 !
202 END DO
203 !
204 IF (pek%TSNOW%SCHEME=='3-L'.OR.pek%TSNOW%SCHEME=='CRO') THEN
205 !
206 ! * optimized rho perm snow profile
207 !
208  IF(io%LGLACIER.AND.pek%TSNOW%NLAYER>=6)THEN
209  WHERE(gwork(:,1))
210  pek%TSNOW%RHO(:,1) = zrhol1
211  END WHERE
212  IF(pek%TSNOW%NLAYER>=6.AND.pek%TSNOW%NLAYER<12)THEN
213  WHERE(gwork(:,2))
214  pek%TSNOW%RHO(:,2) = zrhol1 + 100.
215  END WHERE
216  WHERE(gwork(:,3))
217  pek%TSNOW%RHO(:,3) = zrhol1 + 250.
218  END WHERE
219  ELSE
220  DO jl=2,pek%TSNOW%NLAYER
221  WHERE(gwork(:,jl))
222  pek%TSNOW%RHO(:,jl) = min(zrhosmax,pek%TSNOW%RHO(:,jl-1)+100.)
223  END WHERE
224  ENDDO
225  ENDIF
226  ENDIF
227 !
228 ! * Snow age profile
229 !
230  DO jl=1,pek%TSNOW%NLAYER/4
231  WHERE(gwork(:,jl))
232  pek%TSNOW%AGE(:,jl) = 365.0*float(jl-1)/ float(pek%TSNOW%NLAYER)
233  END WHERE
234  END DO
235  DO jl=1+pek%TSNOW%NLAYER/4,pek%TSNOW%NLAYER
236  WHERE(gwork(:,jl))
237  pek%TSNOW%AGE(:,jl) = 3650.*float(jl-1)/ float(pek%TSNOW%NLAYER)
238  END WHERE
239  END DO
240 !
241  IF(io%LGLACIER)THEN
242  WHERE(gwork(:,:))pek%TSNOW%AGE(:,:) = 0.0
243  ENDIF
244 !
245 END IF
246 !
247 IF (pek%TSNOW%SCHEME=='CRO') THEN
248 DO jl=1,pek%TSNOW%NLAYER/4
249  WHERE(gwork(:,jl))
250  pek%TSNOW%GRAN1(:,jl) = min(-1.,-99.* (1.-4*float(jl)/float(pek%TSNOW%NLAYER)))
251  pek%TSNOW%GRAN2(:,jl) = 50.
252  pek%TSNOW%HIST(:,jl) = 0
253  END WHERE
254 END DO
255 DO jl=1+pek%TSNOW%NLAYER/4,pek%TSNOW%NLAYER
256  WHERE(gwork(:,jl))
257  pek%TSNOW%GRAN1(:,jl) = 99.
258  pek%TSNOW%GRAN2(:,jl) = 0.0003
259  pek%TSNOW%HIST(:,jl) = 0
260  END WHERE
261 END DO
262 END IF
263 !
264 !-------------------------------------------------------------------------------------
265 !
266 !* 3. Modification of snow reservoir profile
267 ! --------------------------------------
268 !
269 !* initial snow content
270 !
271 ALLOCATE(zwsnow(SIZE(pek%XTG,1)))
272 zwsnow(:) = 0.
273 DO jl=1,pek%TSNOW%NLAYER
274  zwsnow(:) = zwsnow(:) + pek%TSNOW%WSNOW(:,jl)
275 END DO
276 !
277 !* new total snow content
278 !
279 zwsnow_perm(:) = max(zwsnow_perm(:),zwsnow(:))
280 !
281 !* new total snow depth
282 !
283 ALLOCATE(zd(SIZE(pek%XTG,1)))
284 zd(:) = 0.
285 DO jl=1,pek%TSNOW%NLAYER
286  zd(:) = zd(:) + pek%TSNOW%WSNOW(:,jl)/pek%TSNOW%RHO(:,jl)
287 END DO
288 zd(:) = zd(:) + (zwsnow_perm(:)-zwsnow(:))/zrhosmax
289 !
290 !* modified snow content profile
291 !
292 SELECT CASE(pek%TSNOW%SCHEME)
293  CASE('D95','1-L','EBA')
294  gwork(:,1)=.false.
295  IF(io%LGLACIER)THEN
296  WHERE(zwsnow(:)>=0..AND.pek%TSNOW%WSNOW(:,1)/=xundef)gwork(:,1)=.true.
297  ELSE
298  WHERE(zwsnow(:)==0..AND.pek%TSNOW%WSNOW(:,1)/=xundef)gwork(:,1)=.true.
299  ENDIF
300  WHERE(gwork(:,1))
301  pek%TSNOW%WSNOW(:,1) = zwsnow_perm(:)
302  END WHERE
303  CASE('3-L','CRO')
304  !* grid
305  ALLOCATE(zdepth(SIZE(pek%XTG,1),pek%TSNOW%NLAYER))
306  CALL snow3lgrid(zdepth,zd)
307  DO jl=1,pek%TSNOW%NLAYER
308  WHERE(zwsnow(:)>= 0. .AND. pek%TSNOW%WSNOW(:,jl)/=xundef)
309  pek%TSNOW%WSNOW(:,jl) = zdepth(:,jl) * pek%TSNOW%RHO(:,jl)
310  END WHERE
311  END DO
312  DEALLOCATE(zdepth)
313 
314 END SELECT
315 !
316 DEALLOCATE(zd)
317 !-------------------------------------------------------------------------------------
318 !
319 !* 4. Temperature of new snow
320 ! -----------------------
321 !
322 ALLOCATE(zt(SIZE(pek%TSNOW%WSNOW,1),SIZE(pek%TSNOW%WSNOW,2)))
323 !
324 SELECT CASE(pek%TSNOW%SCHEME)
325  CASE('1-L')
326  zt(:,:) = pek%TSNOW%T (:,:)
327  CASE('3-L','CRO')
328  CALL snow_heat_to_t_wliq(pek%TSNOW%HEAT,pek%TSNOW%RHO,zt)
329 END SELECT
330 !
331 !* new snow is set to deep ground temperature
332 !
333 DO jl=1,pek%TSNOW%NLAYER
334 !
335  gwork(:,jl)=.false.
336 !
337  IF(io%LGLACIER)THEN
338  WHERE(zwsnow_perm(:)>0.)gwork(:,jl)=.true.
339  ELSE
340  WHERE(zwsnow_perm(:)>0. .AND. zwsnow(:)==0)gwork(:,jl)=.true.
341  ENDIF
342 !
343  WHERE(gwork(:,jl))
344  zt(:,jl) = min(pek%XTG(:,SIZE(pek%XTG,2)),xtt)
345  END WHERE
346 !
347 END DO
348 !
349 !
350 SELECT CASE(pek%TSNOW%SCHEME)
351  CASE('1-L')
352  pek%TSNOW%T (:,:) = zt(:,:)
353  CASE('3-L','CRO')
354  CALL snow_t_wliq_to_heat(pek%TSNOW%HEAT,pek%TSNOW%RHO,zt)
355 END SELECT
356 !
357 DEALLOCATE(zt )
358 DEALLOCATE(gwork)
359 !
360 !
361 !-------------------------------------------------------------------------------------
362 !
363 !* 5. Soil ice initialization for LGLACIER
364 ! -----------------------
365 !
366 ALLOCATE(zwat(SIZE(pek%XTG,1),SIZE(pek%XTG,2)))
367 !
368 IF(io%LGLACIER)THEN
369 !
370  IF (io%CISBA == 'DIF') THEN
371  iwork=io%NGROUND_LAYER
372  zwat(:,:)=kk%XWFC(:,:)
373  ELSE
374  iwork=2
375  zwat(:,:)=kk%XWSAT(:,:)
376  ENDIF
377 !
378  DO jl=1,iwork
379  WHERE(pk%XVEGTYPE_PATCH(:,nvt_snow)>0.0)
380  pek%XWGI(:,jl) = max(pek%XWGI(:,jl),zwat(:,jl)*zpsn(:))
381  pek%XWG (:,jl) = min(pek%XWG (:,jl), max(kk%XWSAT(:,jl)-pek%XWGI(:,jl),xwgmin))
382  END WHERE
383  WHERE(pek%XWG(:,jl) /= xundef .AND. (pek%XWG(:,jl) + pek%XWGI(:,jl)) > kk%XWSAT(:,jl) )
384  pek%XWGI(:,jl) = kk%XWSAT(:,jl)-pek%XWG (:,jl) !WGT<=WSAT
385  END WHERE
386  ENDDO
387 !
388 ENDIF
389 !
390 DEALLOCATE(zwat)
391 DEALLOCATE(zpsn)
392 !
393 !-------------------------------------------------------------------------------------
394 !
395 !* 6. Masking where there is no snow
396 ! ------------------------------
397 !
398  CALL mkflag_snow(pek%TSNOW)
399 !
400 IF (lhook) CALL dr_hook('PREP_PERM_SNOW',1,zhook_handle)
401 !
402 !-------------------------------------------------------------------------------------
403 !
404 END SUBROUTINE prep_perm_snow
real function, dimension(size(ppsng)) wsnow_from_snow_frac_ground(PPSNG)
real, parameter xundef
subroutine prep_perm_snow(IO, KK, PK, PEK)
integer, parameter jprb
Definition: parkind1.F90:32
subroutine mkflag_snow(TPSNOW)
Definition: mkflag_snow.F90:7
intent(out) overrides sub arrays one Sort by the least significant key first sum(iindex(1:n))
logical lhook
Definition: yomhook.F90:15
real, save xtt
Definition: modd_csts.F90:66