source: LMDZ6/trunk/libf/phylmd/surf_landice_mod.F90 @ 3900

Last change on this file since 3900 was 3900, checked in by evignon, 3 years ago

Commission de la nouvelle interface LMDZ-SISVAT
la prochaine commission consistera a supprimer l'ancien repertoire sisvat
et a faire un peu de nettoyage.

  • Property copyright set to
    Name of program: LMDZ
    Creation date: 1984
    Version: LMDZ5
    License: CeCILL version 2
    Holder: Laboratoire de m\'et\'eorologie dynamique, CNRS, UMR 8539
    See the license file in the root directory
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 KB
Line 
1!
2MODULE surf_landice_mod
3 
4  IMPLICIT NONE
5
6CONTAINS
7!
8!****************************************************************************************
9!
10  SUBROUTINE surf_landice(itime, dtime, knon, knindex, &
11       rlon, rlat, debut, lafin, &
12       rmu0, lwdownm, albedo, pphi1, &
13       swnet, lwnet, tsurf, p1lay, &
14       cdragh, cdragm, precip_rain, precip_snow, temp_air, spechum, &
15       AcoefH, AcoefQ, BcoefH, BcoefQ, &
16       AcoefU, AcoefV, BcoefU, BcoefV, &
17       ps, u1, v1, gustiness, rugoro, pctsrf, &
18       snow, qsurf, qsol, agesno, &
19       tsoil, z0m, z0h, SFRWL, alb_dir, alb_dif, evap, fluxsens, fluxlat, &
20       tsurf_new, dflux_s, dflux_l, &
21       alt, slope, cloudf, &
22       snowhgt, qsnow, to_ice, sissnow, &
23       alb3, runoff, &
24       flux_u1, flux_v1)
25
26    USE dimphy
27    USE surface_data,     ONLY : type_ocean, calice, calsno, landice_opt, iflag_albcalc
28    USE fonte_neige_mod,  ONLY : fonte_neige,run_off_lic,fqcalving_global,ffonte_global,fqfonte_global,runofflic_global
29    USE cpl_mod,          ONLY : cpl_send_landice_fields
30    USE calcul_fluxs_mod
31    USE phys_output_var_mod
32!FC
33    USE ioipsl_getin_p_mod, ONLY : getin_p
34
35#ifdef CPP_SISVAT
36    USE surf_sisvat_mod,  ONLY : surf_sisvat
37#endif
38
39#ifdef CPP_INLANDSIS
40    USE surf_inlandsis_mod,  ONLY : surf_inlandsis
41#endif
42
43    USE indice_sol_mod
44
45!    INCLUDE "indicesol.h"
46    INCLUDE "dimsoil.h"
47    INCLUDE "YOMCST.h"
48    INCLUDE "clesphys.h"
49
50! Input variables
51!****************************************************************************************
52    INTEGER, INTENT(IN)                           :: itime, knon
53    INTEGER, DIMENSION(klon), INTENT(in)          :: knindex
54    REAL, INTENT(in)                              :: dtime
55    REAL, DIMENSION(klon), INTENT(IN)             :: swnet ! net shortwave radiance
56    REAL, DIMENSION(klon), INTENT(IN)             :: lwnet ! net longwave radiance
57    REAL, DIMENSION(klon), INTENT(IN)             :: tsurf
58    REAL, DIMENSION(klon), INTENT(IN)             :: p1lay
59    REAL, DIMENSION(klon), INTENT(IN)             :: cdragh, cdragm
60    REAL, DIMENSION(klon), INTENT(IN)             :: precip_rain, precip_snow
61    REAL, DIMENSION(klon), INTENT(IN)             :: temp_air, spechum
62    REAL, DIMENSION(klon), INTENT(IN)             :: AcoefH, AcoefQ
63    REAL, DIMENSION(klon), INTENT(IN)             :: BcoefH, BcoefQ
64    REAL, DIMENSION(klon), INTENT(IN)             :: AcoefU, AcoefV, BcoefU, BcoefV
65    REAL, DIMENSION(klon), INTENT(IN)             :: ps
66    REAL, DIMENSION(klon), INTENT(IN)             :: u1, v1, gustiness
67    REAL, DIMENSION(klon), INTENT(IN)             :: rugoro
68    REAL, DIMENSION(klon,nbsrf), INTENT(IN)       :: pctsrf
69
70    LOGICAL,  INTENT(IN)                          :: debut   !true if first step
71    LOGICAL,  INTENT(IN)                          :: lafin   !true if last step
72    REAL, DIMENSION(klon), INTENT(IN)             :: rlon, rlat
73    REAL, DIMENSION(klon), INTENT(IN)             :: rmu0
74    REAL, DIMENSION(klon), INTENT(IN)             :: lwdownm !ylwdown
75    REAL, DIMENSION(klon), INTENT(IN)             :: albedo  !mean albedo
76    REAL, DIMENSION(klon), INTENT(IN)             :: pphi1   
77    REAL, DIMENSION(klon), INTENT(IN)             :: alt   !mean altitude of the grid box 
78    REAL, DIMENSION(klon), INTENT(IN)             :: slope   !mean slope in grid box 
79    REAL, DIMENSION(klon), INTENT(IN)             :: cloudf  !total cloud fraction
80
81! In/Output variables
82!****************************************************************************************
83    REAL, DIMENSION(klon), INTENT(INOUT)          :: snow, qsol
84    REAL, DIMENSION(klon), INTENT(INOUT)          :: agesno
85    REAL, DIMENSION(klon, nsoilmx), INTENT(INOUT) :: tsoil
86
87! Output variables
88!****************************************************************************************
89    REAL, DIMENSION(klon), INTENT(OUT)            :: qsurf
90    REAL, DIMENSION(klon), INTENT(OUT)            :: z0m, z0h
91!albedo SB >>>
92!    REAL, DIMENSION(klon), INTENT(OUT)            :: alb1  ! new albedo in visible SW interval
93!    REAL, DIMENSION(klon), INTENT(OUT)            :: alb2  ! new albedo in near IR interval
94    REAL, DIMENSION(6), INTENT(IN)                :: SFRWL
95    REAL, DIMENSION(klon,nsw), INTENT(OUT)        :: alb_dir,alb_dif
96!albedo SB <<<
97    REAL, DIMENSION(klon), INTENT(OUT)            :: evap, fluxsens, fluxlat
98    REAL, DIMENSION(klon), INTENT(OUT)            :: tsurf_new
99    REAL, DIMENSION(klon), INTENT(OUT)            :: dflux_s, dflux_l     
100    REAL, DIMENSION(klon), INTENT(OUT)            :: flux_u1, flux_v1
101
102    REAL, DIMENSION(klon), INTENT(OUT)           :: alb3
103    REAL, DIMENSION(klon), INTENT(OUT)           :: qsnow   !column water in snow [kg/m2]
104    REAL, DIMENSION(klon), INTENT(OUT)           :: snowhgt !Snow height (m)
105    REAL, DIMENSION(klon), INTENT(OUT)           :: to_ice
106    REAL, DIMENSION(klon), INTENT(OUT)           :: sissnow
107    REAL, DIMENSION(klon), INTENT(OUT)           :: runoff  !Land ice runoff
108 
109
110! Local variables
111!****************************************************************************************
112    REAL, DIMENSION(klon)    :: soilcap, soilflux
113    REAL, DIMENSION(klon)    :: cal, beta, dif_grnd
114    REAL, DIMENSION(klon)    :: zfra, alb_neig
115    REAL, DIMENSION(klon)    :: radsol
116    REAL, DIMENSION(klon)    :: u0, v0, u1_lay, v1_lay, ustar
117    INTEGER                  :: i,j,nt
118    REAL, DIMENSION(klon)    :: fqfonte,ffonte
119    REAL, DIMENSION(klon)    :: emis_new                  !Emissivity
120    REAL, DIMENSION(klon)    :: swdown,lwdown
121    REAL, DIMENSION(klon)    :: precip_snow_adv, snow_adv !Snow Drift precip./advection (not used in inlandsis)
122    REAL, DIMENSION(klon)    :: erod                      !erosion of surface snow (flux, kg/m2/s like evap)
123    REAL, DIMENSION(klon)    :: zsl_height, wind_velo     !surface layer height, wind spd
124    REAL, DIMENSION(klon)    :: dens_air,  snow_cont_air  !air density; snow content air
125    REAL, DIMENSION(klon)    :: alb_soil                  !albedo of underlying ice
126    REAL, DIMENSION(klon)    :: pexner                    !Exner potential
127    REAL                     :: pref
128    REAL, DIMENSION(klon,nsoilmx) :: tsoil0               !modif
129    REAL                          :: dtis                ! subtimestep
130    LOGICAL                       :: debut_is, lafin_is  ! debut and lafin for inlandsis
131
132    CHARACTER (len = 20)                      :: modname = 'surf_landice'
133    CHARACTER (len = 80)                      :: abort_message
134
135
136    REAL,DIMENSION(klon) :: alb1,alb2
137    REAL, DIMENSION (klon,6) :: alb6
138! End definition
139!****************************************************************************************
140!FC
141!FC
142   REAL,SAVE :: alb_vis_sno_lic
143  !$OMP THREADPRIVATE(alb_vis_sno_lic)
144   REAL,SAVE :: alb_nir_sno_lic
145  !$OMP THREADPRIVATE(alb_nir_sno_lic)
146  LOGICAL, SAVE :: firstcall = .TRUE.
147  !$OMP THREADPRIVATE(firstcall)
148
149
150!FC firtscall initializations
151!******************************************************************************************
152  IF (firstcall) THEN
153  alb_vis_sno_lic=0.77
154  CALL getin_p('alb_vis_sno_lic',alb_vis_sno_lic)
155           PRINT*, 'alb_vis_sno_lic',alb_vis_sno_lic
156  alb_nir_sno_lic=0.77
157  CALL getin_p('alb_nir_sno_lic',alb_nir_sno_lic)
158           PRINT*, 'alb_nir_sno_lic',alb_nir_sno_lic
159 
160!  z0m=1.e-3
161!  z0h = z0m
162  firstcall=.false.
163  ENDIF
164!******************************************************************************************
165
166! Initialize output variables
167    alb3(:) = 999999.
168    alb2(:) = 999999.
169    alb1(:) = 999999.
170   
171    runoff(:) = 0.
172!****************************************************************************************
173! Calculate total absorbed radiance at surface
174!
175!****************************************************************************************
176    radsol(:) = 0.0
177    radsol(1:knon) = swnet(1:knon) + lwnet(1:knon)
178
179!****************************************************************************************
180!  landice_opt = 0 : soil_model, calcul_flux, fonte_neige, ... 
181!  landice_opt = 1  : prepare and call SISVAT snow model
182!  landice_opt = 2  : prepare and call INLANDSIS snow model
183!****************************************************************************************
184
185
186    IF (landice_opt .EQ. 1) THEN
187   
188!****************************************************************************************
189! CALL to SISVAT interface
190!****************************************************************************************
191
192#ifdef CPP_SISVAT
193       ! Prepare for calling SISVAT
194       
195       ! Calculate incoming flux for SW and LW interval: swdown, lwdown
196       swdown(:)        = 0.0
197       lwdown(:)        = 0.0
198       DO i = 1, knon
199          swdown(i)        = swnet(i)/(1-albedo(i))
200          lwdown(i)        = lwdownm(i)
201       END DO
202       
203       ! Set constants and compute some input for SISVAT
204       snow_adv(:)      = 0.                          ! no snow blown in for now
205       snow_cont_air(:) = 0.       
206       alb_soil(:)      = albedo(:)
207       pref             = 100000.                     ! = 1000 hPa
208       DO i = 1, knon
209          wind_velo(i)     = u1(i)**2 + v1(i)**2
210          wind_velo(i)     = wind_velo(i)**0.5
211          pexner(i)        = (p1lay(i)/pref)**(RD/RCPD)
212          dens_air(i)      = p1lay(i)/RD/temp_air(i)  ! dry air density
213          zsl_height(i)     = pphi1(i)/RG             
214       END DO
215
216
217       ! config: compute everything with SV but temperatures afterwards with soil/calculfluxs
218       DO i = 1, knon
219          tsoil0(i,:)=tsoil(i,:)
220       END DO
221           ! Martin
222           PRINT*, 'on appelle surf_sisvat'
223           ! Martin
224       CALL surf_sisvat(knon, rlon, rlat, knindex, itime, dtime, debut, lafin, &
225            rmu0, swdown, lwdown, pexner, ps, p1lay, &
226            precip_rain, precip_snow, precip_snow_adv, snow_adv, &
227            zsl_height, wind_velo, temp_air, dens_air, spechum, tsurf, &
228            rugoro, snow_cont_air, alb_soil, slope, cloudf, &
229            radsol, qsol, tsoil0, snow, snowhgt, qsnow, to_ice,sissnow, agesno, &
230            AcoefH, AcoefQ, BcoefH, BcoefQ, cdragh, &
231            run_off_lic, evap, fluxsens, fluxlat, dflux_s, dflux_l, &       
232            tsurf_new, alb1, alb2, alb3, emis_new, z0m, qsurf)
233       z0h(1:knon)=z0m(1:knon) ! en attendant mieux
234       
235       ! Suppose zero surface speed
236       u0(:)            = 0.0
237       v0(:)            = 0.0
238       ! The calculation of heat/water fluxes, otherwise done by "CALL calcul_fluxs" is
239       ! integrated in SISVAT, using the same method. It can be found in "sisvat.f", in the
240       ! subroutine "SISVAT_TS2".
241       ! u0, v0=0., dif_grnd=0. and beta=1 are assumed there!
242       
243       CALL calcul_flux_wind(knon, dtime, &
244            u0, v0, u1, v1, gustiness, cdragm, &
245            AcoefU, AcoefV, BcoefU, BcoefV, &
246            p1lay, temp_air, &
247            flux_u1, flux_v1)
248#else
249       abort_message='Pb de coherence: landice_opt = 1 mais CPP_SISVAT = .false.'
250       CALL abort_physic(modname,abort_message,1)
251#endif
252
253!****************************************************************************************
254! CALL to INLANDSIS interface
255!****************************************************************************************
256
257    ELSE IF (landice_opt .EQ. 2) THEN
258#ifdef CPP_INLANDSIS
259
260        debut_is=debut
261        lafin_is=.false.
262        ! Suppose zero surface speed
263        u0(:)            = 0.0
264        v0(:)            = 0.0
265
266
267        CALL calcul_flux_wind(knon, dtime, &
268         u0, v0, u1, v1, gustiness, cdragm, &
269         AcoefU, AcoefV, BcoefU, BcoefV, &
270         p1lay, temp_air, &
271         flux_u1, flux_v1)
272
273       
274       ! Set constants and compute some input for SISVAT
275       ! = 1000 hPa
276       ! and calculate incoming flux for SW and LW interval: swdown, lwdown
277       swdown(:)        = 0.0
278       lwdown(:)        = 0.0
279       snow_cont_air(:) = 0.  ! the snow content in air is not a prognostic variable of the model     
280       alb_soil(:)      = 0.4 ! before albedo(:) but here it is the ice albedo that we have to set
281       ustar(:)         = 0.
282       pref             = 100000.       
283       DO i = 1, knon
284          swdown(i)        = swnet(i)/(1-albedo(i))
285          lwdown(i)        = lwdownm(i)
286          wind_velo(i)     = u1(i)**2 + v1(i)**2
287          wind_velo(i)     = wind_velo(i)**0.5
288          pexner(i)        = (p1lay(i)/pref)**(RD/RCPD)
289          dens_air(i)      = p1lay(i)/RD/temp_air(i)  ! dry air density
290          zsl_height(i)    = pphi1(i)/RG     
291          tsoil0(i,:)      = tsoil(i,:) 
292          ustar(i)= (cdragm(i)*(wind_velo(i)**2))**0.5   
293       END DO
294       
295
296
297        dtis=dtime
298
299          IF (lafin) THEN
300            lafin_is=.true.
301          END IF
302
303          CALL surf_inlandsis(knon, rlon, rlat, knindex, itime, dtis, debut_is, lafin_is,&
304            rmu0, swdown, lwdown, albedo, pexner, ps, p1lay, precip_rain, precip_snow,   &
305            zsl_height, wind_velo, ustar, temp_air, dens_air, spechum, tsurf,&
306            rugoro, snow_cont_air, alb_soil, alt, slope, cloudf, &
307            radsol, qsol, tsoil0, snow, zfra, snowhgt, qsnow, to_ice, sissnow,agesno,   &
308            AcoefH, AcoefQ, BcoefH, BcoefQ, cdragm, cdragh, &
309            run_off_lic, fqfonte, ffonte, evap, erod, fluxsens, fluxlat,dflux_s, dflux_l, &
310            tsurf_new, alb1, alb2, alb3, alb6, &
311            emis_new, z0m, z0h, qsurf)
312
313          debut_is=.false.
314
315
316        ! Treatment of snow melting and calving
317
318        ! for consistency with standard LMDZ, add calving to run_off_lic
319        run_off_lic(:)=run_off_lic(:) + to_ice(:)
320
321        DO i = 1, knon
322           ffonte_global(knindex(i),is_lic)    = ffonte(i)
323           fqfonte_global(knindex(i),is_lic)   = fqfonte(i)! net melting= melting - refreezing
324           fqcalving_global(knindex(i),is_lic) = to_ice(i) ! flux
325           runofflic_global(knindex(i)) = run_off_lic(i)
326        ENDDO
327        ! Here, we assume that the calving term is equal to the to_ice term
328        ! (no ice accumulation)
329
330
331#else
332       abort_message='Pb de coherence: landice_opt = 2 mais CPP_INLANDSIS = .false.'
333       CALL abort_physic(modname,abort_message,1)
334#endif
335
336
337
338    ELSE
339
340!****************************************************************************************
341! Soil calculations
342!
343!****************************************************************************************
344
345    ! EV: use calbeta
346    CALL calbeta(dtime, is_lic, knon, snow, qsol, beta, cal, dif_grnd)
347
348
349    ! use soil model and recalculate properly cal
350    IF (soil_model) THEN
351       CALL soil(dtime, is_lic, knon, snow, tsurf, tsoil, soilcap, soilflux)
352       cal(1:knon) = RCPD / soilcap(1:knon)
353       radsol(1:knon)  = radsol(1:knon) + soilflux(1:knon)
354    ELSE
355       cal = RCPD * calice
356       WHERE (snow > 0.0) cal = RCPD * calsno
357    ENDIF
358
359
360!****************************************************************************************
361! Calulate fluxes
362!
363!****************************************************************************************
364!    beta(:) = 1.0
365!    dif_grnd(:) = 0.0
366
367! Suppose zero surface speed
368    u0(:)=0.0
369    v0(:)=0.0
370    u1_lay(:) = u1(:) - u0(:)
371    v1_lay(:) = v1(:) - v0(:)
372
373    CALL calcul_fluxs(knon, is_lic, dtime, &
374         tsurf, p1lay, cal, beta, cdragh, cdragh, ps, &
375         precip_rain, precip_snow, snow, qsurf,  &
376         radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, gustiness, &
377         1.,AcoefH, AcoefQ, BcoefH, BcoefQ, &
378         tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
379
380    CALL calcul_flux_wind(knon, dtime, &
381         u0, v0, u1, v1, gustiness, cdragm, &
382         AcoefU, AcoefV, BcoefU, BcoefV, &
383         p1lay, temp_air, &
384         flux_u1, flux_v1)
385
386!****************************************************************************************
387! Calculate snow height, age, run-off,..
388!   
389!****************************************************************************************
390    CALL fonte_neige(knon, is_lic, knindex, dtime, &
391         tsurf, precip_rain, precip_snow, &
392         snow, qsol, tsurf_new, evap)
393
394
395!****************************************************************************************
396! Calculate albedo
397!
398!****************************************************************************************
399    CALL albsno(klon,knon,dtime,agesno(:),alb_neig(:), precip_snow(:)) 
400
401    WHERE (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
402    zfra(1:knon) = MAX(0.0,MIN(1.0,snow(1:knon)/(snow(1:knon)+10.0)))
403    alb1(1:knon) = alb_neig(1:knon)*zfra(1:knon) + &
404         0.6 * (1.0-zfra(1:knon))
405!
406!IM: plusieurs choix/tests sur l'albedo des "glaciers continentaux"
407!       alb1(1 : knon)  = 0.6 !IM cf FH/GK
408!       alb1(1 : knon)  = 0.82
409!       alb1(1 : knon)  = 0.77 !211003 Ksta0.77
410!       alb1(1 : knon)  = 0.8 !KstaTER0.8 & LMD_ARMIP5
411!IM: KstaTER0.77 & LMD_ARMIP6   
412
413! Attantion: alb1 and alb2 are not the same!
414    alb1(1:knon)  = alb_vis_sno_lic
415    alb2(1:knon)  = alb_nir_sno_lic
416
417
418!****************************************************************************************
419! Rugosity
420!
421!****************************************************************************************
422    z0m=1.e-3
423    z0h = z0m
424    z0m = SQRT(z0m**2+rugoro**2)
425
426
427
428    END IF ! landice_opt
429
430
431!****************************************************************************************
432! Send run-off on land-ice to coupler if coupled ocean.
433! run_off_lic has been calculated in fonte_neige or surf_sisvat
434!
435!****************************************************************************************
436    IF (type_ocean=='couple') THEN
437       CALL cpl_send_landice_fields(itime, knon, knindex, run_off_lic)
438    ENDIF
439
440 ! transfer runoff rate [kg/m2/s](!) to physiq for output
441    runoff(1:knon)=run_off_lic(1:knon)/dtime
442
443 
444!****************************************************************************************
445! Etienne: comment these lines because of duplication just below
446!       snow_o=0.
447!       zfra_o = 0.
448!       DO j = 1, knon
449!           i = knindex(j)
450!           snow_o(i) = snow(j)
451!           zfra_o(i) = zfra(j)
452!       ENDDO
453!
454!****************************************************************************************
455       snow_o=0.
456       zfra_o = 0.
457       DO j = 1, knon
458           i = knindex(j)
459           snow_o(i) = snow(j)
460           zfra_o(i) = zfra(j)
461       ENDDO
462
463
464!albedo SB >>>
465     select case(NSW)
466     case(2)
467       alb_dir(1:knon,1)=alb1(1:knon)
468       alb_dir(1:knon,2)=alb2(1:knon)
469     case(4)
470       alb_dir(1:knon,1)=alb1(1:knon)
471       alb_dir(1:knon,2)=alb2(1:knon)
472       alb_dir(1:knon,3)=alb2(1:knon)
473       alb_dir(1:knon,4)=alb2(1:knon)
474     case(6)
475       alb_dir(1:knon,1)=alb1(1:knon)
476       alb_dir(1:knon,2)=alb1(1:knon)
477       alb_dir(1:knon,3)=alb1(1:knon)
478       alb_dir(1:knon,4)=alb2(1:knon)
479       alb_dir(1:knon,5)=alb2(1:knon)
480       alb_dir(1:knon,6)=alb2(1:knon)
481
482       IF ((landice_opt .EQ.2) .AND. (iflag_albcalc .EQ. 2)) THEN
483       alb_dir(1:knon,1)=alb6(1:knon,1)
484       alb_dir(1:knon,2)=alb6(1:knon,2)
485       alb_dir(1:knon,3)=alb6(1:knon,3)
486       alb_dir(1:knon,4)=alb6(1:knon,4)
487       alb_dir(1:knon,5)=alb6(1:knon,5)
488       alb_dir(1:knon,6)=alb6(1:knon,6)
489       ENDIF
490
491     end select
492alb_dif=alb_dir
493!albedo SB <<<
494
495 
496 
497
498  END SUBROUTINE surf_landice
499!
500!****************************************************************************************
501!
502END MODULE surf_landice_mod
503
504
505
Note: See TracBrowser for help on using the repository browser.