SURFEX v8.1
General documentation of Surfex
mode_snow3l.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  MODULE mode_snow3l
7 ! ##################
8 !
9 !!**** *MODE_SNOW * - contains explicit snow (ISBA-ES) characteristics functions
10 !! for total liquid water holding capacity of a snow layer (m)
11 !! and the thermal heat capacity of a layer (J K-1 m-3)
12 !!
13 !! PURPOSE
14 !! -------
15 !
16 !!** METHOD
17 !! ------
18 !! direct calculation
19 !!
20 !! EXTERNAL
21 !! --------
22 !!
23 !! IMPLICIT ARGUMENTS
24 !! ------------------
25 !!
26 !! REFERENCE
27 !! ---------
28 !! Boone and Etchevers, J. HydroMeteor., 2001
29 !!
30 !!
31 !! AUTHOR
32 !! ------
33 !! A. Boone * Meteo France *
34 !!
35 !! MODIFICATIONS
36 !! -------------
37 !! Original 01/08/02
38 !! V. Masson 01/2004 add snow grid computations
39 !! V. Vionnet 06/2008 -Introduction of Crocus formulation to
40 ! calculate maximum liquid water holding capacity
41 !! - New algorithm to compute snow grid :
42 ! 10 layers
43 !! - Routine to aggregate snow grain type
44 ! from 2 layers
45 !! _ Routine to compute average grain
46 ! type when snow depth< 3 cm.
47 ! S. Morin 02/2011 - Add routines for Crocus
48 ! A. Boone 02/2012 - Add optimization of do-loops.
49 ! C. Carmagnola 12/2012 - Add the case CSNOWMETAMO!='B92' in subroutine SNOW3LAVGRAIN and in function SNOW3LDIFTYP
50 ! M. Lafaysse 01/2013 - Remove SNOWCROWLIQMAX routines (not used)
51 ! M. Lafaysse 08/2013 - simplification of routine SNOW3LAVGRAIN (logical GDENDRITIC)
52 ! B. Decharme 07/2013 - SNOW3LGRID cleanning
53 ! New algorithm to compute snow grid for 6-L or 12-L
54 ! A. Boone 10/2014 - Added snow thermal conductivity routines
55 ! B. Decharme 01/2015 - Added optical snow grain size diameter
56 !----------------------------------------------------------------------------
57 !
58 !* 0. DECLARATIONS
59 !
60 !
61 INTERFACE snow3lwliqmax
62  MODULE PROCEDURE snow3lwliqmax_3d
63  MODULE PROCEDURE snow3lwliqmax_2d
64  MODULE PROCEDURE snow3lwliqmax_1d
65 END INTERFACE
66 !
67 INTERFACE snow3lhold
68  MODULE PROCEDURE snow3lhold_3d
69  MODULE PROCEDURE snow3lhold_2d
70  MODULE PROCEDURE snow3lhold_1d
71  MODULE PROCEDURE snow3lhold_0d
72 END INTERFACE
73 INTERFACE snowcrohold
74  MODULE PROCEDURE snowcrohold_3d
75  MODULE PROCEDURE snowcrohold_2d
76  MODULE PROCEDURE snowcrohold_1d
77  MODULE PROCEDURE snowcrohold_0d
78 END INTERFACE
79 !
80 INTERFACE snow3lscap
81  MODULE PROCEDURE snow3lscap_3d
82  MODULE PROCEDURE snow3lscap_2d
83  MODULE PROCEDURE snow3lscap_1d
84  MODULE PROCEDURE snow3lscap_0d
85 END INTERFACE
86 !
87 INTERFACE snow3l_marbouty
88  MODULE PROCEDURE snow3l_marbouty
89 END INTERFACE
90 !
91 INTERFACE snow3lgrid
92  MODULE PROCEDURE snow3lgrid_2d
93  MODULE PROCEDURE snow3lgrid_1d
94 END INTERFACE
95 !
96 INTERFACE snow3lagreg
97  MODULE PROCEDURE snow3lagreg
98 END INTERFACE
99 !
100 INTERFACE snow3lavgrain
101  MODULE PROCEDURE snow3lavgrain
102 END INTERFACE
103 !
104 INTERFACE snow3ldiftyp
105  MODULE PROCEDURE snow3ldiftyp
106 END INTERFACE
107 !
108 INTERFACE get_mass_heat
109  MODULE PROCEDURE get_mass_heat
110 END INTERFACE
111 !
112 INTERFACE get_diam
113  MODULE PROCEDURE get_diam
114 END INTERFACE
115 !
116 INTERFACE snow3lradabs
117  MODULE PROCEDURE snow3lradabs_2d
118  MODULE PROCEDURE snow3lradabs_1d
119  MODULE PROCEDURE snow3lradabs_0d
120 END INTERFACE
121 !
123  MODULE PROCEDURE snow3lradabs_sfc
124 END INTERFACE
125 !
126 INTERFACE snow3lthrm
127  MODULE PROCEDURE snow3lthrm
128 END INTERFACE
129 !
130 INTERFACE snow3ldopt
131  MODULE PROCEDURE snow3ldopt_2d
132  MODULE PROCEDURE snow3ldopt_1d
133  MODULE PROCEDURE snow3ldopt_0d
134 END INTERFACE
135 !
136 INTERFACE snow3lalb
137  MODULE PROCEDURE snow3lalb
138 END INTERFACE
139 !
140 INTERFACE snow3lfall
141  MODULE PROCEDURE snow3lfall
142 END INTERFACE
143 !
144 INTERFACE snow3ltransf
145  MODULE PROCEDURE snow3ltransf
146 END INTERFACE
147 !
148 INTERFACE snow3lcompactn
149  MODULE PROCEDURE snow3lcompactn
150 END INTERFACE
151 !
152 !-------------------------------------------------------------------------------
153 CONTAINS
154 !
155 !####################################################################
156  FUNCTION snow3lwliqmax_3d(PSNOWRHO) RESULT(PWLIQMAX)
157 !
158 !! PURPOSE
159 !! -------
160 ! Calculate the maximum liquid water holding capacity of
161 ! snow layer(s).
162 !
163 USE modd_snow_par, ONLY : xrhosmax_es, xsnowrhohold, &
164  xwsnowholdmax2, xwsnowholdmax1
165 !
166 USE yomhook ,ONLY : lhook, dr_hook
167 USE parkind1 ,ONLY : jprb
168 !
169 IMPLICIT NONE
170 !
171 !* 0.1 declarations of arguments
172 !
173 REAL, DIMENSION(:,:,:), INTENT(IN) :: PSNOWRHO ! (kg/m3)
174 !
175 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2),SIZE(PSNOWRHO,3)) :: PWLIQMAX ! (kg/m3)
176 !
177 !* 0.2 declarations of local variables
178 !
179 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2),SIZE(PSNOWRHO,3)) :: ZHOLDMAXR, ZSNOWRHO
180 REAL(KIND=JPRB) :: ZHOOK_HANDLE
181 !-----------------------------------------------------------------------
182 ! Evaluate capacity using upper density limit:
183 !
184 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LWLIQMAX_3D',0,zhook_handle)
185 zsnowrho(:,:,:) = min(xrhosmax_es, psnowrho(:,:,:))
186 !
187 ! Maximum ratio of liquid to SWE:
188 !
189 zholdmaxr(:,:,:) = xwsnowholdmax1 + (xwsnowholdmax2-xwsnowholdmax1)* &
190  max(0.,xsnowrhohold-zsnowrho(:,:,:))/xsnowrhohold
191 !
192 ! Maximum liquid water holding capacity of the snow (kg/m3):
193 !
194 pwliqmax(:,:,:) = zholdmaxr(:,:,:)*zsnowrho(:,:,:)
195 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LWLIQMAX_3D',1,zhook_handle)
196 !
197 END FUNCTION snow3lwliqmax_3d
198 !####################################################################
199  FUNCTION snow3lwliqmax_2d(PSNOWRHO) RESULT(PWLIQMAX)
200 !
201 !! PURPOSE
202 !! -------
203 ! Calculate the maximum liquid water holding capacity of
204 ! snow layer(s).
205 !
206 USE modd_snow_par, ONLY : xrhosmax_es, xsnowrhohold, &
207  xwsnowholdmax2, xwsnowholdmax1
208 !
209 USE yomhook ,ONLY : lhook, dr_hook
210 USE parkind1 ,ONLY : jprb
211 !
212 IMPLICIT NONE
213 !
214 !* 0.1 declarations of arguments
215 !
216 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWRHO ! (kg/m3)
217 !
218 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: PWLIQMAX ! (kg/m3)
219 !
220 !* 0.2 declarations of local variables
221 !
222 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZHOLDMAXR, ZSNOWRHO
223 REAL(KIND=JPRB) :: ZHOOK_HANDLE
224 !-----------------------------------------------------------------------
225 ! Evaluate capacity using upper density limit:
226 !
227 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LWLIQMAX_2D',0,zhook_handle)
228 zsnowrho(:,:) = min(xrhosmax_es, psnowrho(:,:))
229 !
230 ! Maximum ratio of liquid to SWE:
231 !
232 zholdmaxr(:,:) = xwsnowholdmax1 + (xwsnowholdmax2-xwsnowholdmax1)* &
233  max(0.,xsnowrhohold-zsnowrho(:,:))/xsnowrhohold
234 !
235 ! Maximum liquid water holding capacity of the snow (kg/m3):
236 !
237 pwliqmax(:,:) = zholdmaxr(:,:)*zsnowrho(:,:)
238 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LWLIQMAX_2D',1,zhook_handle)
239 !
240 END FUNCTION snow3lwliqmax_2d
241 !####################################################################
242  FUNCTION snow3lwliqmax_1d(PSNOWRHO) RESULT(PWLIQMAX)
243 !
244 !! PURPOSE
245 !! -------
246 ! Calculate the maximum liquid water holding capacity of
247 ! snow layer(s).
248 !
249 USE modd_snow_par, ONLY : xrhosmax_es, xsnowrhohold, &
250  xwsnowholdmax2, xwsnowholdmax1
251 !
252 USE yomhook ,ONLY : lhook, dr_hook
253 USE parkind1 ,ONLY : jprb
254 !
255 IMPLICIT NONE
256 !
257 !* 0.1 declarations of arguments
258 !
259 REAL, DIMENSION(:), INTENT(IN) :: PSNOWRHO ! (kg/m3)
260 !
261 REAL, DIMENSION(SIZE(PSNOWRHO)) :: PWLIQMAX ! (kg/m3)
262 !
263 !* 0.2 declarations of local variables
264 !
265 REAL, DIMENSION(SIZE(PSNOWRHO)) :: ZHOLDMAXR, ZSNOWRHO
266 REAL(KIND=JPRB) :: ZHOOK_HANDLE
267 !----------------------------------------------------------------------
268 ! Evaluate capacity using upper density limit:
269 !
270 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LWLIQMAX_1D',0,zhook_handle)
271 zsnowrho(:) = min(xrhosmax_es, psnowrho(:))
272 !
273 ! Maximum ratio of liquid to SWE:
274 !
275 zholdmaxr(:) = xwsnowholdmax1 + (xwsnowholdmax2-xwsnowholdmax1)* &
276  max(0.,xsnowrhohold-zsnowrho(:))/xsnowrhohold
277 !
278 ! Maximum liquid water holding capacity of the snow (kg/m3):
279 !
280 pwliqmax(:) = zholdmaxr(:)*zsnowrho(:)
281 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LWLIQMAX_1D',1,zhook_handle)
282 !
283 END FUNCTION snow3lwliqmax_1d
284 
285 !####################################################################
286 !####################################################################
287 !####################################################################
288  FUNCTION snow3lhold_3d(PSNOWRHO,PSNOWDZ) RESULT(PWHOLDMAX)
289 !
290 !! PURPOSE
291 !! -------
292 ! Calculate the maximum liquid water holding capacity of
293 ! snow layer(s).
294 !
295 USE modd_csts, ONLY : xrholw
296 USE modd_snow_par, ONLY : xrhosmax_es, xsnowrhohold, &
297  xwsnowholdmax2, xwsnowholdmax1
298 !
299 USE yomhook ,ONLY : lhook, dr_hook
300 USE parkind1 ,ONLY : jprb
301 !
302 IMPLICIT NONE
303 !
304 !* 0.1 declarations of arguments
305 !
306 REAL, DIMENSION(:,:,:), INTENT(IN) :: PSNOWDZ, PSNOWRHO
307 !
308 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2),SIZE(PSNOWRHO,3)) :: PWHOLDMAX
309 !
310 !* 0.2 declarations of local variables
311 !
312 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2),SIZE(PSNOWRHO,3)) :: ZHOLDMAXR, ZSNOWRHO
313 REAL(KIND=JPRB) :: ZHOOK_HANDLE
314 !-------------------------------------------------------------------------
315 ! Evaluate capacity using upper density limit:
316 !
317 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LHOLD_3D',0,zhook_handle)
318 zsnowrho(:,:,:) = min(xrhosmax_es, psnowrho(:,:,:))
319 !
320 ! Maximum ratio of liquid to SWE:
321 !
322 zholdmaxr(:,:,:) = xwsnowholdmax1 + (xwsnowholdmax2-xwsnowholdmax1)* &
323  max(0.,xsnowrhohold-zsnowrho(:,:,:))/xsnowrhohold
324 !
325 ! Maximum liquid water holding capacity of the snow (m):
326 !
327 pwholdmax(:,:,:) = zholdmaxr(:,:,:)*psnowdz(:,:,:)*zsnowrho(:,:,:)/xrholw
328 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LHOLD_3D',1,zhook_handle)
329 !
330 END FUNCTION snow3lhold_3d
331 !####################################################################
332  FUNCTION snow3lhold_2d(PSNOWRHO,PSNOWDZ) RESULT(PWHOLDMAX)
333 !
334 !! PURPOSE
335 !! -------
336 ! Calculate the maximum liquid water holding capacity of
337 ! snow layer(s).
338 !
339 USE modd_csts, ONLY : xrholw
340 USE modd_snow_par, ONLY : xrhosmax_es, xsnowrhohold, &
341  xwsnowholdmax2, xwsnowholdmax1
342 !
343 USE yomhook ,ONLY : lhook, dr_hook
344 USE parkind1 ,ONLY : jprb
345 !
346 IMPLICIT NONE
347 !
348 !* 0.1 declarations of arguments
349 !
350 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWDZ, PSNOWRHO
351 !
352 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: PWHOLDMAX
353 !
354 !* 0.2 declarations of local variables
355 !
356 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZHOLDMAXR, ZSNOWRHO
357 REAL(KIND=JPRB) :: ZHOOK_HANDLE
358 !-----------------------------------------------------------------------
359 ! Evaluate capacity using upper density limit:
360 !
361 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LHOLD_2D',0,zhook_handle)
362 zsnowrho(:,:) = min(xrhosmax_es, psnowrho(:,:))
363 !
364 ! Maximum ratio of liquid to SWE:
365 !
366 zholdmaxr(:,:) = xwsnowholdmax1 + (xwsnowholdmax2-xwsnowholdmax1)* &
367  max(0.,xsnowrhohold-zsnowrho(:,:))/xsnowrhohold
368 !
369 ! Maximum liquid water holding capacity of the snow (m):
370 !
371 pwholdmax(:,:) = zholdmaxr(:,:)*psnowdz(:,:)*zsnowrho(:,:)/xrholw
372 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LHOLD_2D',1,zhook_handle)
373 !
374 END FUNCTION snow3lhold_2d
375 !####################################################################
376  FUNCTION snow3lhold_1d(PSNOWRHO,PSNOWDZ) RESULT(PWHOLDMAX)
377 !
378 !! PURPOSE
379 !! -------
380 ! Calculate the maximum liquid water holding capacity of
381 ! snow layer(s).
382 !
383 USE modd_csts, ONLY : xrholw
384 USE modd_snow_par, ONLY : xrhosmax_es, xsnowrhohold, &
385  xwsnowholdmax2, xwsnowholdmax1
386 !
387 USE yomhook ,ONLY : lhook, dr_hook
388 USE parkind1 ,ONLY : jprb
389 !
390 IMPLICIT NONE
391 !
392 !* 0.1 declarations of arguments
393 !
394 REAL, DIMENSION(:), INTENT(IN) :: PSNOWDZ, PSNOWRHO
395 !
396 REAL, DIMENSION(SIZE(PSNOWRHO)) :: PWHOLDMAX
397 !
398 !* 0.2 declarations of local variables
399 !
400 REAL, DIMENSION(SIZE(PSNOWRHO)) :: ZHOLDMAXR, ZSNOWRHO
401 REAL(KIND=JPRB) :: ZHOOK_HANDLE
402 !-----------------------------------------------------------------------
403 ! Evaluate capacity using upper density limit:
404 !
405 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LHOLD_1D',0,zhook_handle)
406 zsnowrho(:) = min(xrhosmax_es, psnowrho(:))
407 !
408 ! Maximum ratio of liquid to SWE:
409 !
410 zholdmaxr(:) = xwsnowholdmax1 + (xwsnowholdmax2-xwsnowholdmax1)* &
411  max(0.,xsnowrhohold-zsnowrho(:))/xsnowrhohold
412 !
413 ! Maximum liquid water holding capacity of the snow (m):
414 !
415 pwholdmax(:) = zholdmaxr(:)*psnowdz(:)*zsnowrho(:)/xrholw
416 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LHOLD_1D',1,zhook_handle)
417 !
418 END FUNCTION snow3lhold_1d
419 !####################################################################
420  FUNCTION snow3lhold_0d(PSNOWRHO,PSNOWDZ) RESULT(PWHOLDMAX)
421 !
422 !! PURPOSE
423 !! -------
424 ! Calculate the maximum liquid water holding capacity of
425 ! snow layer(s).
426 !
427 USE modd_csts, ONLY : xrholw
428 USE modd_snow_par, ONLY : xrhosmax_es, xsnowrhohold, &
429  xwsnowholdmax2, xwsnowholdmax1
430 !
431 USE yomhook ,ONLY : lhook, dr_hook
432 USE parkind1 ,ONLY : jprb
433 !
434 IMPLICIT NONE
435 !
436 !* 0.1 declarations of arguments
437 !
438 REAL, INTENT(IN) :: PSNOWDZ, PSNOWRHO
439 !
440 REAL :: PWHOLDMAX
441 !
442 !* 0.2 declarations of local variables
443 !
444 REAL :: ZHOLDMAXR, ZSNOWRHO
445 REAL(KIND=JPRB) :: ZHOOK_HANDLE
446 !-------------------------------------------------------------------------------
447 ! Evaluate capacity using upper density limit:
448 !
449 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LHOLD_0D',0,zhook_handle)
450 zsnowrho = min(xrhosmax_es, psnowrho)
451 !
452 ! Maximum ratio of liquid to SWE:
453 !
454 zholdmaxr = xwsnowholdmax1 + (xwsnowholdmax2-xwsnowholdmax1) * &
455  max(0.,xsnowrhohold-zsnowrho)/xsnowrhohold
456 !
457 ! Maximum liquid water holding capacity of the snow (m):
458 !
459 pwholdmax = zholdmaxr*psnowdz*zsnowrho/xrholw
460 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LHOLD_0D',1,zhook_handle)
461 !
462 END FUNCTION snow3lhold_0d
463 !####################################################################
464  FUNCTION snowcrohold_3d(PSNOWRHO,PSNOWLIQ,PSNOWDZ) RESULT(PWHOLDMAX)
465 !
466 !! PURPOSE
467 !! -------
468 ! Calculate the maximum liquid water holding capacity of
469 ! snow layer(s).
470 !
471 USE modd_csts, ONLY : xrholw,xrholi
472 USE modd_snow_par, ONLY : xpercentagepore
473 !
474 USE yomhook ,ONLY : lhook, dr_hook
475 USE parkind1 ,ONLY : jprb
476 !
477 IMPLICIT NONE
478 !
479 !* 0.1 declarations of arguments
480 !
481 REAL, DIMENSION(:,:,:), INTENT(IN) :: PSNOWDZ, PSNOWLIQ, PSNOWRHO
482 !
483 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2),SIZE(PSNOWRHO,3)) :: PWHOLDMAX
484 REAL(KIND=JPRB) :: ZHOOK_HANDLE
485 !-------------------------------------------------------------------------------
486 ! computation of water holding capacity based on Crocus,
487 !taking into account the conversion between wet and dry density -
488 !S. Morin/V. Vionnet 2010 12 09
489 
490 ! PWHOLDMAX is expressed in m water for each layer
491 ! In short, PWHOLDMAX = XPERCENTAGEPORE * porosity * PSNOWDZ .
492 ! The porosity is computed as (rho_ice - (rho_snow - lwc))/(rho_ice)
493 ! where everything has to be in kg m-3 units. In practice, since
494 ! PSNOWLIQ is expressed in m water, expressing the lwc in kg m-3
495 ! is achieved as PSNOWLIQ*XRHOLW/PSNOWDZ. After some rearranging one
496 ! obtains the equation given above.
497 ! Note that equation (19) in Vionnet et al., GMD 2012, is wrong,
498 ! because it does not take into account the fact that liquid water
499 ! content has to be substracted from total density to compute the
500 ! porosity.
501 
502 
503 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOWCROHOLD_3D',0,zhook_handle)
504 pwholdmax(:,:,:) = xpercentagepore/xrholi * (psnowdz * (xrholi-psnowrho) + psnowliq*xrholw)
505 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOWCROHOLD_3D',1,zhook_handle)
506 !
507 END FUNCTION snowcrohold_3d
508 !####################################################################
509  FUNCTION snowcrohold_2d(PSNOWRHO,PSNOWLIQ,PSNOWDZ) RESULT(PWHOLDMAX)
510 !
511 !! PURPOSE
512 !! -------
513 ! Calculate the maximum liquid water holding capacity of
514 ! snow layer(s).
515 !
516 USE modd_csts, ONLY : xrholw,xrholi
517 USE modd_snow_par, ONLY : xpercentagepore
518 !
519 USE yomhook ,ONLY : lhook, dr_hook
520 USE parkind1 ,ONLY : jprb
521 !
522 IMPLICIT NONE
523 !
524 !* 0.1 declarations of arguments
525 !
526 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWDZ, PSNOWRHO, PSNOWLIQ
527 !
528 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: PWHOLDMAX
529 REAL(KIND=JPRB) :: ZHOOK_HANDLE
530 !-------------------------------------------------------------------------------
531 ! computation of water holding capacity based on Crocus,
532 !taking into account the conversion between wet and dry density -
533 !S. Morin/V. Vionnet 2010 12 09
534 
535 ! PWHOLDMAX is expressed in m water for each layer
536 ! In short, PWHOLDMAX = XPERCENTAGEPORE * porosity * PSNOWDZ .
537 ! The porosity is computed as (rho_ice - (rho_snow - lwc))/(rho_ice)
538 ! where everything has to be in kg m-3 units. In practice, since
539 ! PSNOWLIQ is expressed in m water, expressing the lwc in kg m-3
540 ! is achieved as PSNOWLIQ*XRHOLW/PSNOWDZ. After some rearranging one
541 ! obtains the equation given above.
542 ! Note that equation (19) in Vionnet et al., GMD 2012, is wrong,
543 ! because it does not take into account the fact that liquid water
544 ! content has to be substracted from total density to compute the
545 ! porosity.
546 
547 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOWCROHOLD_2D',0,zhook_handle)
548 pwholdmax(:,:) = xpercentagepore/xrholi * (psnowdz * (xrholi-psnowrho) + psnowliq*xrholw)
549 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOWCROHOLD_2D',1,zhook_handle)
550 !
551 END FUNCTION snowcrohold_2d
552 !####################################################################
553 !####################################################################
554 !####################################################################
555  FUNCTION snowcrohold_1d(PSNOWRHO,PSNOWLIQ,PSNOWDZ) RESULT(PWHOLDMAX)
556 !
557 !! PURPOSE
558 !! -------
559 ! Calculate the maximum liquid water holding capacity of
560 ! snow layer(s).
561 !
562 USE modd_csts, ONLY : xrholw,xrholi
563 USE modd_snow_par, ONLY : xpercentagepore
564 !
565 USE yomhook ,ONLY : lhook, dr_hook
566 USE parkind1 ,ONLY : jprb
567 !
568 IMPLICIT NONE
569 !
570 !* 0.1 declarations of arguments
571 !
572 REAL, DIMENSION(:), INTENT(IN) :: PSNOWDZ, PSNOWRHO, PSNOWLIQ
573 !
574 REAL, DIMENSION(SIZE(PSNOWRHO)) :: PWHOLDMAX
575 REAL(KIND=JPRB) :: ZHOOK_HANDLE
576 !-------------------------------------------------------------------------------
577 ! computation of water holding capacity based on Crocus,
578 !taking into account the conversion between wet and dry density -
579 !S. Morin/V. Vionnet 2010 12 09
580 
581 ! PWHOLDMAX is expressed in m water for each layer
582 ! In short, PWHOLDMAX = XPERCENTAGEPORE * porosity * PSNOWDZ .
583 ! The porosity is computed as (rho_ice - (rho_snow - lwc))/(rho_ice)
584 ! where everything has to be in kg m-3 units. In practice, since
585 ! PSNOWLIQ is expressed in m water, expressing the lwc in kg m-3
586 ! is achieved as PSNOWLIQ*XRHOLW/PSNOWDZ. After some rearranging one
587 ! obtains the equation given above.
588 ! Note that equation (19) in Vionnet et al., GMD 2012, is wrong,
589 ! because it does not take into account the fact that liquid water
590 ! content has to be substracted from total density to compute the
591 ! porosity.
592 
593 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOWCROHOLD_1D',0,zhook_handle)
594 pwholdmax(:) = xpercentagepore/xrholi * (psnowdz * (xrholi-psnowrho) + psnowliq*xrholw)
595 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOWCROHOLD_1D',1,zhook_handle)
596 !
597 END FUNCTION snowcrohold_1d
598 !####################################################################
599  FUNCTION snowcrohold_0d(PSNOWRHO,PSNOWLIQ,PSNOWDZ) RESULT(PWHOLDMAX)
600 !
601 !! PURPOSE
602 !! -------
603 ! Calculate the maximum liquid water holding capacity of
604 ! snow layer(s).
605 !
606 USE modd_csts, ONLY : xrholw,xrholi
607 USE modd_snow_par, ONLY : xpercentagepore
608 !
609 USE yomhook ,ONLY : lhook, dr_hook
610 USE parkind1 ,ONLY : jprb
611 !
612 IMPLICIT NONE
613 !
614 !* 0.1 declarations of arguments
615 !
616 REAL, INTENT(IN) :: PSNOWDZ, PSNOWRHO, PSNOWLIQ
617 !
618 REAL :: PWHOLDMAX
619 REAL(KIND=JPRB) :: ZHOOK_HANDLE
620 !-------------------------------------------------------------------------------
621 ! computation of water holding capacity based on Crocus,
622 !taking into account the conversion between wet and dry density -
623 !S. Morin/V. Vionnet 2010 12 09
624 
625 ! PWHOLDMAX is expressed in m water for each layer
626 ! In short, PWHOLDMAX = XPERCENTAGEPORE * porosity * PSNOWDZ .
627 ! The porosity is computed as (rho_ice - (rho_snow - lwc))/(rho_ice)
628 ! where everything has to be in kg m-3 units. In practice, since
629 ! PSNOWLIQ is expressed in m water, expressing the lwc in kg m-3
630 ! is achieved as PSNOWLIQ*XRHOLW/PSNOWDZ. After some rearranging one
631 ! obtains the equation given above.
632 ! Note that equation (19) in Vionnet et al., GMD 2012, is wrong,
633 ! because it does not take into account the fact that liquid water
634 ! content has to be substracted from total density to compute the
635 ! porosity.
636 
637 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOWCROHOLD_0D',0,zhook_handle)
638 pwholdmax = xpercentagepore/xrholi * (psnowdz * (xrholi-psnowrho) + psnowliq*xrholw)
639 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOWCROHOLD_0D',1,zhook_handle)
640 !
641 END FUNCTION snowcrohold_0d
642 !####################################################################
643 !####################################################################
644 !####################################################################
645  FUNCTION snow3lscap_3d(PSNOWRHO) RESULT(PSCAP)
646 !
647 !! PURPOSE
648 !! -------
649 ! Calculate the heat capacity of a snow layer.
650 !
651 USE modd_csts,ONLY : xci
652 !
653 USE yomhook ,ONLY : lhook, dr_hook
654 USE parkind1 ,ONLY : jprb
655 !
656 IMPLICIT NONE
657 !
658 !* 0.1 declarations of arguments
659 !
660 REAL, DIMENSION(:,:,:), INTENT(IN) :: PSNOWRHO
661 !
662 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2),SIZE(PSNOWRHO,3)) :: PSCAP
663 REAL(KIND=JPRB) :: ZHOOK_HANDLE
664 !-------------------------------------------------------------------------------
665 ! The method of Verseghy (1991), Int. J. Climat., 11, 111-133.
666 !
667 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LSCAP_3D',0,zhook_handle)
668 pscap(:,:,:) = psnowrho(:,:,:)*xci ! (J K-1 m-3)
669 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LSCAP_3D',1,zhook_handle)
670 !
671 END FUNCTION snow3lscap_3d
672 !####################################################################
673  FUNCTION snow3lscap_2d(PSNOWRHO) RESULT(PSCAP)
674 !
675 !! PURPOSE
676 !! -------
677 ! Calculate the heat capacity of a snow layer.
678 !
679 USE modd_csts,ONLY : xci
680 !
681 USE yomhook ,ONLY : lhook, dr_hook
682 USE parkind1 ,ONLY : jprb
683 !
684 IMPLICIT NONE
685 !
686 !* 0.1 declarations of arguments
687 !
688 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWRHO
689 !
690 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: PSCAP
691 REAL(KIND=JPRB) :: ZHOOK_HANDLE
692 !-------------------------------------------------------------------------------
693 ! The method of Verseghy (1991), Int. J. Climat., 11, 111-133.
694 !
695 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LSCAP_2D',0,zhook_handle)
696 pscap(:,:) = psnowrho(:,:)*xci ! (J K-1 m-3)
697 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LSCAP_2D',1,zhook_handle)
698 !
699 END FUNCTION snow3lscap_2d
700 !####################################################################
701  FUNCTION snow3lscap_1d(PSNOWRHO) RESULT(PSCAP)
702 !
703 !! PURPOSE
704 !! -------
705 ! Calculate the heat capacity of a snow layer.
706 !
707 USE modd_csts,ONLY : xci
708 !
709 USE yomhook ,ONLY : lhook, dr_hook
710 USE parkind1 ,ONLY : jprb
711 !
712 IMPLICIT NONE
713 !
714 !* 0.1 declarations of arguments
715 !
716 REAL, DIMENSION(:), INTENT(IN) :: PSNOWRHO
717 !
718 REAL, DIMENSION(SIZE(PSNOWRHO)) :: PSCAP
719 REAL(KIND=JPRB) :: ZHOOK_HANDLE
720 !-------------------------------------------------------------------------------
721 ! The method of Verseghy (1991), Int. J. Climat., 11, 111-133.
722 !
723 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LSCAP_1D',0,zhook_handle)
724 pscap(:) = psnowrho(:)*xci ! (J K-1 m-3)
725 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LSCAP_1D',1,zhook_handle)
726 !
727 END FUNCTION snow3lscap_1d
728 !####################################################################
729  FUNCTION snow3lscap_0d(PSNOWRHO) RESULT(PSCAP)
730 !
731 !! PURPOSE
732 !! -------
733 ! Calculate the heat capacity of a snow layer.
734 !
735 USE modd_csts,ONLY : xci
736 !
737 USE yomhook ,ONLY : lhook, dr_hook
738 USE parkind1 ,ONLY : jprb
739 !
740 IMPLICIT NONE
741 !
742 !* 0.1 declarations of arguments
743 !
744 REAL, INTENT(IN) :: PSNOWRHO
745 !
746 REAL :: PSCAP
747 REAL(KIND=JPRB) :: ZHOOK_HANDLE
748 !-------------------------------------------------------------------------------
749 ! The method of Verseghy (1991), Int. J. Climat., 11, 111-133.
750 !
751 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LSCAP_0D',0,zhook_handle)
752 pscap = psnowrho*xci ! (J K-1 m-3)
753 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LSCAP_0D',1,zhook_handle)
754 !
755 END FUNCTION snow3lscap_0d
756 !
757 !####################################################################
758 !####################################################################
759 !####################################################################
760  FUNCTION snow3l_marbouty(PSNOWRHO,PSNOWTEMP,PGRADT) RESULT(PDANGL)
761 !**** *ZDANGL* - CROISSANCE DES GRAINS NON DENDRITIQUES ET ANGULEUX .
762 ! - GROWTH RATES FOR NON DENDRITIC GRAINS WITH SPHERICITY=0
763 
764 
765 ! OBJET.
766 ! ------
767 
768 !** INTERFACE.
769 ! ----------
770 
771 ! *ZDANGL*(PST,PSRO,PGRADT)*
772 
773 ! *PST* - TEMPERATURE DE LA STRATE DE NEIGE.
774 ! *PSRO* - MASSE VOLUMIQUE DE LA STRATE DE NEIGE.
775 ! *PGRADT* - GRADIENT DE TEMPERATURE AFFECTANT LA STRATE DE NEIGE.
776 
777 ! METHODE.
778 ! --------
779 ! THE FUNCTION RETURN A VALUE BETWEEN 0 AND 1 WHICH IS USED IN THE DETERMINATION OF THE
780 ! GROWTH RATE FOR THE CONSIDERED LAYER.
781 ! THIS VALUE (WITHOUT UNIT) IS THE PRODUCT OF 3 FUNCTIONS (WHICH HAVE THEIR SOLUTIONS BETWEEN 0 AND 1) :
782 ! F(TEMPERATURE) * H(DENSITY) * G(TEMPERATURE GRADIENT)
783 
784 ! EXTERNES.
785 ! ---------
786 
787 ! REFERENCES.
788 ! -----------
789 ! MARBOUTY D (1980) AN EXPERIMENTAL STUDY OF TEMPERATURE GRADIENT
790 ! METAMORPHISM J GLACIOLOGY
791 
792 ! AUTEURS.
793 ! --------
794 ! DOMINIQUE MARBOUTY (FMARBO/GMARBO/HMARBO).
795 
796 ! MODIFICATIONS.
797 ! --------------
798 ! 08/95: YANNICK DANIELOU - CODAGE A LA NORME DOCTOR.
799 ! 03/06: JM WILLEMET - F90 AND SI UNITS
800 ! 01/08: JM WILLEMET - ERROR ON THE FORMULATION OF G FUNCTION (WITH GRADIENT) IS CORRECTED
801 
802 USE modd_csts, ONLY : xtt
803 USE modd_snow_metamo
804 !
805 USE yomhook ,ONLY : lhook, dr_hook
806 USE parkind1 ,ONLY : jprb
807 !
808 IMPLICIT NONE
809 !
810 ! DECLARATIONS.
811 ! -------------
812 !
813 REAL ,INTENT(IN) :: PSNOWTEMP, PSNOWRHO, PGRADT
814 !
815 REAL :: PDANGL
816 REAL(KIND=JPRB) :: ZHOOK_HANDLE
817 !
818 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3L_MARBOUTY',0,zhook_handle)
819 !
820 pdangl = 0.0
821 !
822 ! INFLUENCE DE LA TEMPERATURE /TEMPERATURE INFLUENCE.
823 IF( psnowtemp>=xtt-xvtang1 ) THEN
824  !
825  IF ( psnowtemp>=xtt-xvtang2 ) THEN
826  pdangl = xvtang4 + xvtang5 * (xtt-psnowtemp) / xvtang6
827  ELSEIF( psnowtemp>=xtt-xvtang3 ) THEN
828  pdangl = xvtang7 - xvtang8 * (xtt-xvtang2-psnowtemp) / xvtang9
829  ELSE
830  pdangl = xvtanga - xvtangb * (xtt-xvtang3-psnowtemp) / xvtangc
831  ENDIF
832  !
833  ! INFLUENCE DE LA MASSE VOLUMIQUE / DENSITY INFLUENCE.
834  IF ( psnowrho<=xvrang1 ) THEN
835  !
836  IF ( psnowrho>xvrang2 ) THEN
837  pdangl = pdangl * ( 1. - (psnowrho-xvrang2)/(xvrang1-xvrang2) )
838  ENDIF
839  !
840  ! INFLUENCE DU GRADIENT DE TEMPERATURE / TEMPERATURE GRADIENT INFLUENCE.
841  IF ( pgradt<=xvgang1 ) THEN
842  !
843  IF ( pgradt<=xvgang2 ) THEN
844  pdangl = pdangl * xvgang5 * (pgradt-xvgang6)/(xvgang2-xvgang6)
845  ELSEIF( pgradt<=xvgang3 ) THEN
846  pdangl = pdangl * ( xvgang7 + xvgang8 * (pgradt-xvgang2)/(xvgang3-xvgang2) )
847  ELSEIF( pgradt<=xvgang4 )THEN
848  pdangl = pdangl * ( xvgang9 + xvganga * (pgradt-xvgang3)/(xvgang4-xvgang3) )
849  ELSE
850  pdangl = pdangl * ( xvgangb + xvgangc * (pgradt-xvgang4)/(xvgang1-xvgang4) )
851  ENDIF
852  !
853  ENDIF
854  !
855  ELSE
856  !
857  pdangl = 0.
858  !
859  ENDIF
860  !
861 ELSE
862  !
863  pdangl = 0.
864  !
865 ENDIF
866 !
867 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3L_MARBOUTY',1,zhook_handle)
868 !
869 END FUNCTION snow3l_marbouty
870 !
871 !####################################################################
872 !####################################################################
873 !####################################################################
874 !
875  SUBROUTINE snow3lgrid_2d(PSNOWDZ,PSNOW,PSNOWDZ_OLD)
876 !
877 !! PURPOSE
878 !! -------
879 ! Once during each time step, update grid to maintain
880 ! grid proportions. Similar to approach of Lynch-Steiglitz,
881 ! 1994, J. Clim., 7, 1842-1855. Corresponding mass and
882 ! heat adjustments made directly after the call to this
883 ! routine. 3 grid configurations:
884 ! 1) for very thin snow, constant grid spacing
885 ! 2) for intermediate thicknesses, highest resolution at soil/snow
886 ! interface and at the snow/atmosphere interface
887 ! 3) for deep snow, vertical resoution finest at snow/atmosphere
888 ! interface (set to a constant value) and increases with snow depth.
889 ! Second layer can't be more than an order of magnitude thicker
890 ! than surface layer.
891 !
892 !
893 USE modd_surf_par, ONLY : xundef
894 USE modd_snow_par, ONLY : xsnowcritd
895 !
896 USE yomhook ,ONLY : lhook, dr_hook
897 USE parkind1 ,ONLY : jprb
898 !
899 IMPLICIT NONE
900 !
901 !* 0.1 declarations of arguments
902 !
903 REAL, DIMENSION(: ), INTENT(IN ) :: PSNOW
904 REAL, DIMENSION(:,:), INTENT(OUT) :: PSNOWDZ
905 REAL, DIMENSION(:,:), INTENT(IN ), OPTIONAL :: PSNOWDZ_OLD
906 !
907 !* 0.1 declarations of local variables
908 !
909 INTEGER :: JJ, JI
910 !
911 INTEGER :: INLVLS, INI
912 !
913 REAL, DIMENSION(SIZE(PSNOW)) :: ZWORK
914 !
915 LOGICAL , DIMENSION(SIZE(PSNOW)) :: GREGRID
916 
917 ! ISBA-ES snow grid parameters
918 !
919 REAL, PARAMETER, DIMENSION(3) :: ZSGCOEF1 = (/0.25, 0.50, 0.25/)
920 REAL, PARAMETER, DIMENSION(2) :: ZSGCOEF2 = (/0.05, 0.34/)
921 !
922 REAL, PARAMETER, DIMENSION(3) :: ZSGCOEF = (/0.3, 0.4, 0.3/)
923 !
924 ! Minimum total snow depth at which surface layer thickness is constant:
925 !
926 REAL, PARAMETER :: ZSNOWTRANS = 0.20 ! (m)
927 !
928 ! Minimum snow depth by layer for 6-L or 12-L configuration :
929 !
930 REAL, PARAMETER :: ZDZ1=0.01
931 REAL, PARAMETER :: ZDZ2=0.05
932 REAL, PARAMETER :: ZDZ3=0.15
933 REAL, PARAMETER :: ZDZ4=0.50
934 REAL, PARAMETER :: ZDZ5=1.00
935 REAL, PARAMETER :: ZDZN0=0.02
936 REAL, PARAMETER :: ZDZN1=0.1
937 REAL, PARAMETER :: ZDZN2=0.5
938 REAL, PARAMETER :: ZDZN3=1.0
939 !
940 REAL, PARAMETER :: ZCOEF1 = 0.5
941 REAL, PARAMETER :: ZCOEF2 = 1.5
942 !
943 REAL(KIND=JPRB) :: ZHOOK_HANDLE
944 !
945 !-------------------------------------------------------------------------------
946 !
947 ! 0. Initialization:
948 ! ------------------
949 !
950 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LGRID_2D',0,zhook_handle)
951 !
952 inlvls = SIZE(psnowdz(:,:),2)
953 ini = SIZE(psnowdz(:,:),1)
954 !
955 zwork(:) = 0.0
956 gregrid(:) = .true.
957 !
958 ! 1. Calculate current grid for 3-layer (default) configuration):
959 ! ---------------------------------------------------------------
960 ! Based on formulation of Lynch-Stieglitz (1994)
961 ! except for 3 modifications:
962 ! i) smooth transition here at ZSNOWTRANS
963 ! ii) constant ratio for very thin snow:
964 ! iii) ratio of layer 2 to surface layer <= 10
965 !
966 IF(inlvls == 1)THEN
967 !
968  DO ji=1,ini
969  psnowdz(ji,1) = psnow(ji)
970  ENDDO
971 !
972 ELSEIF(inlvls == 3)THEN
973 !
974  WHERE(psnow <= xsnowcritd+0.01)
975  psnowdz(:,1) = min(0.01, psnow(:)/inlvls)
976  psnowdz(:,3) = min(0.01, psnow(:)/inlvls)
977  psnowdz(:,2) = psnow(:) - psnowdz(:,1) - psnowdz(:,3)
978  END WHERE
979 !
980  WHERE(psnow <= zsnowtrans .AND. psnow > xsnowcritd+0.01)
981  psnowdz(:,1) = psnow(:)*zsgcoef1(1)
982  psnowdz(:,2) = psnow(:)*zsgcoef1(2)
983  psnowdz(:,3) = psnow(:)*zsgcoef1(3)
984  END WHERE
985 !
986  WHERE(psnow > zsnowtrans)
987  psnowdz(:,1) = zsgcoef2(1)
988  psnowdz(:,2) = (psnow(:)-zsgcoef2(1))*zsgcoef2(2) + zsgcoef2(1)
989 !
990 ! When using simple finite differences, limit the thickness
991 ! factor between the top and 2nd layers to at most 10
992 !
993  psnowdz(:,2) = min(10*zsgcoef2(1), psnowdz(:,2))
994  psnowdz(:,3) = psnow(:) - psnowdz(:,2) - psnowdz(:,1)
995  END WHERE
996 !
997 !
998 ! 2. Calculate current grid for 6-layer :
999 ! ---------------------------------------------------------------
1000 !
1001 ELSEIF(inlvls == 6)THEN
1002 !
1003 ! critere a satisfaire pour remaillage
1004 !
1005  IF(PRESENT(psnowdz_old))THEN
1006  gregrid(:) = psnowdz_old(:,1) < zcoef1 * min(zdz1 ,psnow(:)/inlvls) .OR. &
1007  & psnowdz_old(:,1) > zcoef2 * min(zdz1 ,psnow(:)/inlvls) .OR. &
1008  & psnowdz_old(:,2) < zcoef1 * min(zdz2 ,psnow(:)/inlvls) .OR. &
1009  & psnowdz_old(:,2) > zcoef2 * min(zdz2 ,psnow(:)/inlvls) .OR. &
1010  & psnowdz_old(:,6) < zcoef1 * min(zdzn1,psnow(:)/inlvls) .OR. &
1011  & psnowdz_old(:,6) > zcoef2 * min(zdzn1,psnow(:)/inlvls)
1012  ENDIF
1013 !
1014  WHERE(gregrid(:))
1015 ! top layers
1016  psnowdz(:,1) = min(zdz1,psnow(:)/inlvls)
1017  psnowdz(:,2) = min(zdz2,psnow(:)/inlvls)
1018 ! last layers
1019  psnowdz(:,6) = min(zdzn1,psnow(:)/inlvls)
1020 ! remaining snow for remaining layers
1021  zwork(:) = psnow(:) - psnowdz(:,1) - psnowdz(:,2) - psnowdz(:,6)
1022  psnowdz(:,3) = zwork(:)*zsgcoef(1)
1023  psnowdz(:,4) = zwork(:)*zsgcoef(2)
1024  psnowdz(:,5) = zwork(:)*zsgcoef(3)
1025 ! layer 3 tickness >= layer 2 tickness
1026  zwork(:)=min(0.0,psnowdz(:,3)-psnowdz(:,2))
1027  psnowdz(:,3)=psnowdz(:,3)-zwork(:)
1028  psnowdz(:,4)=psnowdz(:,4)+zwork(:)
1029 ! layer 5 tickness >= layer 6 tickness
1030  zwork(:)=min(0.0,psnowdz(:,5)-psnowdz(:,6))
1031  psnowdz(:,5)=psnowdz(:,5)-zwork(:)
1032  psnowdz(:,4)=psnowdz(:,4)+zwork(:)
1033  ENDWHERE
1034 !
1035 ! 3. Calculate current grid for 9-layer :
1036 ! ---------------------------------------------------------------
1037 !
1038 ELSEIF(inlvls == 9)THEN
1039 !
1040 ! critere a satisfaire pour remaillage
1041 !
1042  IF(PRESENT(psnowdz_old))THEN
1043  gregrid(:) = psnowdz_old(:,1) < zcoef1 * min(zdz1 ,psnow(:)/inlvls) .OR. &
1044  & psnowdz_old(:,1) > zcoef2 * min(zdz1 ,psnow(:)/inlvls) .OR. &
1045  & psnowdz_old(:,2) < zcoef1 * min(zdz2 ,psnow(:)/inlvls) .OR. &
1046  & psnowdz_old(:,2) > zcoef2 * min(zdz2 ,psnow(:)/inlvls) .OR. &
1047  & psnowdz_old(:,9) < zcoef1 * min(zdzn0,psnow(:)/inlvls) .OR. &
1048  & psnowdz_old(:,9) > zcoef2 * min(zdzn0,psnow(:)/inlvls)
1049  ENDIF
1050 !
1051  WHERE(gregrid(:))
1052 ! top layers
1053  psnowdz(:,1) = min(zdz1,psnow(:)/inlvls)
1054  psnowdz(:,2) = min(zdz2,psnow(:)/inlvls)
1055  psnowdz(:,3) = min(zdz3,psnow(:)/inlvls)
1056 ! last layers
1057  psnowdz(:,9)= min(zdzn0,psnow(:)/inlvls)
1058  psnowdz(:,8)= min(zdzn1,psnow(:)/inlvls)
1059  psnowdz(:,7)= min(zdzn2,psnow(:)/inlvls)
1060 ! remaining snow for remaining layers
1061  zwork(:) = psnow(:) - psnowdz(:, 1) - psnowdz(:, 2) - psnowdz(:, 3) &
1062  - psnowdz(:, 7) - psnowdz(:, 8) - psnowdz(:, 9)
1063  psnowdz(:,4) = zwork(:)*zsgcoef(1)
1064  psnowdz(:,5) = zwork(:)*zsgcoef(2)
1065  psnowdz(:,6) = zwork(:)*zsgcoef(3)
1066 ! layer 4 tickness >= layer 3 tickness
1067  zwork(:)=min(0.0,psnowdz(:,4)-psnowdz(:,3))
1068  psnowdz(:,4)=psnowdz(:,4)-zwork(:)
1069  psnowdz(:,5)=psnowdz(:,5)+zwork(:)
1070 ! layer 6 tickness >= layer 7 tickness
1071  zwork(:)=min(0.0,psnowdz(:,6)-psnowdz(:,7))
1072  psnowdz(:,6)=psnowdz(:,6)-zwork(:)
1073  psnowdz(:,5)=psnowdz(:,5)+zwork(:)
1074  ENDWHERE
1075 !
1076 ! 4. Calculate current grid for 12-layer :
1077 ! ---------------------------------------------------------------
1078 !
1079 ELSEIF(inlvls == 12)THEN
1080 !
1081 ! critere a satisfaire pour remaillage
1082 !
1083  IF(PRESENT(psnowdz_old))THEN
1084  gregrid(:) = psnowdz_old(:, 1) < zcoef1 * min(zdz1 ,psnow(:)/inlvls) .OR. &
1085  & psnowdz_old(:, 1) > zcoef2 * min(zdz1 ,psnow(:)/inlvls) .OR. &
1086  & psnowdz_old(:, 2) < zcoef1 * min(zdz2 ,psnow(:)/inlvls) .OR. &
1087  & psnowdz_old(:, 2) > zcoef2 * min(zdz2 ,psnow(:)/inlvls) .OR. &
1088  & psnowdz_old(:,12) < zcoef1 * min(zdzn0,psnow(:)/inlvls) .OR. &
1089  & psnowdz_old(:,12) > zcoef2 * min(zdzn0,psnow(:)/inlvls)
1090  ENDIF
1091 !
1092  WHERE(gregrid(:))
1093 ! top layers
1094  psnowdz(:,1) = min(zdz1,psnow(:)/inlvls)
1095  psnowdz(:,2) = min(zdz2,psnow(:)/inlvls)
1096  psnowdz(:,3) = min(zdz3,psnow(:)/inlvls)
1097  psnowdz(:,4) = min(zdz4,psnow(:)/inlvls)
1098  psnowdz(:,5) = min(zdz5,psnow(:)/inlvls)
1099 ! last layers
1100  psnowdz(:,12)= min(zdzn0,psnow(:)/inlvls)
1101  psnowdz(:,11)= min(zdzn1,psnow(:)/inlvls)
1102  psnowdz(:,10)= min(zdzn2,psnow(:)/inlvls)
1103  psnowdz(:, 9)= min(zdzn3,psnow(:)/inlvls)
1104 ! remaining snow for remaining layers
1105  zwork(:) = psnow(:) - psnowdz(:, 1) - psnowdz(:, 2) - psnowdz(:, 3) &
1106  - psnowdz(:, 4) - psnowdz(:, 5) - psnowdz(:, 9) &
1107  - psnowdz(:,10) - psnowdz(:,11) - psnowdz(:,12)
1108  psnowdz(:,6) = zwork(:)*zsgcoef(1)
1109  psnowdz(:,7) = zwork(:)*zsgcoef(2)
1110  psnowdz(:,8) = zwork(:)*zsgcoef(3)
1111 ! layer 6 tickness >= layer 5 tickness
1112  zwork(:)=min(0.0,psnowdz(:,6)-psnowdz(:,5))
1113  psnowdz(:,6)=psnowdz(:,6)-zwork(:)
1114  psnowdz(:,7)=psnowdz(:,7)+zwork(:)
1115 ! layer 8 tickness >= layer 9 tickness
1116  zwork(:)=min(0.0,psnowdz(:,8)-psnowdz(:,9))
1117  psnowdz(:,8)=psnowdz(:,8)-zwork(:)
1118  psnowdz(:,7)=psnowdz(:,7)+zwork(:)
1119  ENDWHERE
1120 !
1121 ! 4. Calculate other non-optimized grid :
1122 ! ---------------------------------------
1123 !
1124 ELSEIF(inlvls<10.AND.inlvls/=3.AND.inlvls/=6.AND.inlvls/=9) THEN
1125 !
1126  DO jj=1,inlvls
1127  DO ji=1,ini
1128  psnowdz(ji,jj) = psnow(ji)/inlvls
1129  ENDDO
1130  ENDDO
1131 !
1132  psnowdz(:,inlvls) = psnowdz(:,inlvls) + (psnowdz(:,1) - min(0.05, psnowdz(:,1)))
1133  psnowdz(:,1) = min(0.05, psnowdz(:,1))
1134 !
1135 ELSE !(inlvls>=10 and /=12)
1136 !
1137 ! critere a satisfaire pour remaillage
1138 !
1139  IF(PRESENT(psnowdz_old))THEN
1140  gregrid(:) = psnowdz_old(:, 1) < zcoef1 * min(zdz1 ,psnow(:)/inlvls) .OR. &
1141  & psnowdz_old(:, 1) > zcoef2 * min(zdz1 ,psnow(:)/inlvls) .OR. &
1142  & psnowdz_old(:, 2) < zcoef1 * min(zdz2 ,psnow(:)/inlvls) .OR. &
1143  & psnowdz_old(:, 2) > zcoef2 * min(zdz2 ,psnow(:)/inlvls) .OR. &
1144  & psnowdz_old(:,inlvls) < zcoef1 * min(0.05*psnow(:),psnow(:)/inlvls) .OR. &
1145  & psnowdz_old(:,inlvls) > zcoef2 * min(0.05*psnow(:),psnow(:)/inlvls)
1146  ENDIF
1147 !
1148  WHERE(gregrid(:))
1149  psnowdz(:,1 ) = min(zdz1 ,psnow(:)/inlvls)
1150  psnowdz(:,2 ) = min(zdz2 ,psnow(:)/inlvls)
1151  psnowdz(:,3 ) = min(zdz3 ,psnow(:)/inlvls)
1152  psnowdz(:,4 ) = min(zdz4 ,psnow(:)/inlvls)
1153  psnowdz(:,5 ) = min(zdz5 ,psnow(:)/inlvls)
1154  psnowdz(:,inlvls) = min(0.05*psnow(:),psnow(:)/inlvls)
1155  ENDWHERE
1156 !
1157  DO jj=6,inlvls-1,1
1158  DO ji=1,ini
1159  IF(gregrid(ji))THEN
1160  zwork(ji) = psnowdz(ji,1)+psnowdz(ji,2)+psnowdz(ji,3)+psnowdz(ji,4)+psnowdz(ji,5)
1161  psnowdz(ji,jj) = (psnow(ji)-zwork(ji)-psnowdz(ji,inlvls))/(inlvls-6)
1162  ENDIF
1163  ENDDO
1164  ENDDO
1165 !
1166 ENDIF
1167 !
1168 DO jj=1,inlvls
1169  DO ji=1,ini
1170  IF(psnow(ji)==xundef)THEN
1171  psnowdz(ji,jj) = xundef
1172  ELSEIF(.NOT.gregrid(ji))THEN
1173  psnowdz(ji,jj)=psnowdz_old(ji,jj)
1174  ENDIF
1175  ENDDO
1176 ENDDO
1177 !
1178 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LGRID_2D',1,zhook_handle)
1179 !
1180 END SUBROUTINE snow3lgrid_2d
1181 !####################################################################
1182 !####################################################################
1183 !####################################################################
1184 !
1185  SUBROUTINE snow3lgrid_1d(PSNOWDZ,PSNOW,PSNOWDZ_OLD)
1187 !! PURPOSE
1188 !! -------
1189 ! Once during each time step, update grid to maintain
1190 ! grid proportions. Similar to approach of Lynch-Steiglitz,
1191 ! 1994, J. Clim., 7, 1842-1855. Corresponding mass and
1192 ! heat adjustments made directly after the call to this
1193 ! routine. 3 grid configurations:
1194 ! 1) for very thin snow, constant grid spacing
1195 ! 2) for intermediate thicknesses, highest resolution at soil/snow
1196 ! interface and at the snow/atmosphere interface
1197 ! 3) for deep snow, vertical resoution finest at snow/atmosphere
1198 ! interface (set to a constant value) and increases with snow depth.
1199 ! Second layer can't be more than an order of magnitude thicker
1200 ! than surface layer.
1201 !
1202 !
1203 USE modd_surf_par, ONLY : xundef
1204 USE modd_snow_par, ONLY : xsnowcritd
1205 !
1206 USE yomhook ,ONLY : lhook, dr_hook
1207 USE parkind1 ,ONLY : jprb
1208 !
1209 IMPLICIT NONE
1210 !
1211 !* 0.1 declarations of arguments
1212 !
1213 REAL, INTENT(IN ) :: PSNOW
1214 REAL, DIMENSION(:), INTENT(OUT) :: PSNOWDZ
1215 REAL, DIMENSION(:), INTENT(IN ), OPTIONAL :: PSNOWDZ_OLD
1216 !
1217 !* 0.1 declarations of local variables
1218 !
1219 INTEGER JJ
1220 !
1221 INTEGER :: INLVLS
1222 !
1223 REAL :: ZWORK
1224 !
1225 ! modif_EB pour maillage
1226 LOGICAL :: GREGRID
1227 
1228 ! ISBA-ES snow grid parameters
1229 !
1230 REAL, PARAMETER, DIMENSION(3) :: ZSGCOEF1 = (/0.25, 0.50, 0.25/)
1231 REAL, PARAMETER, DIMENSION(2) :: ZSGCOEF2 = (/0.05, 0.34/)
1232 !
1233 REAL, PARAMETER, DIMENSION(3) :: ZSGCOEF = (/0.3, 0.4, 0.3/)
1234 !
1235 ! Minimum total snow depth at which surface layer thickness is constant:
1236 !
1237 REAL, PARAMETER :: ZSNOWTRANS = 0.20 ! (m)
1238 !
1239 ! Minimum snow depth by layer for 6-L or 12-L configuration :
1240 !
1241 REAL, PARAMETER :: ZDZ1=0.01
1242 REAL, PARAMETER :: ZDZ2=0.05
1243 REAL, PARAMETER :: ZDZ3=0.15
1244 REAL, PARAMETER :: ZDZ4=0.50
1245 REAL, PARAMETER :: ZDZ5=1.00
1246 REAL, PARAMETER :: ZDZN0=0.02
1247 REAL, PARAMETER :: ZDZN1=0.1
1248 REAL, PARAMETER :: ZDZN2=0.5
1249 REAL, PARAMETER :: ZDZN3=1.0
1250 !
1251 REAL, PARAMETER :: ZCOEF1 = 0.5
1252 REAL, PARAMETER :: ZCOEF2 = 1.5
1253 !
1254 REAL(KIND=JPRB) :: ZHOOK_HANDLE
1255 !
1256 !-------------------------------------------------------------------------------
1257 !
1258 ! 0. Initialization:
1259 ! ------------------
1260 !
1261 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LGRID_1D',0,zhook_handle)
1262 !
1263 inlvls = SIZE(psnowdz(:),1)
1264 !
1265 gregrid = .true.
1266 !
1267 ! 1. Calculate current grid for 3-layer (default) configuration):
1268 ! ---------------------------------------------------------------
1269 ! Based on formulation of Lynch-Stieglitz (1994)
1270 ! except for 3 modifications:
1271 ! i) smooth transition here at ZSNOWTRANS
1272 ! ii) constant ratio for very thin snow:
1273 ! iii) ratio of layer 2 to surface layer <= 10
1274 !
1275 IF(inlvls == 1)THEN
1276 !
1277  psnowdz(1) = psnow
1278 !
1279 ELSEIF(inlvls == 3)THEN
1280 !
1281  IF(psnow <= xsnowcritd+0.01)THEN
1282  psnowdz(1) = min(0.01, psnow/inlvls)
1283  psnowdz(3) = min(0.01, psnow/inlvls)
1284  psnowdz(2) = psnow - psnowdz(1) - psnowdz(3)
1285  ENDIF
1286 !
1287  IF(psnow <= zsnowtrans .AND. psnow > xsnowcritd+0.01)THEN
1288  psnowdz(1) = psnow*zsgcoef1(1)
1289  psnowdz(2) = psnow*zsgcoef1(2)
1290  psnowdz(3) = psnow*zsgcoef1(3)
1291  ENDIF
1292 !
1293  IF(psnow > zsnowtrans)THEN
1294  psnowdz(1) = zsgcoef2(1)
1295  psnowdz(2) = (psnow-zsgcoef2(1))*zsgcoef2(2) + zsgcoef2(1)
1296 !
1297 ! When using simple finite differences, limit the thickness
1298 ! factor between the top and 2nd layers to at most 10
1299 !
1300  psnowdz(2) = min(10*zsgcoef2(1), psnowdz(2))
1301  psnowdz(3) = psnow - psnowdz(2) - psnowdz(1)
1302  END IF
1303 !
1304 !
1305 ! 2. Calculate current grid for 6-layer :
1306 ! ---------------------------------------------------------------
1307 !
1308 ELSEIF(inlvls == 6)THEN
1309 !
1310 ! critere a satisfaire pour remaillage
1311 !
1312  IF(PRESENT(psnowdz_old))THEN
1313  gregrid = psnowdz_old(1) < zcoef1 * min(zdz1 ,psnow/inlvls) .OR. &
1314  & psnowdz_old(1) > zcoef2 * min(zdz1 ,psnow/inlvls) .OR. &
1315  & psnowdz_old(2) < zcoef1 * min(zdz2 ,psnow/inlvls) .OR. &
1316  & psnowdz_old(2) > zcoef2 * min(zdz2 ,psnow/inlvls) .OR. &
1317  & psnowdz_old(6) < zcoef1 * min(zdzn1,psnow/inlvls) .OR. &
1318  & psnowdz_old(6) > zcoef2 * min(zdzn1,psnow/inlvls)
1319  ENDIF
1320 !
1321  IF(gregrid)THEN
1322 ! top layers
1323  psnowdz(1) = min(zdz1,psnow/inlvls)
1324  psnowdz(2) = min(zdz2,psnow/inlvls)
1325 ! last layers
1326  psnowdz(6) = min(zdzn1,psnow/inlvls)
1327 ! remaining snow for remaining layers
1328  zwork = psnow - psnowdz(1) - psnowdz(2) - psnowdz(6)
1329  psnowdz(3) = zwork*zsgcoef(1)
1330  psnowdz(4) = zwork*zsgcoef(2)
1331  psnowdz(5) = zwork*zsgcoef(3)
1332 ! layer 3 tickness >= layer 2 tickness
1333  zwork=min(0.0,psnowdz(3)-psnowdz(2))
1334  psnowdz(3)=psnowdz(3)-zwork
1335  psnowdz(4)=psnowdz(4)+zwork
1336 ! layer 5 tickness >= layer 6 tickness
1337  zwork=min(0.0,psnowdz(5)-psnowdz(6))
1338  psnowdz(5)=psnowdz(5)-zwork
1339  psnowdz(4)=psnowdz(4)+zwork
1340  ENDIF
1341 !
1342 ! 3. Calculate current grid for 9-layer :
1343 ! ---------------------------------------------------------------
1344 !
1345 ELSEIF(inlvls == 9)THEN
1346 !
1347 ! critere a satisfaire pour remaillage
1348 !
1349  IF(PRESENT(psnowdz_old))THEN
1350  gregrid = psnowdz_old(1) < zcoef1 * min(zdz1 ,psnow/inlvls) .OR. &
1351  & psnowdz_old(1) > zcoef2 * min(zdz1 ,psnow/inlvls) .OR. &
1352  & psnowdz_old(2) < zcoef1 * min(zdz2 ,psnow/inlvls) .OR. &
1353  & psnowdz_old(2) > zcoef2 * min(zdz2 ,psnow/inlvls) .OR. &
1354  & psnowdz_old(9) < zcoef1 * min(zdzn0,psnow/inlvls) .OR. &
1355  & psnowdz_old(9) > zcoef2 * min(zdzn0,psnow/inlvls)
1356  ENDIF
1357 !
1358  IF(gregrid)THEN
1359 ! top layers
1360  psnowdz(1) = min(zdz1,psnow/inlvls)
1361  psnowdz(2) = min(zdz2,psnow/inlvls)
1362  psnowdz(3) = min(zdz3,psnow/inlvls)
1363 ! last layers
1364  psnowdz(9)= min(zdzn0,psnow/inlvls)
1365  psnowdz(8)= min(zdzn1,psnow/inlvls)
1366  psnowdz(7)= min(zdzn2,psnow/inlvls)
1367 ! remaining snow for remaining layers
1368  zwork = psnow - psnowdz( 1) - psnowdz( 2) - psnowdz( 3) &
1369  - psnowdz( 7) - psnowdz( 8) - psnowdz( 9)
1370  psnowdz(4) = zwork*zsgcoef(1)
1371  psnowdz(5) = zwork*zsgcoef(2)
1372  psnowdz(6) = zwork*zsgcoef(3)
1373 ! layer 4 tickness >= layer 3 tickness
1374  zwork=min(0.0,psnowdz(4)-psnowdz(3))
1375  psnowdz(4)=psnowdz(4)-zwork
1376  psnowdz(5)=psnowdz(5)+zwork
1377 ! layer 6 tickness >= layer 7 tickness
1378  zwork=min(0.0,psnowdz(6)-psnowdz(7))
1379  psnowdz(6)=psnowdz(6)-zwork
1380  psnowdz(5)=psnowdz(5)+zwork
1381  ENDIF
1382 !
1383 ! 4. Calculate current grid for 12-layer :
1384 ! ---------------------------------------------------------------
1385 !
1386 ELSEIF(inlvls == 12)THEN
1387 !
1388 ! modif_EB pour maillage
1389 ! critere a satisfaire pour remaillage
1390  IF(PRESENT(psnowdz_old))THEN
1391  gregrid = psnowdz_old(1) < zcoef1 * min(zdz1 ,psnow/inlvls) .OR. &
1392  & psnowdz_old(1) > zcoef2 * min(zdz1 ,psnow/inlvls) .OR. &
1393  & psnowdz_old(2) < zcoef1 * min(zdz2 ,psnow/inlvls) .OR. &
1394  & psnowdz_old(2) > zcoef2 * min(zdz2 ,psnow/inlvls) .OR. &
1395  & psnowdz_old(12) < zcoef1 * min(zdzn0,psnow/inlvls) .OR. &
1396  & psnowdz_old(12) > zcoef2 * min(zdzn0,psnow/inlvls)
1397  ENDIF
1398 !
1399  IF (gregrid)THEN
1400 ! top layers
1401  psnowdz(1) = min(zdz1,psnow/inlvls)
1402  psnowdz(2) = min(zdz2,psnow/inlvls)
1403  psnowdz(3) = min(zdz3,psnow/inlvls)
1404  psnowdz(4) = min(zdz4,psnow/inlvls)
1405  psnowdz(5) = min(zdz5,psnow/inlvls)
1406 ! last layers
1407  psnowdz(12)= min(zdzn0,psnow/inlvls)
1408  psnowdz(11)= min(zdzn1,psnow/inlvls)
1409  psnowdz(10)= min(zdzn2,psnow/inlvls)
1410  psnowdz( 9)= min(zdzn3,psnow/inlvls)
1411 ! remaining snow for remaining layers
1412  zwork = psnow - psnowdz( 1) - psnowdz( 2) - psnowdz( 3) &
1413  - psnowdz( 4) - psnowdz( 5) - psnowdz( 9) &
1414  - psnowdz(10) - psnowdz(11) - psnowdz(12)
1415  psnowdz(6) = zwork*zsgcoef(1)
1416  psnowdz(7) = zwork*zsgcoef(2)
1417  psnowdz(8) = zwork*zsgcoef(3)
1418 ! layer 6 tickness >= layer 5 tickness
1419  zwork=min(0.0,psnowdz(6)-psnowdz(5))
1420  psnowdz(6)=psnowdz(6)-zwork
1421  psnowdz(7)=psnowdz(7)+zwork
1422 ! layer 8 tickness >= layer 9 tickness
1423  zwork=min(0.0,psnowdz(8)-psnowdz(9))
1424  psnowdz(8)=psnowdz(8)-zwork
1425  psnowdz(7)=psnowdz(7)+zwork
1426  ENDIF
1427 !
1428 ! 4. Calculate other non-optimized grid to allow CROCUS PREP :
1429 ! ------------------------------------------------------------
1430 !
1431 ELSE IF(inlvls<10.AND.inlvls/=3.AND.inlvls/=6.AND.inlvls/=9) THEN
1432 !
1433  DO jj=1,inlvls
1434  psnowdz(jj) = psnow/inlvls
1435  ENDDO
1436 !
1437  psnowdz(inlvls) = psnowdz(inlvls) + (psnowdz(1) - min(0.05, psnowdz(1)))
1438  psnowdz(1) = min(0.05, psnowdz(1))
1439 !
1440 ELSE
1441 !
1442  IF(PRESENT(psnowdz_old))THEN
1443  gregrid = psnowdz_old( 1) < zcoef1 * min(zdz1 ,psnow/inlvls) .OR. &
1444  & psnowdz_old( 1) > zcoef2 * min(zdz1 ,psnow/inlvls) .OR. &
1445  & psnowdz_old( 2) < zcoef1 * min(zdz2 ,psnow/inlvls) .OR. &
1446  & psnowdz_old( 2) > zcoef2 * min(zdz2 ,psnow/inlvls) .OR. &
1447  & psnowdz_old(inlvls) < zcoef1 * min(0.05*psnow,psnow/inlvls) .OR. &
1448  & psnowdz_old(inlvls) > zcoef2 * min(0.05*psnow,psnow/inlvls)
1449  ENDIF
1450 !
1451  IF (gregrid)THEN
1452  psnowdz( 1) = min(zdz1 ,psnow/inlvls)
1453  psnowdz( 2) = min(zdz2 ,psnow/inlvls)
1454  psnowdz( 3) = min(zdz3 ,psnow/inlvls)
1455  psnowdz( 4) = min(zdz4 ,psnow/inlvls)
1456  psnowdz( 5) = min(zdz5 ,psnow/inlvls)
1457  psnowdz(inlvls) = min(0.05*psnow,psnow/inlvls)
1458  zwork = sum(psnowdz(1:5))
1459  DO jj=6,inlvls-1,1
1460  psnowdz(jj) = (psnow - zwork -psnowdz(inlvls))/(inlvls-6)
1461  END DO
1462  ENDIF
1463 !
1464 ENDIF
1465 !
1466 DO jj=1,inlvls
1467  IF(psnow==xundef)THEN
1468  psnowdz(jj) = xundef
1469  ELSEIF(.NOT.gregrid)THEN
1470  psnowdz(jj) = psnowdz_old(jj)
1471  ENDIF
1472 END DO
1473 !
1474 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LGRID_1D',1,zhook_handle)
1475 !
1476 END SUBROUTINE snow3lgrid_1d
1477 !
1478 !###################################################################################
1479 !###################################################################################
1480 SUBROUTINE snow3lagreg(PSNOWDZN,PSNOWDZ,PSNOWRHO,PSNOWGRAN1, PSNOWGRAN2, &
1481  PSNOWHIST,PSNOWGRAN1N,PSNOWGRAN2N,PSNOWHISTN, &
1482  KL1,KL2,PSNOWDDZ )
1483 !
1484 USE modd_snow_metamo
1485 !
1486 USE yomhook ,ONLY : lhook, dr_hook
1487 USE parkind1 ,ONLY : jprb
1488 !
1489 IMPLICIT NONE
1490 !
1491 ! 0.1 declarations of arguments
1492 !
1493 REAL, DIMENSION(:), INTENT(IN) :: PSNOWDZN,PSNOWDZ,PSNOWRHO,PSNOWDDZ
1494 !
1495 REAL, DIMENSION(:), INTENT(IN) :: PSNOWGRAN1,PSNOWGRAN2,PSNOWHIST
1496 REAL, DIMENSION(:), INTENT(OUT) :: PSNOWGRAN1N,PSNOWGRAN2N,PSNOWHISTN
1497 !
1498 INTEGER, INTENT(IN) :: KL1 ! Indice couche de reference (i)
1499 INTEGER, INTENT(IN) :: KL2 ! Indice de la couche (i-1 ou i+1) dont une
1500  ! partie est aggregee à la couche (i)
1501 !
1502 ! 0.2 declaration of local variables
1503 !
1504 REAL, DIMENSION(SIZE(PSNOWRHO,1)) :: ZSNOWRHO
1505 REAL, DIMENSION(SIZE(PSNOWRHO,1)) :: ZDIAMD,ZDIAMV,ZSPHERD,ZSPHERV,&
1506  ZDIAMN,ZSPHERN,ZDENT
1507 !
1508 REAL :: ZDELTA, ZCOMP
1509 !
1510 INTEGER :: IDENT, IVIEU, IL
1511 !
1512 REAL(KIND=JPRB) :: ZHOOK_HANDLE
1513 !
1514 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LAGREG',0,zhook_handle)
1515 !
1516 IF( kl1<kl2 ) THEN
1517  zdelta = 0.0
1518  il = kl1
1519 ELSE
1520  zdelta = 1.0
1521  il = kl2
1522 ENDIF
1523 !
1524 ! Mean Properties
1525 !
1526 ! 1. History
1527 !
1528 IF ( psnowhist(kl1)/=psnowhist(kl2) ) THEN
1529  psnowhistn(kl1) = 0.0
1530 ENDIF
1531 !
1532 ! 2. New grain types
1533 !
1534 ! 2.1 Same grain type
1535 !
1536 IF ( psnowgran1(kl1)*psnowgran1(kl2)>0.0 .OR. &
1537  ( psnowgran1(kl1)==0.0 .AND. psnowgran1(kl2)>=0.0 ) .OR. &
1538  ( psnowgran1(kl2)==0.0 .AND. psnowgran1(kl1)>=0.0 ) ) THEN
1539  !
1540  !code original vincent PSNOWGRAN1N(KL1)=(PSNOWGRAN1(KL1)*PSNOWRHO(KL1)&
1541  !code original vincent *(PSNOWDZN(KL1)-(1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))-ZDELTA*&
1542  !code original vincent ABS(PSNOWDDZ(KL2)))+PSNOWGRAN1(KL2)* &
1543  !code original vincent PSNOWRHO(KL2)*((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ &
1544  !code original vincent ZDELTA*ABS(PSNOWDDZ(KL2))))/((PSNOWDZN(KL1)-(1.0-ZDELTA)&
1545  !code original vincent *ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2)))* &
1546  !code original vincent PSNOWRHO(KL1)+((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ &
1547  !code original vincent ZDELTA*ABS(PSNOWDDZ(KL2)))*PSNOWRHO(KL2))
1548  !code original vincent !
1549  !code original vincent PSNOWGRAN2N(KL1)=(PSNOWGRAN2(KL1)*PSNOWRHO(KL1) &
1550  !code original vincent *(PSNOWDZN(KL1)-(1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))-ZDELTA* &
1551  !code original vincent ABS(PSNOWDDZ(KL2)))+PSNOWGRAN2(KL2)* &
1552  !code original vincent PSNOWRHO(KL2)*((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1)) &
1553  !code original vincent +ZDELTA*ABS(PSNOWDDZ(KL2))))/((PSNOWDZN(KL1)-(1.0-ZDELTA)&
1554  !code original vincent *ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2)))* &
1555  !code original vincent PSNOWRHO(KL1)+((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ &
1556  !code original vincent ZDELTA*ABS(PSNOWDDZ(KL2)))*PSNOWRHO(KL2))
1557  !
1558  !plm
1559  CALL get_agreg(kl1,kl2,psnowgran1(kl1),psnowgran1(kl2),psnowgran1n(kl1))
1560  !
1561  CALL get_agreg(kl1,kl2,psnowgran2(kl1),psnowgran2(kl2),psnowgran2n(kl1))
1562  !
1563  !plm
1564  !
1565 ELSE
1566  !
1567  ! 2.2 Different types
1568  !
1569  IF ( psnowgran1(kl1)<0.0 ) THEN
1570  ident = kl1
1571  ivieu = kl2
1572  ELSE
1573  ident = kl2
1574  ivieu = kl1
1575  ENDIF
1576  !
1577  zdiamd(kl1) = - psnowgran1(ident)/xgran * xdiaet + ( 1.0 + psnowgran1(ident)/xgran ) * &
1578  ( psnowgran2(ident)/xgran * xdiagf + ( 1.0 - psnowgran2(ident)/xgran ) * xdiafp )
1579  !
1580  zspherd(kl1) = psnowgran2(ident)/xgran
1581  zdiamv(kl1) = psnowgran2(ivieu)
1582  zspherv(kl1) = psnowgran1(ivieu)/xgran
1583  !IF(KL1==1)THEN
1584  !write(*,*) 'ZDD1',ZDIAMD(1),'ZSD1',ZSPHERD(1)
1585  !write(*,*) 'ZDV1',ZDIAMV(1),'ZSV1',ZSPHERV(1)
1586  !ENDIF
1587  !
1588  IF ( ident==kl1 ) THEN
1589  !code original vincent ZDIAMN(KL1)= (ZDIAMD(KL1)*PSNOWRHO(IDENT)*&
1590  !code original vincent (PSNOWDZN(IDENT)-(1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))-ZDELTA* &
1591  !code original vincent ABS(PSNOWDDZ(KL2)))+ZDIAMV(KL1)*PSNOWRHO(IVIEU)*( &
1592  !code original vincent (1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2))))/&
1593  !code original vincent ((PSNOWDZN(KL1)-(1.0-ZDELTA)* &
1594  !code original vincent ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2)))* &
1595  !code original vincent PSNOWRHO(KL1)+((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ &
1596  !code original vincent ZDELTA*ABS(PSNOWDDZ(KL2)))*PSNOWRHO(KL2))
1597  !
1598  !plm
1599  CALL get_agreg(ident,ivieu,zdiamd(kl1),zdiamv(kl1),zdiamn(kl1))
1600  !
1601  !plm
1602  !
1603  !code original vincent ZSPHERN(KL1)= (ZSPHERD(KL1)*PSNOWRHO(IDENT)*&
1604  !code original vincent (PSNOWDZN(IDENT)-(1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))-ZDELTA* &
1605  !code original vincent ABS(PSNOWDDZ(KL2)))+ZSPHERV(KL1)*PSNOWRHO(IVIEU)*( &
1606  !code original vincent (1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2))))/&
1607  !code original vincent ((PSNOWDZN(KL1)-(1.0-ZDELTA)* &
1608  !code original vincent ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2)))* &
1609  !code original vincent PSNOWRHO(KL1)+((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ &
1610  !code original vincent ZDELTA*ABS(PSNOWDDZ(KL2)))*PSNOWRHO(KL2))
1611 
1612  !plm
1613  CALL get_agreg(ident,ivieu,zspherd(kl1),zspherv(kl1),zsphern(kl1))
1614  !plm
1615  !
1616  ELSE
1617  !code original vincent ZDIAMN(KL1)= (ZDIAMD(KL1)*PSNOWRHO(IDENT)*&
1618  !code original vincent ((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ZDELTA*ABS(PSNOWDDZ(KL2)))&
1619  !code original vincent +ZDIAMV(KL1)*PSNOWRHO(IVIEU)*(PSNOWDZN(IVIEU)-(1.0-ZDELTA)* &
1620  !code original vincent ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2))))/&
1621  !code original vincent ((PSNOWDZN(KL1)-(1.0-ZDELTA)* &
1622  !code original vincent ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2)))* &
1623  !code original vincent PSNOWRHO(KL1)+((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ &
1624  !code original vincent ZDELTA*ABS(PSNOWDDZ(KL2)))*PSNOWRHO(KL2))
1625  !code original vincent!
1626  !code original vincent ZSPHERN(KL1)= (ZSPHERD(KL1)*PSNOWRHO(IDENT)*&
1627  !code original vincent ((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ZDELTA*ABS(PSNOWDDZ(KL2)))&
1628  !code original vincent +ZSPHERV(KL1)*PSNOWRHO(IVIEU)*(PSNOWDZN(IVIEU)-(1.0-ZDELTA)* &
1629  !code original vincent ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2))))/&
1630  !code original vincent ((PSNOWDZN(KL1)-(1.0-ZDELTA)* &
1631  !code original vincent ABS(PSNOWDDZ(KL1))-ZDELTA*ABS(PSNOWDDZ(KL2)))* &
1632  !code original vincent PSNOWRHO(KL1)+((1.0-ZDELTA)*ABS(PSNOWDDZ(KL1))+ &
1633  !code original vincent ZDELTA*ABS(PSNOWDDZ(KL2)))*PSNOWRHO(KL2))
1634  !plm
1635  !
1636  CALL get_agreg(ivieu,ident,zdiamv(kl1),zdiamd(kl1),zdiamn(kl1))
1637  !
1638  CALL get_agreg(ivieu,ident,zspherv(kl1),zspherd(kl1),zsphern(kl1))
1639  !plm
1640  !
1641  ENDIF
1642  !
1643  zcomp = zsphern(kl1) * xdiagf + ( 1.-zsphern(kl1) ) * xdiafp
1644  IF( zdiamn(kl1) < zcomp ) THEN
1645  !
1646  zdent(kl1) = ( zdiamn(kl1) - zcomp ) / ( xdiaet - zcomp )
1647  !IF(KL1==1) write(*,*) 'ZDENT',ZDENT(1)
1648  psnowgran1n(kl1) = - xgran * zdent(kl1)
1649  psnowgran2n(kl1) = xgran * zsphern(kl1)
1650  !
1651  ELSE
1652  !
1653  psnowgran1n(kl1) = xgran * zsphern(kl1)
1654  psnowgran2n(kl1) = zdiamn(kl1)
1655  !
1656  ENDIF
1657  !
1658 ENDIF
1659 !
1660 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LAGREG',1,zhook_handle)
1661 !
1662 ! 3. Update snow grains parameters : GRAN1, GRAN2
1663 ! PSNOWGRAN1(KL1)=ZSNOWGRAN1(KL1)
1664 ! PSNOWGRAN2(KL1)=ZSNOWGRAN2(KL1)
1665 !
1666 CONTAINS
1667 !
1668 SUBROUTINE get_agreg(KID1,KID2,PFIELD1,PFIELD2,PFIELD)
1670 INTEGER, INTENT(IN) :: KID1, KID2
1671 REAL, INTENT(IN) :: PFIELD1, PFIELD2
1672 REAL, INTENT(OUT) :: PFIELD
1673 !
1674 REAL(KIND=JPRB) :: ZHOOK_HANDLE
1675 !
1676 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LAGREG:GET_AGREG',0,zhook_handle)
1677 !
1678 pfield = ( pfield1 * psnowrho(kid1) * ( psnowdzn(kid1) - abs(psnowddz(il)) ) &
1679  + pfield2 * psnowrho(kid2) * abs(psnowddz(il)) ) / &
1680  ( psnowrho(kl1) * ( psnowdzn(kl1) - abs(psnowddz(il)) ) + &
1681  psnowrho(kl2) * abs(psnowddz(il)) )
1682 !
1683 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LAGREG:GET_AGREG',1,zhook_handle)
1684 !
1685 END SUBROUTINE get_agreg
1686 !
1687 END SUBROUTINE snow3lagreg
1688 !###############################################################################
1689 !###############################################################################
1690 !
1691 !
1692 !ajout EB : ajout des arguments "N" pour faire idem variables d'origine
1693 SUBROUTINE snow3lavgrain(PSNOWGRAN1,PSNOWGRAN2,PSNOWHIST, &
1694  PSNOWGRAN1N,PSNOWGRAN2N,PSNOWHISTN,PNDENT,PNVIEU,&
1695  HSNOWMETAMO)
1696 !
1697 USE modd_snow_metamo, ONLY : xvdiam6, xuepsi
1698 !
1699 USE yomhook ,ONLY : lhook, dr_hook
1700 USE parkind1 ,ONLY : jprb
1701 !
1702 IMPLICIT NONE
1703 !
1704 ! 0.1 declarations of arguments
1705 !
1706 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWGRAN1,PSNOWGRAN2,PSNOWHIST
1707 ! ajout EB
1708 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWGRAN1N,PSNOWGRAN2N,PSNOWHISTN
1709 !
1710 REAL, DIMENSION(:), INTENT(IN) :: PNDENT, PNVIEU
1711 !
1712  CHARACTER(3), INTENT(IN) :: HSNOWMETAMO
1713 ! 0.2 declaration of local variables
1714 !
1715 REAL, DIMENSION(SIZE(PSNOWGRAN1,1)) :: ZGRAN1, ZGRAN2, ZHIST
1716 !
1717 LOGICAL, DIMENSION(SIZE(PSNOWGRAN1,1),SIZE(PSNOWGRAN1,2)) :: GDENDRITIC
1718 !
1719 INTEGER :: JI, JL
1720 INTEGER :: INLVLS, INI
1721 !
1722 REAL(KIND=JPRB) :: ZHOOK_HANDLE
1723 !
1724 ! 0.3 initialization
1725 !
1726 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LAVGRAIN',0,zhook_handle)
1727 !
1728 inlvls = SIZE(psnowgran1,2)
1729 ini = SIZE(psnowgran1,1)
1730 !
1731 zgran1(:) = 0.0
1732 zgran2(:) = 0.0
1733 zhist(:) = 0.0
1734 !
1735 DO ji = 1,ini
1736  !
1737  IF ( pndent(ji)==0.0 .AND. pnvieu(ji)==0.0 ) THEN
1738  !
1739  zgran1(ji) = 1.0
1740  zgran2(ji) = 1.0
1741  zhist(ji) = 1.0
1742  !
1743  ELSE
1744  !
1745  DO jl = 1,inlvls
1746  IF ( hsnowmetamo=='B92' ) THEN
1747  gdendritic(ji,jl) = ( psnowgran1(ji,jl) < 0.0 )
1748  ELSE
1749  gdendritic(ji,jl) = ( psnowgran1(ji,jl) < xvdiam6*(4.-psnowgran2(ji,jl)) - xuepsi )
1750  ENDIF
1751  ENDDO
1752  !
1753  IF ( pndent(ji)>=pnvieu(ji) ) THEN ! more dendritic than non dendritic snow layer
1754  !
1755  DO jl = 1,inlvls
1756  IF ( gdendritic(ji,jl) ) THEN
1757  zgran1(ji) = zgran1(ji) + psnowgran1(ji,jl)
1758  zgran2(ji) = zgran2(ji) + psnowgran2(ji,jl)
1759  ENDIF
1760  ENDDO
1761  !
1762  psnowgran1n(ji,:) = zgran1(ji) / pndent(ji)
1763  psnowgran2n(ji,:) = zgran2(ji) / pndent(ji)
1764  psnowhistn(ji,:) = 0.0
1765  !
1766  ELSE ! more non dendritic than dendritic snow layers
1767  !
1768  DO jl = 1,inlvls
1769  IF ( .NOT.gdendritic(ji,jl) ) THEN
1770  zgran1(ji) = zgran1(ji) + psnowgran1(ji,jl)
1771  zgran2(ji) = zgran2(ji) + psnowgran2(ji,jl)
1772  zhist(ji) = zhist(ji) + psnowhist(ji,jl)
1773  ENDIF
1774  ENDDO
1775  !
1776  psnowgran1n(ji,:) = zgran1(ji) / pnvieu(ji)
1777  psnowgran2n(ji,:) = zgran2(ji) / pnvieu(ji)
1778  psnowhistn(ji,:) = zhist(ji) / pnvieu(ji)
1779  !
1780  ENDIF
1781  !
1782  ENDIF
1783  !
1784 ENDDO
1785 
1786 
1787 
1788 !
1789 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LAVGRAIN',1,zhook_handle)
1790 !
1791 END SUBROUTINE snow3lavgrain
1792 !
1793 !####################################################################
1794 !####################################################################
1795 !####################################################################
1796 FUNCTION snow3ldiftyp(PGRAIN1,PGRAIN2,PGRAIN3,PGRAIN4,HSNOWMETAMO) RESULT(ZDIFTYPE)
1798 ! à remplacer sans doute par une routine equivalente du nouveau crocus
1799 !* CALCUL DE LA DIFFERENCE ENTRE DEUX TYPES DE GRAINS
1800 ! VALEUR ENTRE 200 ET 0
1801 !
1802 USE modd_snow_metamo, ONLY : xgran, xvdiam6, xuepsi
1803 !
1804 USE yomhook ,ONLY : lhook, dr_hook
1805 USE parkind1 ,ONLY : jprb
1806 !
1807 IMPLICIT NONE
1808 !* 0.1 declarations of arguments
1809 REAL, INTENT(IN) :: PGRAIN1, PGRAIN2, PGRAIN3, PGRAIN4
1810  CHARACTER(3), INTENT(IN) :: HSNOWMETAMO
1811 REAL :: ZDIFTYPE, ZCOEF3, ZCOEF4
1812 REAL(KIND=JPRB) :: ZHOOK_HANDLE
1813 
1814 !* 0.2 calcul de la difference entre type de grains
1815 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LDIFTYP',0,zhook_handle)
1816 !
1817 IF ( hsnowmetamo=='B92' ) THEN
1818  !
1819  IF ( ( pgrain1<0. .AND. pgrain2>=0.) .OR. ( pgrain1>=0. .AND. pgrain2<0. ) ) THEN
1820  zdiftype = 200.
1821  ELSEIF ( pgrain1<0. ) THEN
1822  zdiftype = abs( pgrain1-pgrain2 ) * .5 + abs( pgrain3-pgrain4 ) * .5
1823  ELSE
1824  zdiftype = abs( pgrain1-pgrain2 ) + abs( pgrain3-pgrain4 ) * 5. * 10000.
1825  ENDIF
1826  !
1827 ELSE
1828  !
1829  zcoef3 = xvdiam6 * (4.-pgrain3) - xuepsi
1830  zcoef4 = xvdiam6 * (4.-pgrain4) - xuepsi
1831  IF ( ( pgrain1<zcoef3 .AND. pgrain2>=zcoef4 ) .OR. ( pgrain1>=zcoef3 .AND. pgrain2<zcoef4 ) ) THEN
1832  zdiftype = 200.
1833  ELSEIF ( pgrain1<zcoef3 ) THEN
1834  zdiftype = abs( (pgrain3-pgrain4)*xgran ) * .5 + &
1835  abs( ( (pgrain1/xvdiam6 - 4. + pgrain3) / (pgrain3 - 3.) - &
1836  (pgrain2/xvdiam6 - 4. + pgrain4) / (pgrain4 - 3.) ) * xgran ) * .5
1837 
1838  ELSE
1839  zdiftype = abs( (pgrain3-pgrain4)*xgran ) + abs( zcoef3-zcoef4 ) * 5. * 10000.
1840  ENDIF
1841  !
1842 ENDIF
1843 !
1844 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LDIFTYP',1,zhook_handle)
1845 !
1846 END FUNCTION snow3ldiftyp
1847 
1848 !####################################################################
1849 SUBROUTINE get_mass_heat(KJ,KNLVLS_NEW,KNLVLS_OLD, &
1850  PSNOWZTOP_OLD,PSNOWZTOP_NEW,PSNOWZBOT_OLD,PSNOWZBOT_NEW, &
1851  PSNOWRHOO,PSNOWDZO,PSNOWGRAN1O,PSNOWGRAN2O,PSNOWHISTO, &
1852  PSNOWAGEO,PSNOWHEATO, &
1853  PSNOWRHON,PSNOWDZN,PSNOWGRAN1N,PSNOWGRAN2N,PSNOWHISTN, &
1854  PSNOWAGEN, PSNOWHEATN,HSNOWMETAMO )
1855 !
1856 USE modd_snow_par, ONLY : xsnowcritd, xd1, xd2, xd3, xx, xvalb5, xvalb6
1857 !
1858 USE yomhook ,ONLY : lhook, dr_hook
1859 USE parkind1 ,ONLY : jprb
1860 !
1861 IMPLICIT NONE
1862 !
1863 INTEGER, INTENt(IN) :: KJ
1864 INTEGER, INTENT(IN) :: KNLVLS_NEW, KNLVLS_OLD
1865 REAL, DIMENSION(:), INTENT(IN) :: PSNOWZTOP_OLD, PSNOWZBOT_OLD
1866 REAL, DIMENSION(:), INTENT(IN) :: PSNOWZTOP_NEW, PSNOWZBOT_NEW
1867 REAL, DIMENSION(:), INTENT(IN) :: PSNOWRHOO, PSNOWDZO, PSNOWGRAN1O, PSNOWGRAN2O, &
1868  PSNOWHISTO, PSNOWAGEO, PSNOWHEATO
1869 REAL, DIMENSION(:), INTENT(IN) :: PSNOWDZN
1870  CHARACTER(3), INTENT(IN) :: HSNOWMETAMO
1871 REAL, DIMENSION(:), INTENT(OUT) :: PSNOWRHON, PSNOWGRAN1N, PSNOWGRAN2N, &
1872  PSNOWHISTN, PSNOWAGEN, PSNOWHEATN
1873 !
1874 REAL :: ZPROPOR, ZMASDZ_OLD, ZDIAM, ZMASTOT_T07
1875 REAL :: ZSNOWHEAN, ZMASTOTN, ZDENTMOYN, ZSPHERMOYN, ZALBMOYN, ZHISTMOYN
1876 REAL :: ZAGEMOYN
1877 !
1878 INTEGER :: JST_NEW, JST_OLD
1879 !
1880 REAL(KIND=JPRB) :: ZHOOK_HANDLE
1881 !
1882 IF (lhook) CALL dr_hook('GET_MASS_HEAT',0,zhook_handle)
1883 !
1884 psnowrhon(:) = 0.
1885 psnowgran1n(:) = 0.
1886 psnowgran2n(:) = 0.
1887 psnowhistn(:) = 0.
1888 psnowagen(:) = 0.
1889 psnowheatn(:) = 0.
1890 !
1891 DO jst_new = 1,knlvls_new
1892  !
1893  zsnowhean = 0.
1894  zmastotn = 0.
1895  zmastot_t07 = 0.
1896  zdentmoyn = 0.
1897  zsphermoyn = 0.
1898  zalbmoyn = 0.
1899  zdiam = 0.
1900  zhistmoyn = 0.
1901  zagemoyn = 0.
1902  !
1903  ! lopp over the ols snow layers
1904  DO jst_old = 1,knlvls_old
1905  !
1906  IF( psnowztop_old(jst_old)<=psnowzbot_new(jst_new) ) THEN
1907  ! JST_OLD lower than JJ_NEW ==> no contribution
1908  ELSEIF ( psnowzbot_old(jst_old)>=psnowztop_new(jst_new) ) THEN
1909  ! JST_OLD higher than JJ_NEW ==> no contribution
1910  ELSE
1911  ! old layer contributes to the new one
1912  ! computation of its contributing ratio and mass/heat
1913  zpropor = ( min( psnowztop_old(jst_old), psnowztop_new(jst_new) ) &
1914  - max( psnowzbot_old(jst_old), psnowzbot_new(jst_new) ) ) &
1915  / psnowdzo(jst_old)
1916  zmasdz_old = zpropor * psnowrhoo(jst_old) * psnowdzo(jst_old)
1917  !
1918  zmastotn = zmastotn + zmasdz_old
1919  zmastot_t07 = zmastot_t07 + 1.
1920  !
1921  zsnowhean = zsnowhean + zpropor * psnowheato(jst_old)
1922  !
1923  IF ( hsnowmetamo=='B92' ) THEN
1924  !
1925  ! contribution to the grain optical size and then to the albedo
1926  IF ( psnowgran1o(jst_old)<0. ) THEN
1927  zdiam = -psnowgran1o(jst_old)*xd1/xx + (1.+psnowgran1o(jst_old)/xx) * &
1928  ( psnowgran2o(jst_old)*xd2/xx + (1.-psnowgran2o(jst_old)/xx)*xd3 )
1929  zdiam = zdiam/10000.
1930  zdentmoyn = zdentmoyn - zmasdz_old * psnowgran1o(jst_old) / xx
1931  zsphermoyn = zsphermoyn + zmasdz_old * psnowgran2o(jst_old) / xx
1932  ELSE
1933  zdiam = psnowgran2o(jst_old)
1934  zdentmoyn = zdentmoyn + zmasdz_old * 0.
1935  zsphermoyn = zsphermoyn + zmasdz_old * psnowgran1o(jst_old) / xx
1936  ENDIF
1937  !
1938  ELSE
1939  !
1940  zdiam = psnowgran1o(jst_old)
1941  zsphermoyn = zsphermoyn + zmasdz_old * psnowgran2o(jst_old)
1942  !
1943  ENDIF
1944  !
1945  zalbmoyn = zalbmoyn + max( 0., zmasdz_old * (xvalb5-xvalb6*sqrt(zdiam)) )
1946  zhistmoyn = zhistmoyn + zmasdz_old * psnowhisto(jst_old)
1947  zagemoyn = zagemoyn + zmasdz_old * psnowageo(jst_old)
1948  !
1949  ENDIF
1950  !
1951  ENDDO
1952  !
1953  ! the new layer inherits from the weihted average properties of the old ones
1954  ! heat and mass
1955  psnowheatn(jst_new) = zsnowhean
1956  psnowrhon(jst_new) = zmastotn / psnowdzn(jst_new)
1957  ! grain type and size decuced from the average albedo
1958  zalbmoyn = zalbmoyn / zmastotn
1959  zsphermoyn = max( 0., zsphermoyn/zmastotn )
1960  zdentmoyn = max( 0., zdentmoyn /zmastotn )
1961  zdiam = ( (xvalb5-zalbmoyn)/xvalb6 )**2
1962  !
1963  IF ( hsnowmetamo=='B92' ) THEN
1964  !
1965  ! size between D2 and D3 and dendricity < 0
1966  ! sphericity is firts preserved, if possible. If not,
1967  ! denditricity =0
1968  psnowgran1n(jst_new) = -xx * zdentmoyn
1969  !
1970  IF ( zdentmoyn/=1.) THEN
1971  psnowgran2n(jst_new) = xx * ( ( zdiam*10000. + psnowgran1n(jst_new)*xd1/xx ) &
1972  / ( 1. + psnowgran1n(jst_new)/xx ) - xd3 ) &
1973  / ( xd2-xd3 )
1974  ENDIF
1975  !
1976  ! dendricity is preserved if possible and sphericity is adjusted
1977  IF ( zdiam < xd2/10000. - 0.0000001 ) THEN
1978  !
1979  IF ( abs( psnowgran1n(jst_new)+xx ) < 0.01 ) THEN
1980  !
1981  psnowgran2n(jst_new) = xx * zsphermoyn
1982  !
1983  ELSEIF ( abs( psnowgran1n(jst_new) ) < 0.0001 ) THEN ! dendritic snow
1984  !
1985  psnowgran1n(jst_new) = xx * zsphermoyn
1986  psnowgran2n(jst_new) = zdiam
1987  !
1988  ELSEIF ( psnowgran2n(jst_new) < 0. ) THEN ! non dendritic
1989  !
1990  psnowgran2n(jst_new) = 0.
1991  !
1992  ELSEIF ( psnowgran2n(jst_new) > xx + 0.0000001 ) THEN ! non dendritic
1993  !
1994  psnowgran2n(jst_new) = xx
1995  !
1996  ENDIF
1997  !
1998  ELSEIF ( zdiam > xd3/10000. .OR. zdentmoyn <= 0. + 0.0000001 .OR. &
1999  psnowgran2n(jst_new) < 0. .OR. psnowgran2n(jst_new) > xx ) THEN
2000  !
2001  ! dendritic snow
2002  ! inconsistency with ZDIAM ==> dendricity = 0
2003  ! size between D2 and D3 and dendricity == 0
2004  psnowgran1n(jst_new) = xx * zsphermoyn
2005  psnowgran2n(jst_new) = zdiam
2006  !
2007  ENDIF
2008  !
2009  ELSE
2010  !
2011  psnowgran1n(jst_new) = zdiam
2012  psnowgran2n(jst_new) = min( 1., zsphermoyn )
2013  !
2014  ENDIF
2015  !
2016  psnowhistn(jst_new) = nint( zhistmoyn/zmastotn )
2017  psnowagen(jst_new) = zagemoyn / zmastotn
2018  !
2019 ENDDO
2020 !
2021 IF (lhook) CALL dr_hook('GET_MASS_HEAT',1,zhook_handle)
2022 !
2023 END SUBROUTINE get_mass_heat
2024 !####################################################################
2025 SUBROUTINE get_diam(PSNOWGRAN1,PSNOWGRAN2,PDIAM,HSNOWMETAMO)
2027 USE modd_snow_par, ONLY : xd1, xd2, xd3, xx
2028 !
2029 USE yomhook ,ONLY : lhook, dr_hook
2030 USE parkind1 ,ONLY : jprb
2031 !
2032 IMPLICIT NONE
2033 !
2034 REAL, INTENT(IN) :: PSNOWGRAN1
2035 REAL, INTENT(IN) :: PSNOWGRAN2
2036 REAL, INTENT(OUT) :: PDIAM
2037 !
2038  CHARACTER(3), INTENT(IN) :: HSNOWMETAMO
2039 !
2040 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2041 !
2042 IF (lhook) CALL dr_hook('GET_DIAM',0,zhook_handle)
2043 !
2044 IF ( hsnowmetamo=='B92' ) THEN
2045  !
2046  IF( psnowgran1<0. ) THEN
2047  pdiam = -psnowgran1*xd1/xx + (1.+psnowgran1/xx) * &
2048  ( psnowgran2*xd2/xx + (1.-psnowgran2/xx) * xd3 )
2049  pdiam = pdiam/10000.
2050  ELSE
2051  pdiam = psnowgran2*psnowgran1/xx + &
2052  max( 0.0004, 0.5*psnowgran2 ) * ( 1.-psnowgran1/xx )
2053  ENDIF
2054  !
2055 ELSE
2056  !
2057  pdiam = psnowgran1
2058  !
2059 ENDIF
2060 !
2061 IF (lhook) CALL dr_hook('GET_DIAM',1,zhook_handle)
2062 !
2063 END SUBROUTINE get_diam
2064 !####################################################################
2065 !####################################################################
2066 !####################################################################
2067 FUNCTION snow3lradabs_0d(PSNOWRHO,PSNOWDZ,PSPECTRALALBEDO,PZENITH,PPERMSNOWFRAC,PDSGRAIN) RESULT(PCOEF)
2069 !! PURPOSE
2070 !! -------
2071 ! Calculate the transmission of shortwave radiation within the snowpack
2072 ! (with depth)
2073 ! A. Boone 02/2011
2074 ! A. Boone 11/2014 Updated to use spectral dependence.
2075 ! NOTE, assumes 3 spectral bands
2076 !
2077 USE modd_surf_par, ONLY : xundef
2079 USE modd_snow_par, ONLY : xvspec1,xvspec2,xvspec3,xvbeta1,xvbeta2, &
2080  xvbeta4,xvbeta3,xvbeta5, xmincoszen
2081 !
2082 USE yomhook ,ONLY : lhook, dr_hook
2083 USE parkind1 ,ONLY : jprb
2084 !
2085 IMPLICIT NONE
2086 !
2087 !* 0.1 declarations of arguments
2088 !
2089 REAL, INTENT(IN) :: PSNOWRHO ! snow density (kg m-3)
2090 REAL, INTENT(IN) :: PSNOWDZ ! layer thickness (m)
2091 REAL, INTENT(IN) :: PZENITH ! zenith angle (rad)
2092 REAL, INTENT(IN) :: PPERMSNOWFRAC ! permanent snow fraction (-)
2093 REAL, DIMENSION(:), INTENT(IN) :: PSPECTRALALBEDO ! spectral albedo (-)
2094 REAL, INTENT(IN) :: PDSGRAIN ! Snow optical grain diameter (m)
2095 !
2096 REAL :: PCOEF ! -
2097 !
2098 !* 0.2 declarations of local variables
2099 !
2100 REAL :: ZWORK, ZPROJLAT, &
2101  ZBETA1, ZBETA2, ZBETA3, &
2102  ZOPTICALPATH1, ZOPTICALPATH2, &
2103  ZOPTICALPATH3
2104 !
2105 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2106 !
2107 !-------------------------------------------------------------------------------
2108 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LRADABS_0D',0,zhook_handle)
2109 !
2110 ! Coefficient for taking into account the increase of path length of rays
2111 ! in snow due to zenithal angle
2112 !
2113 zprojlat = (1.0-ppermsnowfrac)+ppermsnowfrac/ &
2114  max(xmincoszen,cos(pzenith))
2115 !
2116 ! Extinction coefficient:
2117 !
2118 zwork = sqrt(pdsgrain)
2119 zbeta1 = max(xvbeta1*psnowrho/zwork,xvbeta2)
2120 zbeta2 = max(xvbeta3*psnowrho/zwork,xvbeta4)
2121 zbeta3 = xvbeta5
2122 !
2123 zopticalpath1 = zbeta1*psnowdz
2124 zopticalpath2 = zbeta2*psnowdz
2125 zopticalpath3 = xundef
2126 !
2127 IF(pspectralalbedo(3)==xundef)THEN
2128  pcoef = xsw_wght_vis*(1.0-pspectralalbedo(1))*exp(-zopticalpath1*zprojlat) &
2129  + xsw_wght_nir*(1.0-pspectralalbedo(2))*exp(-zopticalpath2*zprojlat)
2130 ELSE
2131  zopticalpath3 = zbeta3*psnowdz
2132  pcoef = xvspec1*(1.0-pspectralalbedo(1))*exp(-zopticalpath1*zprojlat) &
2133  + xvspec2*(1.0-pspectralalbedo(2))*exp(-zopticalpath2*zprojlat) &
2134  + xvspec3*(1.0-pspectralalbedo(3))*exp(-zopticalpath3*zprojlat)
2135 ENDIF
2136 !
2137 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LRADABS_0D',1,zhook_handle)
2138 !-------------------------------------------------------------------------------
2139 !
2140 END FUNCTION snow3lradabs_0d
2141 !####################################################################
2142 !####################################################################
2143 !####################################################################
2144 FUNCTION snow3lradabs_1d(PSNOWRHO,PSNOWDZ,PSPECTRALALBEDO,PZENITH,PPERMSNOWFRAC,PDSGRAIN) RESULT(PCOEF)
2146 !! PURPOSE
2147 !! -------
2148 ! Calculate the transmission of shortwave radiation within the snowpack
2149 ! (with depth)
2150 ! A. Boone 02/2011
2151 ! A. Boone 11/2014 Updated to use spectral dependence
2152 ! NOTE, assumes 3 spectral bands
2153 !
2154 USE modd_surf_par, ONLY : xundef
2156 USE modd_snow_par, ONLY : xvspec1,xvspec2,xvspec3,xvbeta1,xvbeta2, &
2157  xvbeta4,xvbeta3,xvbeta5, xmincoszen
2158 !
2159 USE yomhook ,ONLY : lhook, dr_hook
2160 USE parkind1 ,ONLY : jprb
2161 !
2162 IMPLICIT NONE
2163 !
2164 !* 0.1 declarations of arguments
2165 !
2166 REAL, DIMENSION(:), INTENT(IN) :: PSNOWRHO ! snow density (kg m-3)
2167 REAL, DIMENSION(:), INTENT(IN) :: PSNOWDZ ! layer thickness (m)
2168 REAL, DIMENSION(:), INTENT(IN) :: PZENITH ! zenith angle (rad)
2169 REAL, DIMENSION(:), INTENT(IN) :: PPERMSNOWFRAC ! permanent snow fraction (-)
2170 REAL, DIMENSION(:,:), INTENT(IN) :: PSPECTRALALBEDO ! spectral albedo (-)
2171 REAL, DIMENSION(:), INTENT(IN) :: PDSGRAIN ! Snow optical grain diameter (m)
2172 !
2173 REAL, DIMENSION(SIZE(PSNOWRHO)) :: PCOEF ! -
2174 !
2175 !* 0.2 declarations of local variables
2176 !
2177 REAL, DIMENSION(SIZE(PSNOWRHO)) :: ZWORK, ZPROJLAT, &
2178  ZBETA1, ZBETA2, ZBETA3, &
2179  ZOPTICALPATH1, ZOPTICALPATH2, &
2180  ZOPTICALPATH3
2181 !
2182 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2183 !
2184 !-------------------------------------------------------------------------------
2185 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LRADABS_1D',0,zhook_handle)
2186 !
2187 ! Coefficient for taking into account the increase of path length of rays
2188 ! in snow due to zenithal angle
2189 !
2190 zprojlat(:) = (1.0-ppermsnowfrac(:))+ppermsnowfrac(:)/ &
2191  max(xmincoszen,cos(pzenith(:)))
2192 !
2193 ! Extinction coefficient:
2194 !
2195 zwork(:) = sqrt(pdsgrain(:))
2196 zbeta1(:) = max(xvbeta1*psnowrho(:)/zwork(:),xvbeta2)
2197 zbeta2(:) = max(xvbeta3*psnowrho(:)/zwork(:),xvbeta4)
2198 zbeta3(:) = xvbeta5
2199 !
2200 zopticalpath1(:) = zbeta1(:)*psnowdz(:)
2201 zopticalpath2(:) = zbeta2(:)*psnowdz(:)
2202 zopticalpath3(:) = xundef
2203 !
2204 WHERE(pspectralalbedo(:,3)==xundef)
2205  pcoef(:) = xsw_wght_vis*(1.0-pspectralalbedo(:,1))*exp(-zopticalpath1(:)*zprojlat(:)) &
2206  + xsw_wght_nir*(1.0-pspectralalbedo(:,2))*exp(-zopticalpath2(:)*zprojlat(:))
2207 ELSEWHERE
2208  zopticalpath3(:) = zbeta3(:)*psnowdz(:)
2209  pcoef(:) = xvspec1*(1.0-pspectralalbedo(:,1))*exp(-zopticalpath1(:)*zprojlat(:)) &
2210  + xvspec2*(1.0-pspectralalbedo(:,2))*exp(-zopticalpath2(:)*zprojlat(:)) &
2211  + xvspec3*(1.0-pspectralalbedo(:,3))*exp(-zopticalpath3(:)*zprojlat(:))
2212 END WHERE
2213 !
2214 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LRADABS_1D',1,zhook_handle)
2215 !-------------------------------------------------------------------------------
2216 !
2217 END FUNCTION snow3lradabs_1d
2218 !####################################################################
2219 !####################################################################
2220 !####################################################################
2221 FUNCTION snow3lradabs_2d(PSNOWRHO,PSNOWDZ,PSPECTRALALBEDO,PZENITH,PPERMSNOWFRAC,PDSGRAIN) RESULT(PCOEF)
2223 !! PURPOSE
2224 !! -------
2225 ! Calculate the transmission of shortwave radiation within the snowpack
2226 ! (with depth)
2227 ! A. Boone 02/2011
2228 ! A. Boone 11/2014 Updated to use spectral dependence
2229 ! NOTE, assumes 3 spectral bands
2230 !
2231 USE modd_surf_par, ONLY : xundef
2233 USE modd_snow_par, ONLY : xvspec1,xvspec2,xvspec3,xvbeta1,xvbeta2, &
2234  xvbeta4,xvbeta3,xvbeta5, xmincoszen
2235 !
2236 USE yomhook ,ONLY : lhook, dr_hook
2237 USE parkind1 ,ONLY : jprb
2238 !
2239 IMPLICIT NONE
2240 !
2241 !* 0.1 declarations of arguments
2242 !
2243 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWRHO ! snow density (kg m-3)
2244 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWDZ ! layer thickness (m)
2245 REAL, DIMENSION(:,:), INTENT(IN) :: PZENITH ! zenith angle (rad)
2246 REAL, DIMENSION(:,:), INTENT(IN) :: PPERMSNOWFRAC ! permanent snow fraction (-)
2247 REAL, DIMENSION(:,:,:), INTENT(IN) :: PSPECTRALALBEDO ! spectral albedo (-)
2248 REAL, DIMENSION(:,:), INTENT(IN) :: PDSGRAIN ! Snow optical grain diameter (m)
2249 !
2250 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: PCOEF ! -
2251 !
2252 !* 0.2 declarations of local variables
2253 !
2254 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZWORK, ZPROJLAT, &
2255  ZBETA1, ZBETA2, ZBETA3, &
2256  ZOPTICALPATH1, ZOPTICALPATH2, &
2257  ZOPTICALPATH3
2258 !
2259 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2260 !
2261 !-------------------------------------------------------------------------------
2262 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LRADABS_2D',0,zhook_handle)
2263 !
2264 ! Coefficient for taking into account the increase of path length of rays
2265 ! in snow due to zenithal angle
2266 !
2267 zprojlat(:,:) = (1.0-ppermsnowfrac(:,:))+ppermsnowfrac(:,:)/ &
2268  max(xmincoszen,cos(pzenith(:,:)))
2269 !
2270 ! Extinction coefficient:
2271 !
2272 zwork(:,:) = sqrt(pdsgrain(:,:))
2273 zbeta1(:,:) = max(xvbeta1*psnowrho(:,:)/zwork(:,:),xvbeta2)
2274 zbeta2(:,:) = max(xvbeta3*psnowrho(:,:)/zwork(:,:),xvbeta4)
2275 zbeta3(:,:) = xvbeta5
2276 !
2277 zopticalpath1(:,:) = zbeta1(:,:)*psnowdz(:,:)
2278 zopticalpath2(:,:) = zbeta2(:,:)*psnowdz(:,:)
2279 zopticalpath3(:,:) = xundef
2280 !
2281 WHERE(pspectralalbedo(:,:,3)==xundef)
2282  pcoef(:,:) = xsw_wght_vis*(1.0-pspectralalbedo(:,:,1))*exp(-zopticalpath1(:,:)*zprojlat(:,:)) &
2283  + xsw_wght_nir*(1.0-pspectralalbedo(:,:,2))*exp(-zopticalpath2(:,:)*zprojlat(:,:))
2284 ELSEWHERE
2285  zopticalpath3(:,:) = zbeta3(:,:)*psnowdz(:,:)
2286  pcoef(:,:) = xvspec1*(1.0-pspectralalbedo(:,:,1))*exp(-zopticalpath1(:,:)*zprojlat(:,:)) &
2287  + xvspec2*(1.0-pspectralalbedo(:,:,2))*exp(-zopticalpath2(:,:)*zprojlat(:,:)) &
2288  + xvspec3*(1.0-pspectralalbedo(:,:,3))*exp(-zopticalpath3(:,:)*zprojlat(:,:))
2289 END WHERE
2290 !
2291 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LRADABS_2D',1,zhook_handle)
2292 !-------------------------------------------------------------------------------
2293 !
2294 END FUNCTION snow3lradabs_2d
2295 !####################################################################
2296 !####################################################################
2297 !####################################################################
2298 FUNCTION snow3lradabs_sfc(PSNOWRHO,PSNOWDZ,PSPECTRALALBEDO,PZENITH,PPERMSNOWFRAC,PDSGRAIN) RESULT(PCOEF)
2300 !! PURPOSE
2301 !! -------
2302 ! Calculate the transmission of shortwave radiation within the snowpack
2303 ! (with depth) for 3 spectral bands
2304 ! A. Boone 02/2011
2305 ! A. Boone 11/2014 Updated to use spectral dependence
2306 ! NOTE, assumes 3 spectral bands
2307 ! A. Boone 06/2017 ONLY considers albedo of uppermost layer
2308 !
2309 USE modd_surf_par, ONLY : xundef
2310 USE modd_snow_par, ONLY : xvspec1,xvspec2,xvspec3,xvbeta1,xvbeta2, &
2311  xvbeta4,xvbeta3,xvbeta5, xmincoszen
2313 !
2314 USE yomhook ,ONLY : lhook, dr_hook
2315 USE parkind1 ,ONLY : jprb
2316 !
2317 IMPLICIT NONE
2318 !
2319 !* 0.1 declarations of arguments
2320 !
2321 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWRHO ! snow density (kg m-3)
2322 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWDZ ! layer thickness (m)
2323 REAL, DIMENSION(:), INTENT(IN) :: PZENITH ! zenith angle (rad)
2324 REAL, DIMENSION(:), INTENT(IN) :: PPERMSNOWFRAC ! permanent snow fraction (-)
2325 REAL, DIMENSION(:,:), INTENT(IN) :: PSPECTRALALBEDO ! spectral albedo (-)
2326 REAL, DIMENSION(:,:), INTENT(IN) :: PDSGRAIN ! Snow optical grain diameter (m)
2327 !
2328 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: PCOEF ! -
2329 !
2330 !* 0.2 declarations of local variables
2331 !
2332 INTEGER :: JJ, JI, INLVLS, INI
2333 REAL, DIMENSION(SIZE(PSNOWRHO,1)) :: ZPROJLAT, ZOPTICALPATH1, &
2334  ZOPTICALPATH2, ZOPTICALPATH3
2335 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZWORK, ZBETA1, ZBETA2, ZBETA3
2336 !
2337 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2338 !
2339 !-------------------------------------------------------------------------------
2340 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LRADABS_SFC',0,zhook_handle)
2341 !
2342 ini = SIZE(psnowdz(:,:),1)
2343 inlvls = SIZE(psnowdz(:,:),2)
2344 !
2345 ! Coefficient for taking into account the increase of path length of rays
2346 ! in snow due to zenithal angle
2347 !
2348 zprojlat(:) = (1.0-ppermsnowfrac(:))+ppermsnowfrac(:)/ &
2349  max(xmincoszen,cos(pzenith(:)))
2350 !
2351 ! Extinction coefficient:
2352 !
2353 zwork(:,:) = sqrt(pdsgrain(:,:))
2354 zbeta1(:,:) = max(xvbeta1*psnowrho(:,:)/zwork(:,:),xvbeta2)
2355 zbeta2(:,:) = max(xvbeta3*psnowrho(:,:)/zwork(:,:),xvbeta4)
2356 zbeta3(:,:) = xvbeta5
2357 !
2358 zopticalpath1(:) = 0.0
2359 zopticalpath2(:) = 0.0
2360 zopticalpath3(:) = 0.0
2361 !
2362 DO jj=1,inlvls
2363  DO ji=1,ini
2364  zopticalpath1(ji) = zopticalpath1(ji) + zbeta1(ji,jj)*psnowdz(ji,jj)
2365  zopticalpath2(ji) = zopticalpath2(ji) + zbeta2(ji,jj)*psnowdz(ji,jj)
2366 
2367  IF(pspectralalbedo(ji,3)==xundef)THEN
2368 
2369  pcoef(ji,jj) = xsw_wght_vis*(1.0-pspectralalbedo(ji,1))*exp(-zopticalpath1(ji)*zprojlat(ji)) &
2370  + xsw_wght_nir*(1.0-pspectralalbedo(ji,2))*exp(-zopticalpath2(ji)*zprojlat(ji))
2371  ELSE
2372 
2373  zopticalpath3(ji) = zopticalpath3(ji) + zbeta3(ji,jj)*psnowdz(ji,jj)
2374 
2375  pcoef(ji,jj) = xvspec1*(1.0-pspectralalbedo(ji,1))*exp(-zopticalpath1(ji)*zprojlat(ji)) &
2376  + xvspec2*(1.0-pspectralalbedo(ji,2))*exp(-zopticalpath2(ji)*zprojlat(ji)) &
2377  + xvspec3*(1.0-pspectralalbedo(ji,3))*exp(-zopticalpath3(ji)*zprojlat(ji))
2378 
2379  ENDIF
2380 
2381  ENDDO
2382 ENDDO
2383 !
2384 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LRADABS_SFC',1,zhook_handle)
2385 !-------------------------------------------------------------------------------
2386 !
2387 END FUNCTION snow3lradabs_sfc
2388 !####################################################################
2389 !####################################################################
2390 !####################################################################
2391  SUBROUTINE snow3lthrm(PSNOWRHO,PSCOND,PSNOWTEMP,PPS)
2393 !! PURPOSE
2394 !! -------
2395 ! Calculate snow thermal conductivity from
2396 ! Sun et al. 1999, J. of Geophys. Res., 104, 19587-19579 (vapor)
2397 ! and Yen, 1981, CRREL Rep 81-10 (snow)
2398 ! or Anderson, 1976, NOAA Tech. Rep. NWS 19 (snow).
2399 !
2400 !
2401 USE modd_csts, ONLY : xp00, xcondi, xrholw
2402 !
2403 USE modd_snow_par, ONLY : xvrkz6, xsnowthrmcond1, &
2404  xsnowthrmcond2, &
2405  xsnowthrmcond_avap, &
2406  xsnowthrmcond_bvap, &
2407  xsnowthrmcond_cvap
2408 !
2409 USE yomhook ,ONLY : lhook, dr_hook
2410 USE parkind1 ,ONLY : jprb
2411 !
2412 IMPLICIT NONE
2413 !
2414 !* 0.1 declarations of arguments
2415 !
2416 REAL, DIMENSION(:), INTENT(IN) :: PPS
2417 !
2418 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWTEMP, PSNOWRHO
2419 !
2420 REAL, DIMENSION(:,:), INTENT(OUT) :: PSCOND
2421 !
2422 !
2423 !* 0.2 declarations of local variables
2424 !
2425 INTEGER :: JJ, JI
2426 !
2427 INTEGER :: INI
2428 INTEGER :: INLVLS
2429 !
2430  CHARACTER(LEN=5) :: YSNOWCOND !should be in namelist
2431 !
2432 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2433 !-------------------------------------------------------------------------------
2434 !
2435 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LTHRM',0,zhook_handle)
2436 !
2437 ini = SIZE(psnowrho(:,:),1)
2438 inlvls = SIZE(psnowrho(:,:),2)
2439 !
2440 ! 1. Snow thermal conductivity
2441 ! ----------------------------
2442 !
2443 ysnowcond='YEN81' !should be in namelist
2444 !
2445 IF(ysnowcond=='AND76')THEN
2446 ! Thermal conductivity coefficients from Anderson (1976)
2447  pscond(:,:) = (xsnowthrmcond1 + xsnowthrmcond2*psnowrho(:,:)*psnowrho(:,:))
2448 ELSE
2449 ! Thermal conductivity coefficients from Yen (1981)
2450  pscond(:,:) = xcondi * exp(xvrkz6*log(psnowrho(:,:)/xrholw))
2451 ENDIF
2452 !
2453 ! 2. Implicit vapor diffn effects
2454 ! -------------------------------
2455 !
2456 DO jj=1,inlvls
2457  DO ji=1,ini
2458  pscond(ji,jj) = pscond(ji,jj) + max(0.0,(xsnowthrmcond_avap+(xsnowthrmcond_bvap/(psnowtemp(ji,jj) &
2459  + xsnowthrmcond_cvap)))*(xp00/pps(ji)))
2460  ENDDO
2461 ENDDO
2462 !
2463 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LTHRM',1,zhook_handle)
2464 !
2465 !-------------------------------------------------------------------------------
2466 !
2467 END SUBROUTINE snow3lthrm
2468 !####################################################################
2469 !####################################################################
2470 !####################################################################
2471 FUNCTION snow3ldopt_2d(PSNOWRHO,PSNOWAGE) RESULT(PDOPT)
2473 !! PURPOSE
2474 !! -------
2475 ! Calculate the optical grain diameter.
2476 !
2477 USE modd_snow_par, ONLY : xdsgrain_max,xsnow_agrain, &
2478  xsnow_bgrain,xsnow_cgrain
2479 !
2480 USE yomhook ,ONLY : lhook, dr_hook
2481 USE parkind1 ,ONLY : jprb
2482 !
2483 IMPLICIT NONE
2484 !
2485 !* 0.1 declarations of arguments
2486 !
2487 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWRHO,PSNOWAGE
2488 !
2489 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: PDOPT
2490 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZAGE
2491 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSRHO4
2492 !
2493 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2494 !-------------------------------------------------------------------------------
2495 !
2496 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LDOPT_2D',0,zhook_handle)
2497 !
2498 zage(:,:) = min(15.,psnowage(:,:))
2499 !
2500 zsrho4(:,:) = psnowrho(:,:)*psnowrho(:,:)*psnowrho(:,:)*psnowrho(:,:)
2501 !
2502 pdopt(:,:) = min(xdsgrain_max,xsnow_agrain+xsnow_bgrain*zsrho4(:,:)+xsnow_cgrain*zage(:,:))
2503 !
2504 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LDOPT_2D',1,zhook_handle)
2505 !
2506 END FUNCTION snow3ldopt_2d
2507 !####################################################################
2508 FUNCTION snow3ldopt_1d(PSNOWRHO,PSNOWAGE) RESULT(PDOPT)
2510 !! PURPOSE
2511 !! -------
2512 ! Calculate the optical grain diameter.
2513 !
2514 USE modd_snow_par, ONLY : xdsgrain_max,xsnow_agrain, &
2515  xsnow_bgrain,xsnow_cgrain
2516 !
2517 USE yomhook ,ONLY : lhook, dr_hook
2518 USE parkind1 ,ONLY : jprb
2519 !
2520 IMPLICIT NONE
2521 !
2522 !* 0.1 declarations of arguments
2523 !
2524 REAL, DIMENSION(:), INTENT(IN) :: PSNOWRHO,PSNOWAGE
2525 !
2526 REAL, DIMENSION(SIZE(PSNOWRHO)) :: PDOPT
2527 REAL, DIMENSION(SIZE(PSNOWRHO)) :: ZAGE
2528 REAL, DIMENSION(SIZE(PSNOWRHO)) :: ZSRHO4
2529 !
2530 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2531 !-------------------------------------------------------------------------------
2532 !
2533 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LDOPT_1D',0,zhook_handle)
2534 !
2535 zage(:) = min(15.,psnowage(:))
2536 !
2537 zsrho4(:) = psnowrho(:)*psnowrho(:)*psnowrho(:)*psnowrho(:)
2538 !
2539 pdopt(:) = min(xdsgrain_max,xsnow_agrain+xsnow_bgrain*zsrho4(:)+xsnow_cgrain*zage(:))
2540 !
2541 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LDOPT_1D',1,zhook_handle)
2542 !
2543 END FUNCTION snow3ldopt_1d
2544 !####################################################################
2545 FUNCTION snow3ldopt_0d(PSNOWRHO,PSNOWAGE) RESULT(PDOPT)
2547 !! PURPOSE
2548 !! -------
2549 ! Calculate the optical grain diameter.
2550 !
2551 USE modd_snow_par, ONLY : xdsgrain_max,xsnow_agrain, &
2552  xsnow_bgrain,xsnow_cgrain
2553 !
2554 USE yomhook ,ONLY : lhook, dr_hook
2555 USE parkind1 ,ONLY : jprb
2556 !
2557 IMPLICIT NONE
2558 !
2559 !* 0.1 declarations of arguments
2560 !
2561 REAL, INTENT(IN) :: PSNOWRHO,PSNOWAGE
2562 !
2563 REAL :: PDOPT
2564 REAL :: ZAGE
2565 REAL :: ZSRHO4
2566 !
2567 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2568 !-------------------------------------------------------------------------------
2569 !
2570 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LDOPT_0D',0,zhook_handle)
2571 !
2572 zage = min(15.,psnowage)
2573 !
2574 zsrho4 = psnowrho*psnowrho*psnowrho*psnowrho
2575 !
2576 pdopt = min(xdsgrain_max,xsnow_agrain+xsnow_bgrain*zsrho4+xsnow_cgrain*zage)
2577 !
2578 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LDOPT_0D',1,zhook_handle)
2579 !
2580 END FUNCTION snow3ldopt_0d
2581 !####################################################################
2582 !####################################################################
2583 !####################################################################
2584 SUBROUTINE snow3lalb(PALBEDOSC,PSPECTRALALBEDO,PSNOWRHO,PSNOWAGE, &
2585  PPERMSNOWFRAC,PPS)
2587 !! PURPOSE
2588 !! -------
2589 ! Calculate the snow surface albedo. Use the method of
2590 ! CROCUS with 3 spectral albedo depending on snow density
2591 ! and age
2592 !
2593 !
2594 USE modd_snow_par, ONLY : xvaging_glacier, xvaging_noglacier, &
2595  xvalb2,xvalb3,xvalb4,xvalb5,xvalb6, &
2596  xvalb7,xvalb8,xvalb9,xvalb10,xvalb11, &
2597  xvdiop1,xvrpre1,xvrpre2,xvpres1, &
2598  xvw1,xvw2,xvspec1,xvspec2,xvspec3
2599 !
2600 USE yomhook ,ONLY : lhook, dr_hook
2601 USE parkind1 ,ONLY : jprb
2602 !
2603 IMPLICIT NONE
2604 !
2605 !* 0.1 declarations of arguments
2606 !
2607 REAL, DIMENSION(:), INTENT(IN) :: PSNOWRHO
2608 REAL, DIMENSION(:), INTENT(IN) :: PSNOWAGE
2609 REAL, DIMENSION(:), INTENT(IN) :: PPERMSNOWFRAC
2610 REAL, DIMENSION(:), INTENT(IN) :: PPS
2611 !
2612 REAL, DIMENSION(:), INTENT(INOUT) :: PALBEDOSC
2613 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSPECTRALALBEDO
2614 !
2615 !* 0.2 declarations of local variables
2616 !
2617 REAL, PARAMETER :: ZALBNIR1 = 0.3
2618 REAL, PARAMETER :: ZALBNIR2 = 0.0
2619 !
2620 REAL, DIMENSION(SIZE(PSNOWRHO)) :: ZVAGING, ZDIAM, ZAGE, &
2621  ZWORK, ZPRES_EFFECT
2622 !
2623 REAL, DIMENSION(SIZE(PSNOWRHO)) :: ZALB1, ZALB2, ZALB3
2624 !
2625 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2626 !
2627 !-------------------------------------------------------------------------------
2628 !
2629 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LALB',0,zhook_handle)
2630 !
2631 ! 0. Initialize:
2632 ! ------------------
2633 !
2634 !Snow age effect parameter for Visible (small over glacier)
2635 zvaging(:)=xvaging_glacier*ppermsnowfrac(:) + xvaging_noglacier*(1.0-ppermsnowfrac(:))
2636 !
2637 !Atm pression effect parameter on albedo
2638 zpres_effect(:) = xvalb10*min(max(pps(:)/xvpres1,xvrpre1),xvrpre2)
2639 !
2640 ! 1. Snow optical grain diameter :
2641 ! --------------------------------
2642 !
2643 !Snow optical diameter do not depend on snow age over glacier or polar regions
2644 zage(:) = (1.0-ppermsnowfrac(:))*psnowage(:)
2645 !
2646 zdiam(:) = snow3ldopt(psnowrho(:),zage(:))
2647 !
2648 ! 2. spectral albedo over 3 bands :
2649 ! ---------------------------------
2650 !
2651 !Snow age effect limited to 1 year
2652 zage(:) = min(365.,psnowage(:))
2653 !
2654 zwork(:)=sqrt(zdiam(:))
2655 !
2656 ! Visible
2657 zalb1(:)=min(xvalb4,xvalb2-xvalb3*zwork(:))
2658 zalb1(:)=max(xvalb11,zalb1(:)-zpres_effect(:)*zage(:)/zvaging(:))
2659 !
2660 ! near Infra-red 1
2661 zalb2(:)=xvalb5-xvalb6*zwork(:)
2662 zalb2(:)=max(zalbnir1,zalb2(:))
2663 !
2664 ! near Infra-red 2
2665 zdiam(:)=min(xvdiop1,zdiam(:))
2666 zwork(:)=sqrt(zdiam(:))
2667 zalb3(:)=xvalb7*zdiam(:)-xvalb8*zwork(:)+xvalb9
2668 zalb3(:)=max(zalbnir2,zalb3(:))
2669 !
2670 pspectralalbedo(:,1)=zalb1(:)
2671 pspectralalbedo(:,2)=zalb2(:)
2672 pspectralalbedo(:,3)=zalb3(:)
2673 !
2674 ! 3. total albedo :
2675 ! -----------------
2676 !
2677 palbedosc(:)=xvspec1*zalb1(:)+xvspec2*zalb2(:)+xvspec3*zalb3(:)
2678 !
2679 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LALB',1,zhook_handle)
2680 !
2681 !-------------------------------------------------------------------------------
2682 !
2683 END SUBROUTINE snow3lalb
2684 !####################################################################
2685 !####################################################################
2686 !####################################################################
2687 SUBROUTINE snow3lfall(PTSTEP,PSR,PTA,PVMOD,PSNOW,PSNOWRHO,PSNOWDZ, &
2688  PSNOWHEAT,PSNOWHMASS,PSNOWAGE,PPERMSNOWFRAC)
2689 !
2690 !! PURPOSE
2691 !! -------
2692 ! Calculate changes to snowpack resulting from snowfall.
2693 ! Update mass and heat content of uppermost layer.
2694 !
2695 !
2696 USE modd_csts, ONLY : xlmtt, xtt, xci
2697 USE modd_snow_par, ONLY : xrhosmin_es, xsnowdmin, &
2698  xsnowfall_a_sn, &
2699  xsnowfall_b_sn, &
2700  xsnowfall_c_sn
2701 !
2702 USE yomhook , ONLY : lhook, dr_hook
2703 USE parkind1 , ONLY : jprb
2704 !
2705 IMPLICIT NONE
2706 !
2707 !* 0.1 declarations of arguments
2708 !
2709 REAL, INTENT(IN) :: PTSTEP
2710 !
2711 REAL, DIMENSION(:), INTENT(IN) :: PSR, PTA, PVMOD, PPERMSNOWFRAC
2712 !
2713 REAL, DIMENSION(:), INTENT(INOUT) :: PSNOW
2714 !
2715 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWRHO, PSNOWDZ, PSNOWHEAT, PSNOWAGE
2716 !
2717 REAL, DIMENSION(:), INTENT(OUT) :: PSNOWHMASS
2718 !
2719 !
2720 !* 0.2 declarations of local variables
2721 !
2722 INTEGER :: JJ, JI
2723 !
2724 INTEGER :: INI
2725 INTEGER :: INLVLS
2726 !
2727 REAL, DIMENSION(SIZE(PTA)) :: ZSNOWFALL, ZRHOSNEW, &
2728  ZSNOW, ZSNOWTEMP, &
2729  ZSNOWFALL_DELTA, ZSCAP, &
2730  ZAGENEW
2731 !
2732 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2733 !
2734 !-------------------------------------------------------------------------------
2735 !
2736 ! 0. Initialize:
2737 ! ------------------
2738 !
2739 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LFALL',0,zhook_handle)
2740 !
2741 ini = SIZE(psnowdz(:,:),1)
2742 inlvls = SIZE(psnowdz(:,:),2)
2743 !
2744 zrhosnew(:) = xrhosmin_es
2745 zagenew(:) = 0.0
2746 zsnowfall(:) = 0.0
2747 zscap(:) = 0.0
2748 zsnow(:) = psnow(:)
2749 !
2750 psnowhmass(:) = 0.0
2751 !
2752 ! 1. Incorporate snowfall into snowpack:
2753 ! --------------------------------------
2754 !
2755 !
2756 ! Heat content of newly fallen snow (J/m2):
2757 ! NOTE for now we assume the snowfall has
2758 ! the temperature of the snow surface upon reaching the snow.
2759 ! This is done as opposed to using the air temperature since
2760 ! this flux is quite small and has little to no impact
2761 ! on the time scales of interest. If we use the above assumption
2762 ! then, then the snowfall advective heat flux is zero.
2763 !
2764 zsnowtemp(:) = xtt
2765 zscap(:) = snow3lscap(psnowrho(:,1))
2766 !
2767 WHERE (psr(:) > 0.0 .AND. psnowdz(:,1)>0.)
2768  zsnowtemp(:) = xtt + (psnowheat(:,1) + &
2769  xlmtt*psnowrho(:,1)*psnowdz(:,1))/ &
2770  (zscap(:)*max(xsnowdmin/inlvls,psnowdz(:,1)))
2771  zsnowtemp(:) = min(xtt, zsnowtemp(:))
2772 END WHERE
2773 !
2774 WHERE (psr(:) > 0.0)
2775 !
2776  psnowhmass(:) = psr(:)*(xci*(zsnowtemp(:)-xtt)-xlmtt)*ptstep
2777 !
2778 ! Snowfall density: Following CROCUS (Pahaut 1976)
2779 !
2780  zrhosnew(:) = max(xrhosmin_es, xsnowfall_a_sn + xsnowfall_b_sn*(pta(:)-xtt)+ &
2781  xsnowfall_c_sn*sqrt(pvmod(:)))
2782 !
2783 !
2784 ! Fresh snowfall changes the snowpack age,
2785 ! decreasing in uppermost snow layer (mass weighted average):
2786 !
2787  psnowage(:,1) = (psnowage(:,1)*psnowdz(:,1)*psnowrho(:,1)+zagenew(:)*psr(:)*ptstep) / &
2788  (psnowdz(:,1)*psnowrho(:,1)+psr(:)*ptstep)
2789 !
2790 ! Augment total pack depth:
2791 !
2792  zsnowfall(:) = psr(:)*ptstep/zrhosnew(:) ! snowfall thickness (m)
2793 !
2794  psnow(:) = psnow(:) + zsnowfall(:)
2795 !
2796 ! Fresh snowfall changes the snowpack
2797 ! density, increases the total liquid water
2798 ! equivalent: in uppermost snow layer:
2799 !
2800  psnowrho(:,1) = (psnowdz(:,1)*psnowrho(:,1) + zsnowfall(:)*zrhosnew(:))/ &
2801  (psnowdz(:,1)+zsnowfall(:))
2802 !
2803  psnowdz(:,1) = psnowdz(:,1) + zsnowfall(:)
2804 !
2805 ! Add energy of snowfall to snowpack:
2806 ! Update heat content (J/m2) (therefore the snow temperature
2807 ! and liquid content):
2808 !
2809  psnowheat(:,1) = psnowheat(:,1) + psnowhmass(:)
2810 !
2811 END WHERE
2812 !
2813 !
2814 ! 2. Case of new snowfall on a previously snow-free surface:
2815 ! ----------------------------------------------------------
2816 !
2817 ! When snow first falls on a surface devoid of snow,
2818 ! redistribute the snow mass throughout the 3 layers:
2819 ! (temperature already set in the calling routine
2820 ! for this case)
2821 !
2822 zsnowfall_delta(:) = 0.0
2823 WHERE(zsnow(:) == 0.0 .AND. psr(:) > 0.0)
2824  zsnowfall_delta(:) = 1.0
2825 END WHERE
2826 !
2827 DO jj=1,inlvls
2828  DO ji=1,ini
2829 !
2830  psnowdz(ji,jj) = zsnowfall_delta(ji)*(zsnowfall(ji) /inlvls) + &
2831  (1.0-zsnowfall_delta(ji))*psnowdz(ji,jj)
2832 !
2833  psnowheat(ji,jj) = zsnowfall_delta(ji)*(psnowhmass(ji)/inlvls) + &
2834  (1.0-zsnowfall_delta(ji))*psnowheat(ji,jj)
2835 !
2836  psnowrho(ji,jj) = zsnowfall_delta(ji)*zrhosnew(ji) + &
2837  (1.0-zsnowfall_delta(ji))*psnowrho(ji,jj)
2838 !
2839  psnowage(ji,jj) = zsnowfall_delta(ji)*(zagenew(ji)/inlvls) + &
2840  (1.0-zsnowfall_delta(ji))*psnowage(ji,jj)
2841 !
2842  ENDDO
2843 ENDDO
2844 !
2845 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LFALL',1,zhook_handle)
2846 !
2847 !
2848 END SUBROUTINE snow3lfall
2849 !####################################################################
2850 !####################################################################
2851 !####################################################################
2852 SUBROUTINE snow3lcompactn(PTSTEP,PSNOWDZMIN,PSNOWRHO,PSNOWDZ,PSNOWTEMP,PSNOW,PSNOWLIQ)
2854 !! PURPOSE
2855 !! -------
2856 ! Snow compaction due to overburden and settling.
2857 ! Mass is unchanged: layer thickness is reduced
2858 ! in proportion to density increases. Method
2859 ! of Brun et al (1989) and Vionnet et al. (2012)
2860 !
2861 !
2862 USE modd_surf_par, ONLY : xundef
2863 !
2864 USE modd_csts, ONLY : xtt, xg
2865 USE modd_snow_par, ONLY : xrhosmax_es
2866 !
2867 USE modd_snow_metamo, ONLY : xvvisc1,xvvisc3,xvvisc4, &
2869 !
2870 USE yomhook , ONLY : lhook, dr_hook
2871 USE parkind1 , ONLY : jprb
2872 !
2873 IMPLICIT NONE
2874 !
2875 !* 0.1 declarations of arguments
2876 !
2877 REAL, INTENT(IN) :: PTSTEP
2878 REAL, INTENT(IN) :: PSNOWDZMIN
2879 !
2880 REAL, DIMENSION(:,:), INTENT(IN) :: PSNOWTEMP, PSNOWLIQ
2881 !
2882 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWRHO, PSNOWDZ
2883 !
2884 REAL, DIMENSION(:), INTENT(OUT) :: PSNOW
2885 !
2886 !
2887 !* 0.2 declarations of local variables
2888 !
2889 INTEGER :: JJ, JI
2890 !
2891 INTEGER :: INI
2892 INTEGER :: INLVLS
2893 !
2894 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWRHO2, ZVISCOCITY, ZF1, &
2895  ZTEMP, ZSMASS, ZSNOWDZ, &
2896  ZWSNOWDZ, ZWHOLDMAX
2897 !
2898 !
2899 REAL(KIND=JPRB) :: ZHOOK_HANDLE
2900 !
2901 !-------------------------------------------------------------------------------
2902 !
2903 ! 0. Initialization:
2904 ! ------------------
2905 !
2906 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LCOMPACTN',0,zhook_handle)
2907 !
2908 ini = SIZE(psnowdz(:,:),1)
2909 inlvls = SIZE(psnowdz(:,:),2)
2910 !
2911 zsnowrho2(:,:) = psnowrho(:,:)
2912 zsnowdz(:,:) = max(psnowdzmin,psnowdz(:,:))
2913 zviscocity(:,:) = 0.0
2914 ztemp(:,:) = 0.0
2915 !
2916 ! 1. Cumulative snow mass (kg/m2):
2917 ! --------------------------------
2918 !
2919 zsmass(:,:) = 0.0
2920 DO jj=2,inlvls
2921  DO ji=1,ini
2922  zsmass(ji,jj) = zsmass(ji,jj-1) + psnowdz(ji,jj-1)*psnowrho(ji,jj-1)
2923  ENDDO
2924 ENDDO
2925 ! overburden of half the mass of the uppermost layer applied to itself
2926 zsmass(:,1) = 0.5 * psnowdz(:,1) * psnowrho(:,1)
2927 !
2928 ! 2. Compaction
2929 ! -------------
2930 !
2931 !Liquid water effect
2932 !
2933 zwholdmax(:,:) = snow3lhold(psnowrho,psnowdz)
2934 zwholdmax(:,:) = max(1.e-10, zwholdmax(:,:))
2935 zf1(:,:) = 1.0/(xvvisc5+10.*min(1.0,psnowliq(:,:)/zwholdmax(:,:)))
2936 !
2937 !Snow viscocity, density and grid thicknesses
2938 !
2939 DO jj=1,inlvls
2940  DO ji=1,ini
2941 !
2942  IF(psnowrho(ji,jj) < xrhosmax_es)THEN
2943 !
2944 ! temperature dependence limited to 5K: Schleef et al. (2014)
2945  ztemp(ji,jj) = xvvisc4*min(5.0,abs(xtt-psnowtemp(ji,jj)))
2946 !
2947 ! Calculate snow viscocity: Brun et al. (1989), Vionnet et al. (2012)
2948  zviscocity(ji,jj) = xvvisc1*zf1(ji,jj)*exp(xvvisc3*psnowrho(ji,jj)+ztemp(ji,jj))*psnowrho(ji,jj)/xvro11
2949 !
2950 ! Calculate snow density:
2951  zsnowrho2(ji,jj) = psnowrho(ji,jj) + psnowrho(ji,jj)*ptstep &
2952  * ( (xg*zsmass(ji,jj)/zviscocity(ji,jj)) )
2953 !
2954 ! Conserve mass by decreasing grid thicknesses in response to density increases
2955  psnowdz(ji,jj) = psnowdz(ji,jj)*(psnowrho(ji,jj)/zsnowrho2(ji,jj))
2956 !
2957  ENDIF
2958 !
2959  ENDDO
2960 ENDDO
2961 !
2962 ! 3. Update total snow depth and density profile:
2963 ! -----------------------------------------------
2964 !
2965 ! Compaction/augmentation of total snowpack depth
2966 !
2967 psnow(:) = 0.
2968 DO jj=1,inlvls
2969  DO ji=1,ini
2970  psnow(ji) = psnow(ji) + psnowdz(ji,jj)
2971  ENDDO
2972 ENDDO
2973 !
2974 ! Update density (kg m-3):
2975 !
2976 psnowrho(:,:) = zsnowrho2(:,:)
2977 !
2978 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LCOMPACTN',1,zhook_handle)
2979 !
2980 !-------------------------------------------------------------------------------
2981 !
2982 END SUBROUTINE snow3lcompactn
2983 !####################################################################
2984 !####################################################################
2985 !####################################################################
2986  SUBROUTINE snow3ltransf(PSNOW,PSNOWDZ,PSNOWDZN, &
2987  PSNOWRHO,PSNOWHEAT,PSNOWAGE)
2989 !! PURPOSE
2990 !! -------
2991 ! Snow mass,heat and characteristics redistibution in case of
2992 ! grid resizing. Total mass and heat content of the overall snowpack
2993 ! unchanged/conserved within this routine.
2994 ! Same method as in Crocus
2995 !
2996 USE modd_surf_par, ONLY : xundef
2997 USE modd_snow_par, ONLY : xsnowcritd
2998 !
2999 USE yomhook , ONLY : lhook, dr_hook
3000 USE parkind1 , ONLY : jprb
3001 !
3002 IMPLICIT NONE
3003 !
3004 !
3005 !* 0.1 declarations of arguments
3006 !
3007 REAL, DIMENSION(: ), INTENT(IN) :: PSNOW
3008 !
3009 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWDZN
3010 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWHEAT
3011 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWRHO
3012 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWDZ
3013 REAL, DIMENSION(:,:), INTENT(INOUT) :: PSNOWAGE
3014 !
3015 !* 0.2 declarations of local variables
3016 !
3017 INTEGER :: JI, JL, JLO
3018 !
3019 INTEGER :: INI
3020 INTEGER :: INLVLS
3021 !
3022 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWRHON
3023 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWHEATN
3024 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWAGEN
3025 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWZTOP_NEW
3026 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWZBOT_NEW
3027 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWRHOO
3028 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWHEATO
3029 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWAGEO
3030 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWDZO
3031 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWZTOP_OLD
3032 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWZBOT_OLD
3033 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWHEAN
3034 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZSNOWAGN
3035 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZMASTOTN
3036 REAL, DIMENSION(SIZE(PSNOWRHO,1),SIZE(PSNOWRHO,2)) :: ZMASSDZO
3037 !
3038 REAL, DIMENSION(SIZE(PSNOW)) :: ZPSNOW_OLD, ZPSNOW_NEW
3039 REAL, DIMENSION(SIZE(PSNOW)) :: ZSUMHEAT, ZSUMSWE, ZSUMAGE, ZSNOWMIX_DELTA
3040 !
3041 REAL :: ZPROPOR
3042 !
3043 REAL(KIND=JPRB) :: ZHOOK_HANDLE
3044 !
3045 !-------------------------------------------------------------------------------
3046 !
3047 ! 0. Initialization:
3048 ! ------------------
3049 !
3050 !
3051 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LTRANSF',0,zhook_handle)
3052 !
3053 ini = SIZE(psnowrho,1)
3054 inlvls = SIZE(psnowrho,2)
3055 !
3056 zpsnow_new(:) = 0.0
3057 zpsnow_old(:) = psnow(:)
3058 !
3059 DO jl=1,inlvls
3060  DO ji=1,ini
3061  zpsnow_new(ji)=zpsnow_new(ji)+psnowdzn(ji,jl)
3062  ENDDO
3063 ENDDO
3064 !
3065 ! initialization of variables describing the initial snowpack
3066 !
3067 zsnowdzo(:,:) = psnowdz(:,:)
3068 zsnowrhoo(:,:) = psnowrho(:,:)
3069 zsnowheato(:,:) = psnowheat(:,:)
3070 zsnowageo(:,:) = psnowage(:,:)
3071 zmassdzo(:,:) = xundef
3072 !
3073 ! 1. Calculate vertical grid limits (m):
3074 ! --------------------------------------
3075 !
3076 zsnowztop_old(:,1) = zpsnow_old(:)
3077 zsnowztop_new(:,1) = zpsnow_new(:)
3078 zsnowzbot_old(:,1) = zsnowztop_old(:,1)-zsnowdzo(:,1)
3079 zsnowzbot_new(:,1) = zsnowztop_new(:,1)-psnowdzn(:,1)
3080 !
3081 DO jl=2,inlvls
3082  DO ji=1,ini
3083  zsnowztop_old(ji,jl) = zsnowzbot_old(ji,jl-1)
3084  zsnowztop_new(ji,jl) = zsnowzbot_new(ji,jl-1)
3085  zsnowzbot_old(ji,jl) = zsnowztop_old(ji,jl )-zsnowdzo(ji,jl)
3086  zsnowzbot_new(ji,jl) = zsnowztop_new(ji,jl )-psnowdzn(ji,jl)
3087  ENDDO
3088 ENDDO
3089 zsnowzbot_old(:,inlvls)=0.0
3090 zsnowzbot_new(:,inlvls)=0.0
3091 !
3092 ! 3. Calculate mass, heat, charcateristics mixing due to vertical grid resizing:
3093 ! --------------------------------------------------------------------
3094 !
3095 ! loop over the new snow layers
3096 ! Summ or avergage of the constituting quantities of the old snow layers
3097 ! which are totally or partially inserted in the new snow layer
3098 ! For snow age, mass weighted average is used.
3099 !
3100 zsnowhean(:,:)=0.0
3101 zmastotn(:,:)=0.0
3102 zsnowagn(:,:)=0.0
3103 !
3104 DO jl=1,inlvls
3105  DO jlo=1, inlvls
3106  DO ji=1,ini
3107  IF((zsnowztop_old(ji,jlo)>zsnowzbot_new(ji,jl)).AND.(zsnowzbot_old(ji,jlo)<zsnowztop_new(ji,jl)))THEN
3108 !
3109  zpropor = (min(zsnowztop_old(ji,jlo), zsnowztop_new(ji,jl)) &
3110  - max(zsnowzbot_old(ji,jlo), zsnowzbot_new(ji,jl)))&
3111  / zsnowdzo(ji,jlo)
3112 !
3113  zmassdzo(ji,jlo)=zsnowrhoo(ji,jlo)*zsnowdzo(ji,jlo)*zpropor
3114 !
3115  zmastotn(ji,jl)=zmastotn(ji,jl)+zmassdzo(ji,jlo)
3116  zsnowagn(ji,jl)=zsnowagn(ji,jl)+zsnowageo(ji,jlo)*zmassdzo(ji,jlo)
3117 !
3118  zsnowhean(ji,jl)=zsnowhean(ji,jl)+zsnowheato(ji,jlo)*zpropor
3119 !
3120  ENDIF
3121  ENDDO
3122  ENDDO
3123 ENDDO
3124 !
3125 ! the new layer inherits from the weighted average properties of the old ones
3126 ! heat and mass
3127 !
3128 zsnowheatn(:,:)= zsnowhean(:,:)
3129 zsnowagen(:,:)= zsnowagn(:,:)/zmastotn(:,:)
3130 zsnowrhon(:,:)= zmastotn(:,:)/psnowdzn(:,:)
3131 !
3132 !
3133 ! 4. Vanishing or very thin snowpack check:
3134 ! -----------------------------------------
3135 !
3136 ! NOTE: ONLY for very shallow snowpacks, mix properties (homogeneous):
3137 ! this avoids problems related to heat and mass exchange for
3138 ! thin layers during heavy snowfall or signifigant melt: one
3139 ! new/old layer can exceed the thickness of several old/new layers.
3140 ! Therefore, mix (conservative):
3141 !
3142 zsumheat(:) = 0.0
3143 zsumswe(:) = 0.0
3144 zsumage(:) = 0.0
3145 zsnowmix_delta(:) = 0.0
3146 !
3147 DO jl=1,inlvls
3148  DO ji=1,ini
3149  IF(psnow(ji) < xsnowcritd)THEN
3150  zsumheat(ji) = zsumheat(ji) + psnowheat(ji,jl)
3151  zsumswe(ji) = zsumswe(ji) + psnowrho(ji,jl)*psnowdz(ji,jl)
3152  zsumage(ji) = zsumage(ji) + psnowage(ji,jl)
3153  zsnowmix_delta(ji) = 1.0
3154  ENDIF
3155  ENDDO
3156 ENDDO
3157 !
3158 ! Heat and mass are evenly distributed vertically:
3159 ! heat and mass (density and thickness) are constant
3160 ! in profile:
3161 !
3162 DO jl=1,inlvls
3163  DO ji=1,ini
3164 !
3165  zsnowheatn(ji,jl) = zsnowmix_delta(ji)*(zsumheat(ji)/inlvls) + &
3166  (1.0-zsnowmix_delta(ji))*zsnowheatn(ji,jl)
3167 !
3168  psnowdzn(ji,jl) = zsnowmix_delta(ji)*(psnow(ji)/inlvls) + &
3169  (1.0-zsnowmix_delta(ji))*psnowdzn(ji,jl)
3170 !
3171  zsnowrhon(ji,jl) = zsnowmix_delta(ji)*(zsumswe(ji)/psnow(ji)) + &
3172  (1.0-zsnowmix_delta(ji))*zsnowrhon(ji,jl)
3173 !
3174  zsnowagen(ji,jl) = zsnowmix_delta(ji)*(zsumage(ji)/inlvls) + &
3175  (1.0-zsnowmix_delta(ji))*zsnowagen(ji,jl)
3176 !
3177  ENDDO
3178 ENDDO
3179 !
3180 ! 5. Update mass (density and thickness) and heat:
3181 ! ------------------------------------------------
3182 !
3183 psnowdz(:,:) = psnowdzn(:,:)
3184 psnowrho(:,:) = zsnowrhon(:,:)
3185 psnowheat(:,:) = zsnowheatn(:,:)
3186 psnowage(:,:) = zsnowagen(:,:)
3187 !
3188 IF (lhook) CALL dr_hook('MODE_SNOW3L:SNOW3LTRANSF',1,zhook_handle)
3189 !
3190 !
3191 !-------------------------------------------------------------------------------
3192 !
3193 END SUBROUTINE snow3ltransf
3194 !####################################################################
3195 !####################################################################
3196 !####################################################################
3197 
3198 
3199 END MODULE mode_snow3l
3200 
real, parameter xvtang7
real, parameter xvtangc
real, parameter xdiagf
real, parameter xdiaet
real, parameter xvgang4
real, parameter xsw_wght_vis
real function, dimension(size(psnowrho, 1), size(psnowrho, 2)) snow3lhold_2d(PSNOWRHO, PSNOWDZ)
real, parameter xvtang2
real, parameter xuepsi
real, parameter xvvisc5
real function snow3lhold_0d(PSNOWRHO, PSNOWDZ)
function snowcrohold_3d(PSNOWRHO, PSNOWLIQ, PSNOWDZ)
function snowcrohold_1d(PSNOWRHO, PSNOWLIQ, PSNOWDZ)
real, parameter xvgang9
real function snow3lscap_0d(PSNOWRHO)
function snowcrohold_2d(PSNOWRHO, PSNOWLIQ, PSNOWDZ)
real, parameter xvgang6
subroutine get_agreg(KID1, KID2, PFIELD1, PFIELD2, PFIELD)
real, parameter xvganga
function snow3lradabs_2d(PSNOWRHO, PSNOWDZ, PSPECTRALALBEDO, PZENITH, PPERMS
real function, dimension(size(psnowrho)) snow3ldopt_1d(PSNOWRHO, PSNOWAGE)
real, parameter xvvisc4
real function, dimension(size(psnowrho, 1), size(psnowrho, 2)) snow3lscap_2d(PSNOWRHO)
function snow3lwliqmax_3d(PSNOWRHO)
real, parameter xundef
real, save xcondi
Definition: modd_csts.F90:82
real, parameter xvtang8
real, parameter xvtang3
function snow3lhold_3d(PSNOWRHO, PSNOWDZ)
real, parameter xvgang2
real, save xg
Definition: modd_csts.F90:55
function snow3lradabs_1d(PSNOWRHO, PSNOWDZ, PSPECTRALALBEDO, PZENITH, PPERMS
integer, parameter jprb
Definition: parkind1.F90:32
real, parameter xdiafp
function snow3lscap_3d(PSNOWRHO)
real, parameter xvgang3
real function, dimension(size(psnowrho, 1), size(psnowrho, 2)) snow3lwliqmax_2d(PSNOWRHO)
real, parameter xvtanga
real, parameter xgran
real, save xci
Definition: modd_csts.F90:65
real, parameter xvtangb
real function, dimension(size(psnowrho)) snow3lhold_1d(PSNOWRHO, PSNOWDZ)
real, parameter xvrang2
real function, dimension(size(psnowrho)) snow3lscap_1d(PSNOWRHO)
intent(out) overrides sub arrays one Sort by the least significant key first sum(iindex(1:n))
real, parameter xvdiam6
real, parameter xvrang1
subroutine snow3lgrid_2d(PSNOWDZ, PSNOW, PSNOWDZ_OLD)
logical lhook
Definition: yomhook.F90:15
real, save xrholi
Definition: modd_csts.F90:81
real, parameter xvvisc3
real, parameter xvgang7
real function, dimension(size(psnowrho, 1), size(psnowrho, 2)) snow3ldopt_2d(PSNOWRHO, PSNOWAGE)
real function snow3ldopt_0d(PSNOWRHO, PSNOWAGE)
real, parameter xvtang5
real, parameter xvtang9
real, parameter xvgang8
real, parameter xvgang1
real, parameter xvvisc6
real, parameter xvvisc1
real, save xrholw
Definition: modd_csts.F90:64
function snowcrohold_0d(PSNOWRHO, PSNOWLIQ, PSNOWDZ)
real, save xtt
Definition: modd_csts.F90:66
real, parameter xvro11
real, parameter xvgangc
function snow3lradabs_0d(PSNOWRHO, PSNOWDZ, PSPECTRALALBEDO, PZENITH, PPERMS
real function, dimension(size(psnowrho)) snow3lwliqmax_1d(PSNOWRHO)
real, parameter xvtang6
real, save xlmtt
Definition: modd_csts.F90:72
real, save xp00
Definition: modd_csts.F90:57
real, parameter xvtang4
subroutine snow3lgrid_1d(PSNOWDZ, PSNOW, PSNOWDZ_OLD)
real, parameter xvtang1
real, parameter xvgang5
real, parameter xvgangb
real, parameter xsw_wght_nir