/[lmdze]/trunk/phylmd/Interface_surf/interface_surf.f
ViewVC logotype

Annotation of /trunk/phylmd/Interface_surf/interface_surf.f

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (hide annotations)
Fri Apr 8 12:43:31 2011 UTC (13 years, 1 month ago) by guez
Original Path: trunk/libf/phylmd/interface_surf.f90
File size: 60167 byte(s)
"start_init_phys" is now called directly by "etat0" instead of through
"start_init_dyn". "qsol_2d" is no longer a variable of module
"start_init_phys_m", it is an argument of
"start_init_phys". "start_init_dyn" now receives "tsol_2d" from
"etat0".

Split file "vlspltqs.f" into "vlspltqs.f90", "vlxqs.f90" and
""vlyqs.f90".

In "start_init_orog", replaced calls to "flin*" by calls to NetCDF95.

1 guez 3 MODULE interface_surf
2    
3 guez 14 ! From phylmd/interface_surf.F90, version 1.8 2005/05/25 13:10:09
4 guez 3
5 guez 38 ! Ce module regroupe toutes les routines gérant l'interface entre le
6     ! modèle atmosphérique et les modèles de surface (sols continentaux,
7     ! océans, glaces). Les routines sont les suivantes. "interfsurf_hq" :
8     ! routine d'aiguillage vers les interfaces avec les différents
9     ! modèles de surface ; "interfoce_*" : routines d'interface proprement
10     ! dites.
11 guez 3
12 guez 38 ! L. Fairhead, LMD, february 2000
13 guez 3
14     IMPLICIT none
15    
16     PRIVATE
17     PUBLIC :: interfsurf_hq
18    
19 guez 38 ! run_off ruissellement total
20     REAL, ALLOCATABLE, DIMENSION(:), SAVE :: run_off, run_off_lic
21     real, allocatable, dimension(:), save :: coastalflow, riverflow
22 guez 3
23 guez 14 REAL, ALLOCATABLE, DIMENSION(:, :), SAVE :: tmp_rriv, tmp_rcoa, tmp_rlic
24 guez 38 ! pour simuler la fonte des glaciers antarctiques
25 guez 14 REAL, ALLOCATABLE, DIMENSION(:, :), SAVE :: coeff_iceberg
26 guez 38 real, save :: surf_maille
27     real, save :: cte_flux_iceberg = 6.3e7
28     integer, save :: num_antarctic = 1
29     REAL, save :: tau_calv
30 guez 3
31     CONTAINS
32    
33 guez 38 SUBROUTINE interfsurf_hq(itime, dtime, date0, jour, rmu0, &
34     klon, iim, jjm, nisurf, knon, knindex, pctsrf, &
35     rlon, rlat, cufi, cvfi, &
36     debut, lafin, ok_veget, soil_model, nsoilmx, tsoil, qsol, &
37     zlev, u1_lay, v1_lay, temp_air, spechum, epot_air, ccanopy, &
38     tq_cdrag, petAcoef, peqAcoef, petBcoef, peqBcoef, &
39     precip_rain, precip_snow, sollw, sollwdown, swnet, swdown, &
40     fder, taux, tauy, &
41     windsp, &
42     rugos, rugoro, &
43     albedo, snow, qsurf, &
44     tsurf, p1lay, ps, radsol, &
45     ocean, npas, nexca, zmasq, &
46     evap, fluxsens, fluxlat, dflux_l, dflux_s, &
47     tsol_rad, tsurf_new, alb_new, alblw, emis_new, &
48     z0_new, pctsrf_new, agesno, fqcalving, ffonte, run_off_lic_0, &
49     flux_o, flux_g, tslab, seaice)
50 guez 3
51     ! Cette routine sert d'aiguillage entre l'atmosphère et la surface
52 guez 14 ! en général (sols continentaux, océans, glaces) pour les flux de
53 guez 3 ! chaleur et d'humidité.
54     ! En pratique l'interface se fait entre la couche limite du modèle
55     ! atmosphérique ("clmain.F") et les routines de surface
56     ! ("sechiba", "oasis"...).
57    
58     ! L.Fairhead 02/2000
59    
60 guez 14 use abort_gcm_m, only: abort_gcm
61     use gath_cpl, only: gath2cpl
62     use indicesol
63 guez 38 use SUPHEC_M
64 guez 14 use albsno_m, only: albsno
65    
66     ! Parametres d'entree
67 guez 3 ! input:
68 guez 38 ! klon nombre total de points de grille
69     ! iim, jjm nbres de pts de grille
70     ! dtime pas de temps de la physique (en s)
71     ! date0 jour initial
72     ! jour jour dans l'annee en cours,
73     ! rmu0 cosinus de l'angle solaire zenithal
74     ! nexca pas de temps couplage
75     ! nisurf index de la surface a traiter (1 = sol continental)
76     ! knon nombre de points de la surface a traiter
77     ! knindex index des points de la surface a traiter
78     ! pctsrf tableau des pourcentages de surface de chaque maille
79     ! rlon longitudes
80     ! rlat latitudes
81     ! cufi, cvfi resolution des mailles en x et y (m)
82     ! debut logical: 1er appel a la physique
83     ! lafin logical: dernier appel a la physique
84     ! ok_veget logical: appel ou non au schema de surface continental
85     ! (si false calcul simplifie des fluxs sur les continents)
86     ! zlev hauteur de la premiere couche
87     ! u1_lay vitesse u 1ere couche
88     ! v1_lay vitesse v 1ere couche
89     ! temp_air temperature de l'air 1ere couche
90     ! spechum humidite specifique 1ere couche
91     ! epot_air temp potentielle de l'air
92     ! ccanopy concentration CO2 canopee
93     ! tq_cdrag cdrag
94     ! petAcoef coeff. A de la resolution de la CL pour t
95     ! peqAcoef coeff. A de la resolution de la CL pour q
96     ! petBcoef coeff. B de la resolution de la CL pour t
97     ! peqBcoef coeff. B de la resolution de la CL pour q
98     ! precip_rain precipitation liquide
99     ! precip_snow precipitation solide
100     ! sollw flux IR net a la surface
101     ! sollwdown flux IR descendant a la surface
102     ! swnet flux solaire net
103     ! swdown flux solaire entrant a la surface
104     ! albedo albedo de la surface
105     ! tsurf temperature de surface
106     ! tslab temperature slab ocean
107     ! pctsrf_slab pourcentages (0-1) des sous-surfaces dans le slab
108     ! tmp_pctsrf_slab = pctsrf_slab
109     ! p1lay pression 1er niveau (milieu de couche)
110     ! ps pression au sol
111     ! radsol rayonnement net aus sol (LW + SW)
112     ! ocean type d'ocean utilise ("force" ou "slab" mais pas "couple")
113     ! fder derivee des flux (pour le couplage)
114     ! taux, tauy tension de vents
115     ! windsp module du vent a 10m
116     ! rugos rugosite
117     ! zmasq masque terre/ocean
118     ! rugoro rugosite orographique
119     ! run_off_lic_0 runoff glacier du pas de temps precedent
120     integer, intent(IN) :: itime ! numero du pas de temps
121 guez 3 integer, intent(IN) :: iim, jjm
122     integer, intent(IN) :: klon
123     real, intent(IN) :: dtime
124     real, intent(IN) :: date0
125     integer, intent(IN) :: jour
126 guez 38 real, intent(IN) :: rmu0(klon)
127 guez 3 integer, intent(IN) :: nisurf
128     integer, intent(IN) :: knon
129     integer, dimension(klon), intent(in) :: knindex
130 guez 14 real, dimension(klon, nbsrf), intent(IN) :: pctsrf
131 guez 3 logical, intent(IN) :: debut, lafin, ok_veget
132     real, dimension(klon), intent(IN) :: rlon, rlat
133     real, dimension(klon), intent(IN) :: cufi, cvfi
134     real, dimension(klon), intent(INOUT) :: tq_cdrag
135     real, dimension(klon), intent(IN) :: zlev
136     real, dimension(klon), intent(IN) :: u1_lay, v1_lay
137     real, dimension(klon), intent(IN) :: temp_air, spechum
138     real, dimension(klon), intent(IN) :: epot_air, ccanopy
139     real, dimension(klon), intent(IN) :: petAcoef, peqAcoef
140     real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
141     real, dimension(klon), intent(IN) :: precip_rain, precip_snow
142     real, dimension(klon), intent(IN) :: sollw, sollwdown, swnet, swdown
143     real, dimension(klon), intent(IN) :: ps, albedo
144     real, dimension(klon), intent(IN) :: tsurf, p1lay
145     !IM: "slab" ocean
146     real, dimension(klon), intent(INOUT) :: tslab
147     real, allocatable, dimension(:), save :: tmp_tslab
148     real, dimension(klon), intent(OUT) :: flux_o, flux_g
149 guez 38 real, dimension(klon), intent(INOUT) :: seaice ! glace de mer (kg/m2)
150 guez 14 REAL, DIMENSION(klon), INTENT(INOUT) :: radsol, fder
151 guez 3 real, dimension(klon), intent(IN) :: zmasq
152     real, dimension(klon), intent(IN) :: taux, tauy, rugos, rugoro
153     real, dimension(klon), intent(IN) :: windsp
154 guez 12 character(len=*), intent(IN):: ocean
155 guez 38 integer :: npas, nexca ! nombre et pas de temps couplage
156 guez 3 real, dimension(klon), intent(INOUT) :: evap, snow, qsurf
157     !! PB ajout pour soil
158 guez 12 logical, intent(in):: soil_model
159 guez 38 integer :: nsoilmx
160 guez 3 REAL, DIMENSION(klon, nsoilmx) :: tsoil
161     REAL, dimension(klon), intent(INOUT) :: qsol
162 guez 38 REAL, dimension(klon) :: soilcap
163     REAL, dimension(klon) :: soilflux
164 guez 14
165 guez 3 ! Parametres de sortie
166 guez 14 ! output:
167 guez 38 ! evap evaporation totale
168     ! fluxsens flux de chaleur sensible
169     ! fluxlat flux de chaleur latente
170     ! tsol_rad
171     ! tsurf_new temperature au sol
172     ! alb_new albedo
173     ! emis_new emissivite
174     ! z0_new surface roughness
175     ! pctsrf_new nouvelle repartition des surfaces
176 guez 3 real, dimension(klon), intent(OUT):: fluxsens, fluxlat
177     real, dimension(klon), intent(OUT):: tsol_rad, tsurf_new, alb_new
178     real, dimension(klon), intent(OUT):: alblw
179     real, dimension(klon), intent(OUT):: emis_new, z0_new
180     real, dimension(klon), intent(OUT):: dflux_l, dflux_s
181 guez 14 real, dimension(klon, nbsrf), intent(OUT) :: pctsrf_new
182 guez 3 real, dimension(klon), intent(INOUT):: agesno
183     real, dimension(klon), intent(INOUT):: run_off_lic_0
184    
185     ! Flux thermique utiliser pour fondre la neige
186 guez 38 !jld a rajouter real, dimension(klon), intent(INOUT):: ffonte
187 guez 3 real, dimension(klon), intent(INOUT):: ffonte
188     ! Flux d'eau "perdue" par la surface et nécessaire pour que limiter la
189     ! hauteur de neige, en kg/m2/s
190 guez 38 !jld a rajouter real, dimension(klon), intent(INOUT):: fqcalving
191 guez 3 real, dimension(klon), intent(INOUT):: fqcalving
192     !IM: "slab" ocean - Local
193     real, parameter :: t_grnd=271.35
194     real, dimension(klon) :: zx_sl
195     integer i
196     real, allocatable, dimension(:), save :: tmp_flux_o, tmp_flux_g
197     real, allocatable, dimension(:), save :: tmp_radsol
198 guez 14 real, allocatable, dimension(:, :), save :: tmp_pctsrf_slab
199 guez 3 real, allocatable, dimension(:), save :: tmp_seaice
200    
201     ! Local
202 guez 14 character (len = 20), save :: modname = 'interfsurf_hq'
203 guez 3 character (len = 80) :: abort_message
204 guez 38 logical, save :: first_call = .true.
205     integer, save :: error
206     integer :: ii
207     logical, save :: check = .false.
208 guez 3 real, dimension(klon):: cal, beta, dif_grnd, capsol
209 guez 38 real, parameter :: calice=1.0/(5.1444e+06*0.15), tau_gl=86400.*5.
210     real, parameter :: calsno=1./(2.3867e+06*.15)
211 guez 3 real, dimension(klon):: tsurf_temp
212     real, dimension(klon):: alb_neig, alb_eau
213     real, DIMENSION(klon):: zfra
214 guez 38 logical :: cumul = .false.
215 guez 14 INTEGER, dimension(1) :: iloc
216 guez 3 real, dimension(klon):: fder_prev
217     REAL, dimension(klon) :: bidule
218    
219     !-------------------------------------------------------------
220    
221 guez 14 if (check) write(*, *) 'Entree ', modname
222 guez 3
223     ! On doit commencer par appeler les schemas de surfaces continentales
224     ! car l'ocean a besoin du ruissellement qui est y calcule
225    
226     if (first_call) then
227     call conf_interface(tau_calv)
228     if (nisurf /= is_ter .and. klon > 1) then
229 guez 14 write(*, *)' *** Warning ***'
230     write(*, *)' nisurf = ', nisurf, ' /= is_ter = ', is_ter
231     write(*, *)'or on doit commencer par les surfaces continentales'
232 guez 3 abort_message='voir ci-dessus'
233 guez 14 call abort_gcm(modname, abort_message, 1)
234 guez 3 endif
235 guez 12 if (ocean /= 'slab' .and. ocean /= 'force') then
236 guez 14 write(*, *)' *** Warning ***'
237     write(*, *)'Option couplage pour l''ocean = ', ocean
238 guez 3 abort_message='option pour l''ocean non valable'
239 guez 14 call abort_gcm(modname, abort_message, 1)
240 guez 3 endif
241     if ( is_oce > is_sic ) then
242 guez 14 write(*, *)' *** Warning ***'
243     write(*, *)' Pour des raisons de sequencement dans le code'
244     write(*, *)' l''ocean doit etre traite avant la banquise'
245     write(*, *)' or is_oce = ', is_oce, '> is_sic = ', is_sic
246 guez 3 abort_message='voir ci-dessus'
247 guez 14 call abort_gcm(modname, abort_message, 1)
248 guez 3 endif
249     endif
250     first_call = .false.
251    
252     ! Initialisations diverses
253 guez 14
254 guez 3 ffonte(1:knon)=0.
255     fqcalving(1:knon)=0.
256    
257     cal = 999999. ; beta = 999999. ; dif_grnd = 999999. ; capsol = 999999.
258     alb_new = 999999. ; z0_new = 999999. ; alb_neig = 999999.
259     tsurf_new = 999999.
260     alblw = 999999.
261    
262     !IM: "slab" ocean; initialisations
263     flux_o = 0.
264     flux_g = 0.
265 guez 14
266 guez 3 if (.not. allocated(tmp_flux_o)) then
267     allocate(tmp_flux_o(klon), stat = error)
268     DO i=1, knon
269     tmp_flux_o(knindex(i))=flux_o(i)
270     ENDDO
271     if (error /= 0) then
272     abort_message='Pb allocation tmp_flux_o'
273 guez 14 call abort_gcm(modname, abort_message, 1)
274 guez 3 endif
275     endif
276 guez 38 if (.not. allocated(tmp_flux_g)) then
277 guez 3 allocate(tmp_flux_g(klon), stat = error)
278     DO i=1, knon
279     tmp_flux_g(knindex(i))=flux_g(i)
280     ENDDO
281     if (error /= 0) then
282     abort_message='Pb allocation tmp_flux_g'
283 guez 14 call abort_gcm(modname, abort_message, 1)
284 guez 3 endif
285     endif
286 guez 38 if (.not. allocated(tmp_radsol)) then
287 guez 3 allocate(tmp_radsol(klon), stat = error)
288     if (error /= 0) then
289     abort_message='Pb allocation tmp_radsol'
290 guez 14 call abort_gcm(modname, abort_message, 1)
291 guez 3 endif
292     endif
293     DO i=1, knon
294     tmp_radsol(knindex(i))=radsol(i)
295     ENDDO
296     if (.not. allocated(tmp_pctsrf_slab)) then
297 guez 14 allocate(tmp_pctsrf_slab(klon, nbsrf), stat = error)
298 guez 3 if (error /= 0) then
299     abort_message='Pb allocation tmp_pctsrf_slab'
300 guez 14 call abort_gcm(modname, abort_message, 1)
301 guez 3 endif
302     DO i=1, klon
303 guez 14 tmp_pctsrf_slab(i, 1:nbsrf)=pctsrf(i, 1:nbsrf)
304 guez 3 ENDDO
305     endif
306 guez 14
307 guez 3 if (.not. allocated(tmp_seaice)) then
308     allocate(tmp_seaice(klon), stat = error)
309     if (error /= 0) then
310     abort_message='Pb allocation tmp_seaice'
311 guez 14 call abort_gcm(modname, abort_message, 1)
312 guez 3 endif
313     DO i=1, klon
314     tmp_seaice(i)=seaice(i)
315     ENDDO
316     endif
317 guez 14
318 guez 3 if (.not. allocated(tmp_tslab)) then
319     allocate(tmp_tslab(klon), stat = error)
320     if (error /= 0) then
321     abort_message='Pb allocation tmp_tslab'
322 guez 14 call abort_gcm(modname, abort_message, 1)
323 guez 3 endif
324     endif
325     DO i=1, klon
326     tmp_tslab(i)=tslab(i)
327     ENDDO
328 guez 14
329 guez 3 ! Aiguillage vers les differents schemas de surface
330    
331     if (nisurf == is_ter) then
332 guez 14
333 guez 3 ! Surface "terre" appel a l'interface avec les sols continentaux
334 guez 14
335 guez 3 ! allocation du run-off
336     if (.not. allocated(coastalflow)) then
337     allocate(coastalflow(knon), stat = error)
338     if (error /= 0) then
339     abort_message='Pb allocation coastalflow'
340 guez 14 call abort_gcm(modname, abort_message, 1)
341 guez 3 endif
342     allocate(riverflow(knon), stat = error)
343     if (error /= 0) then
344     abort_message='Pb allocation riverflow'
345 guez 14 call abort_gcm(modname, abort_message, 1)
346 guez 3 endif
347     allocate(run_off(knon), stat = error)
348     if (error /= 0) then
349     abort_message='Pb allocation run_off'
350 guez 14 call abort_gcm(modname, abort_message, 1)
351 guez 3 endif
352 guez 38 !cym
353 guez 3 run_off=0.0
354     !cym
355    
356     !!$PB
357 guez 14 ALLOCATE (tmp_rriv(iim, jjm+1), stat=error)
358 guez 3 if (error /= 0) then
359     abort_message='Pb allocation tmp_rriv'
360 guez 14 call abort_gcm(modname, abort_message, 1)
361 guez 3 endif
362 guez 14 ALLOCATE (tmp_rcoa(iim, jjm+1), stat=error)
363 guez 3 if (error /= 0) then
364     abort_message='Pb allocation tmp_rcoa'
365 guez 14 call abort_gcm(modname, abort_message, 1)
366 guez 3 endif
367 guez 14 ALLOCATE (tmp_rlic(iim, jjm+1), stat=error)
368 guez 3 if (error /= 0) then
369     abort_message='Pb allocation tmp_rlic'
370 guez 14 call abort_gcm(modname, abort_message, 1)
371 guez 3 endif
372     tmp_rriv = 0.0
373     tmp_rcoa = 0.0
374     tmp_rlic = 0.0
375    
376     !!$
377     else if (size(coastalflow) /= knon) then
378 guez 14 write(*, *)'Bizarre, le nombre de points continentaux'
379     write(*, *)'a change entre deux appels. J''arrete ...'
380 guez 3 abort_message='voir ci-dessus'
381 guez 14 call abort_gcm(modname, abort_message, 1)
382 guez 3 endif
383     coastalflow = 0.
384     riverflow = 0.
385 guez 14
386 guez 3 ! Calcul age de la neige
387    
388     if (.not. ok_veget) then
389 guez 14 ! calcul albedo: lecture albedo fichier boundary conditions
390     ! puis ajout albedo neige
391     call interfsur_lim(itime, dtime, jour, klon, nisurf, knon, knindex, &
392     debut, alb_new, z0_new)
393    
394 guez 3 ! calcul snow et qsurf, hydrol adapté
395     CALL calbeta(dtime, nisurf, knon, snow, qsol, beta, capsol, dif_grnd)
396    
397     IF (soil_model) THEN
398 guez 14 CALL soil(dtime, nisurf, knon, snow, tsurf, tsoil, soilcap, &
399     soilflux)
400 guez 3 cal(1:knon) = RCPD / soilcap(1:knon)
401 guez 38 radsol(1:knon) = radsol(1:knon) + soilflux(1:knon)
402 guez 3 ELSE
403     cal = RCPD * capsol
404     ENDIF
405     CALL calcul_fluxs( klon, knon, nisurf, dtime, &
406 guez 38 tsurf, p1lay, cal, beta, tq_cdrag, ps, &
407     precip_rain, precip_snow, snow, qsurf, &
408     radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
409     petAcoef, peqAcoef, petBcoef, peqBcoef, &
410     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
411 guez 3
412     CALL fonte_neige( klon, knon, nisurf, dtime, &
413 guez 38 tsurf, p1lay, cal, beta, tq_cdrag, ps, &
414     precip_rain, precip_snow, snow, qsol, &
415     radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
416     petAcoef, peqAcoef, petBcoef, peqBcoef, &
417     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l, &
418     fqcalving, ffonte, run_off_lic_0)
419 guez 3
420 guez 14 call albsno(klon, knon, dtime, agesno, alb_neig, precip_snow)
421 guez 3 where (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
422 guez 14 zfra(1:knon) = max(0.0, min(1.0, snow(1:knon)/(snow(1:knon)+10.0)))
423 guez 38 alb_new(1 : knon) = alb_neig(1 : knon) *zfra(1:knon) + &
424 guez 14 alb_new(1 : knon)*(1.0-zfra(1:knon))
425 guez 3 z0_new = sqrt(z0_new**2+rugoro**2)
426     alblw(1 : knon) = alb_new(1 : knon)
427 guez 14 endif
428 guez 3
429     ! Remplissage des pourcentages de surface
430 guez 14 pctsrf_new(:, nisurf) = pctsrf(:, nisurf)
431 guez 3 else if (nisurf == is_oce) then
432     ! Surface "ocean" appel a l'interface avec l'ocean
433 guez 14 if (ocean == 'slab') then
434 guez 3 tsurf_new = tsurf
435     pctsrf_new = tmp_pctsrf_slab
436 guez 14 else
437     ! lecture conditions limites
438     call interfoce_lim(itime, dtime, jour, klon, nisurf, knon, knindex, &
439     debut, tsurf_new, pctsrf_new)
440 guez 3 endif
441    
442     tsurf_temp = tsurf_new
443     cal = 0.
444     beta = 1.
445     dif_grnd = 0.
446 guez 14 alb_neig = 0.
447     agesno = 0.
448 guez 3
449     call calcul_fluxs( klon, knon, nisurf, dtime, &
450 guez 38 tsurf_temp, p1lay, cal, beta, tq_cdrag, ps, &
451     precip_rain, precip_snow, snow, qsurf, &
452     radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
453     petAcoef, peqAcoef, petBcoef, peqBcoef, &
454     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
455 guez 3
456 guez 38 fder_prev = fder
457 guez 3 fder = fder_prev + dflux_s + dflux_l
458    
459     iloc = maxloc(fder(1:klon))
460     if (check.and.fder(iloc(1))> 0.) then
461 guez 14 WRITE(*, *)'**** Debug fder****'
462     WRITE(*, *)'max fder(', iloc(1), ') = ', fder(iloc(1))
463     WRITE(*, *)'fder_prev, dflux_s, dflux_l', fder_prev(iloc(1)), &
464 guez 38 dflux_s(iloc(1)), dflux_l(iloc(1))
465 guez 3 endif
466    
467     !IM: flux ocean-atmosphere utile pour le "slab" ocean
468     DO i=1, knon
469     zx_sl(i) = RLVTT
470     if (tsurf_new(i) .LT. RTT) zx_sl(i) = RLSTT
471     flux_o(i) = fluxsens(i)-evap(i)*zx_sl(i)
472     tmp_flux_o(knindex(i)) = flux_o(i)
473     tmp_radsol(knindex(i))=radsol(i)
474     ENDDO
475 guez 14
476 guez 3 ! 2eme appel a interfoce pour le cumul des champs (en particulier
477     ! fluxsens et fluxlat calcules dans calcul_fluxs)
478 guez 14
479 guez 38 if (ocean == 'slab ') then
480 guez 3 seaice=tmp_seaice
481     cumul = .true.
482     call interfoce_slab(klon, debut, itime, dtime, jour, &
483 guez 38 tmp_radsol, tmp_flux_o, tmp_flux_g, pctsrf, &
484     tslab, seaice, pctsrf_new)
485 guez 14
486 guez 3 tmp_pctsrf_slab=pctsrf_new
487     DO i=1, knon
488     tsurf_new(i)=tslab(knindex(i))
489 guez 14 ENDDO
490 guez 3 endif
491    
492     ! calcul albedo
493     if ( minval(rmu0) == maxval(rmu0) .and. minval(rmu0) == -999.999 ) then
494 guez 14 CALL alboc(FLOAT(jour), rlat, alb_eau)
495 guez 38 else ! cycle diurne
496 guez 14 CALL alboc_cd(rmu0, alb_eau)
497 guez 3 endif
498     DO ii =1, knon
499     alb_new(ii) = alb_eau(knindex(ii))
500     enddo
501    
502     z0_new = sqrt(rugos**2 + rugoro**2)
503     alblw(1:knon) = alb_new(1:knon)
504     else if (nisurf == is_sic) then
505 guez 14 if (check) write(*, *)'sea ice, nisurf = ', nisurf
506 guez 3
507 guez 14 ! Surface "glace de mer" appel a l'interface avec l'ocean
508 guez 3
509 guez 14
510 guez 38 if (ocean == 'slab ') then
511 guez 3 pctsrf_new=tmp_pctsrf_slab
512 guez 14
513 guez 3 DO ii = 1, knon
514     tsurf_new(ii) = tsurf(ii)
515 guez 14 IF (pctsrf_new(knindex(ii), nisurf) < EPSFRA) then
516 guez 3 snow(ii) = 0.0
517     tsurf_new(ii) = RTT - 1.8
518 guez 14 IF (soil_model) tsoil(ii, :) = RTT -1.8
519 guez 3 ENDIF
520     ENDDO
521    
522     CALL calbeta(dtime, nisurf, knon, snow, qsol, beta, capsol, dif_grnd)
523    
524     IF (soil_model) THEN
525 guez 14 CALL soil(dtime, nisurf, knon, snow, tsurf_new, tsoil, soilcap, soilflux)
526 guez 3 cal(1:knon) = RCPD / soilcap(1:knon)
527 guez 38 radsol(1:knon) = radsol(1:knon) + soilflux(1:knon)
528 guez 3 ELSE
529     dif_grnd = 1.0 / tau_gl
530     cal = RCPD * calice
531     WHERE (snow > 0.0) cal = RCPD * calsno
532     ENDIF
533     tsurf_temp = tsurf_new
534     beta = 1.0
535 guez 14
536 guez 3 ELSE
537 guez 38 ! ! lecture conditions limites
538 guez 3 CALL interfoce_lim(itime, dtime, jour, &
539 guez 38 klon, nisurf, knon, knindex, &
540     debut, &
541     tsurf_new, pctsrf_new)
542 guez 3
543     !IM cf LF
544     DO ii = 1, knon
545     tsurf_new(ii) = tsurf(ii)
546 guez 14 !IMbad IF (pctsrf_new(ii, nisurf) < EPSFRA) then
547     IF (pctsrf_new(knindex(ii), nisurf) < EPSFRA) then
548 guez 3 snow(ii) = 0.0
549 guez 38 !IM cf LF/JLD tsurf(ii) = RTT - 1.8
550 guez 3 tsurf_new(ii) = RTT - 1.8
551 guez 14 IF (soil_model) tsoil(ii, :) = RTT -1.8
552 guez 3 endif
553     enddo
554    
555     CALL calbeta(dtime, nisurf, knon, snow, qsol, beta, capsol, dif_grnd)
556    
557     IF (soil_model) THEN
558 guez 38 !IM cf LF/JLD CALL soil(dtime, nisurf, knon, snow, tsurf, tsoil, soilcap, soilflux)
559 guez 14 CALL soil(dtime, nisurf, knon, snow, tsurf_new, tsoil, soilcap, soilflux)
560 guez 3 cal(1:knon) = RCPD / soilcap(1:knon)
561 guez 38 radsol(1:knon) = radsol(1:knon) + soilflux(1:knon)
562 guez 3 dif_grnd = 0.
563     ELSE
564     dif_grnd = 1.0 / tau_gl
565     cal = RCPD * calice
566     WHERE (snow > 0.0) cal = RCPD * calsno
567     ENDIF
568     !IMbadtsurf_temp = tsurf
569     tsurf_temp = tsurf_new
570     beta = 1.0
571     ENDIF
572    
573     CALL calcul_fluxs( klon, knon, nisurf, dtime, &
574 guez 38 tsurf_temp, p1lay, cal, beta, tq_cdrag, ps, &
575     precip_rain, precip_snow, snow, qsurf, &
576     radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
577     petAcoef, peqAcoef, petBcoef, peqBcoef, &
578     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
579 guez 14
580 guez 3 !IM: flux entre l'ocean et la glace de mer pour le "slab" ocean
581     DO i = 1, knon
582     flux_g(i) = 0.0
583 guez 14
584 guez 3 !IM: faire dependre le coefficient de conduction de la glace de mer
585 guez 38 ! de l'epaisseur de la glace de mer, dans l'hypothese ou le coeff.
586     ! actuel correspond a 3m de glace de mer, cf. L.Li
587 guez 14
588 guez 38 ! IF(1.EQ.0) THEN
589     ! IF(siceh(i).GT.0.) THEN
590     ! new_dif_grnd(i) = dif_grnd(i)*3./siceh(i)
591     ! ELSE
592     ! new_dif_grnd(i) = 0.
593     ! ENDIF
594     ! ENDIF !(1.EQ.0) THEN
595 guez 14
596 guez 3 IF (cal(i).GT.1.0e-15) flux_g(i)=(tsurf_new(i)-t_grnd) &
597 guez 38 * dif_grnd(i) *RCPD/cal(i)
598     ! & * new_dif_grnd(i) *RCPD/cal(i)
599 guez 3 tmp_flux_g(knindex(i))=flux_g(i)
600     tmp_radsol(knindex(i))=radsol(i)
601     ENDDO
602    
603 guez 12 CALL fonte_neige( klon, knon, nisurf, dtime, &
604 guez 38 tsurf_temp, p1lay, cal, beta, tq_cdrag, ps, &
605     precip_rain, precip_snow, snow, qsol, &
606     radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
607     petAcoef, peqAcoef, petBcoef, peqBcoef, &
608     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l, &
609     fqcalving, ffonte, run_off_lic_0)
610 guez 3
611 guez 38 ! calcul albedo
612 guez 3
613 guez 38 CALL albsno(klon, knon, dtime, agesno, alb_neig, precip_snow)
614 guez 12 WHERE (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
615 guez 14 zfra(1:knon) = MAX(0.0, MIN(1.0, snow(1:knon)/(snow(1:knon)+10.0)))
616 guez 12 alb_new(1 : knon) = alb_neig(1 : knon) *zfra(1:knon) + &
617     0.6 * (1.0-zfra(1:knon))
618 guez 3
619 guez 38 fder_prev = fder
620 guez 3 fder = fder_prev + dflux_s + dflux_l
621    
622     iloc = maxloc(fder(1:klon))
623     if (check.and.fder(iloc(1))> 0.) then
624 guez 14 WRITE(*, *)'**** Debug fder ****'
625     WRITE(*, *)'max fder(', iloc(1), ') = ', fder(iloc(1))
626     WRITE(*, *)'fder_prev, dflux_s, dflux_l', fder_prev(iloc(1)), &
627 guez 38 dflux_s(iloc(1)), dflux_l(iloc(1))
628 guez 3 endif
629    
630 guez 14
631 guez 3 ! 2eme appel a interfoce pour le cumul et le passage des flux a l'ocean
632 guez 14
633 guez 3 z0_new = 0.002
634     z0_new = SQRT(z0_new**2+rugoro**2)
635     alblw(1:knon) = alb_new(1:knon)
636    
637     else if (nisurf == is_lic) then
638    
639 guez 14 if (check) write(*, *)'glacier, nisurf = ', nisurf
640 guez 3
641     if (.not. allocated(run_off_lic)) then
642     allocate(run_off_lic(knon), stat = error)
643     if (error /= 0) then
644     abort_message='Pb allocation run_off_lic'
645 guez 14 call abort_gcm(modname, abort_message, 1)
646 guez 3 endif
647     run_off_lic = 0.
648     endif
649 guez 14
650 guez 3 ! Surface "glacier continentaux" appel a l'interface avec le sol
651 guez 14
652 guez 3 IF (soil_model) THEN
653 guez 14 CALL soil(dtime, nisurf, knon, snow, tsurf, tsoil, soilcap, soilflux)
654 guez 3 cal(1:knon) = RCPD / soilcap(1:knon)
655 guez 38 radsol(1:knon) = radsol(1:knon) + soilflux(1:knon)
656 guez 3 ELSE
657     cal = RCPD * calice
658     WHERE (snow > 0.0) cal = RCPD * calsno
659     ENDIF
660     beta = 1.0
661     dif_grnd = 0.0
662    
663     call calcul_fluxs( klon, knon, nisurf, dtime, &
664 guez 38 tsurf, p1lay, cal, beta, tq_cdrag, ps, &
665     precip_rain, precip_snow, snow, qsurf, &
666     radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
667     petAcoef, peqAcoef, petBcoef, peqBcoef, &
668     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
669 guez 3
670     call fonte_neige( klon, knon, nisurf, dtime, &
671 guez 38 tsurf, p1lay, cal, beta, tq_cdrag, ps, &
672     precip_rain, precip_snow, snow, qsol, &
673     radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
674     petAcoef, peqAcoef, petBcoef, peqBcoef, &
675     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l, &
676     fqcalving, ffonte, run_off_lic_0)
677 guez 3
678     ! passage du run-off des glaciers calcule dans fonte_neige au coupleur
679     bidule=0.
680 guez 38 bidule(1:knon)= run_off_lic(1:knon)
681 guez 14 call gath2cpl(bidule, tmp_rlic, klon, knon, iim, jjm, knindex)
682    
683 guez 3 ! calcul albedo
684 guez 14
685 guez 38 CALL albsno(klon, knon, dtime, agesno, alb_neig, precip_snow)
686 guez 3 WHERE (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
687 guez 14 zfra(1:knon) = MAX(0.0, MIN(1.0, snow(1:knon)/(snow(1:knon)+10.0)))
688 guez 38 alb_new(1 : knon) = alb_neig(1 : knon)*zfra(1:knon) + &
689     0.6 * (1.0-zfra(1:knon))
690 guez 14
691 guez 3 !IM: plusieurs choix/tests sur l'albedo des "glaciers continentaux"
692 guez 38 ! alb_new(1 : knon) = 0.6 !IM cf FH/GK
693     ! alb_new(1 : knon) = 0.82
694     ! alb_new(1 : knon) = 0.77 !211003 Ksta0.77
695     ! alb_new(1 : knon) = 0.8 !KstaTER0.8 & LMD_ARMIP5
696     !IM: KstaTER0.77 & LMD_ARMIP6
697     alb_new(1 : knon) = 0.77
698 guez 3
699 guez 14
700 guez 3 ! Rugosite
701 guez 14
702 guez 3 z0_new = rugoro
703 guez 14
704 guez 3 ! Remplissage des pourcentages de surface
705    
706 guez 14 pctsrf_new(:, nisurf) = pctsrf(:, nisurf)
707    
708 guez 3 alblw(1:knon) = alb_new(1:knon)
709     else
710 guez 14 write(*, *)'Index surface = ', nisurf
711 guez 3 abort_message = 'Index surface non valable'
712 guez 14 call abort_gcm(modname, abort_message, 1)
713 guez 3 endif
714    
715     END SUBROUTINE interfsurf_hq
716    
717     !************************
718    
719 guez 38 SUBROUTINE interfoce_slab(klon, debut, itap, dtime, ijour, &
720     radsol, fluxo, fluxg, pctsrf, &
721     tslab, seaice, pctsrf_slab)
722 guez 14
723 guez 3 ! Cette routine calcule la temperature d'un slab ocean, la glace de mer
724     ! et les pourcentages de la maille couverte par l'ocean libre et/ou
725     ! la glace de mer pour un "slab" ocean de 50m
726 guez 14
727 guez 3 ! I. Musat 04.02.2005
728 guez 14
729 guez 3 ! input:
730 guez 38 ! klon nombre total de points de grille
731     ! debut logical: 1er appel a la physique
732     ! itap numero du pas de temps
733     ! dtime pas de temps de la physique (en s)
734     ! ijour jour dans l'annee en cours
735     ! radsol rayonnement net au sol (LW + SW)
736     ! fluxo flux turbulent (sensible + latent) sur les mailles oceaniques
737     ! fluxg flux de conduction entre la surface de la glace de mer et l'ocean
738     ! pctsrf tableau des pourcentages de surface de chaque maille
739 guez 3 ! output:
740 guez 38 ! tslab temperature de l'ocean libre
741     ! seaice glace de mer (kg/m2)
742     ! pctsrf_slab "pourcentages" (valeurs entre 0. et 1.) surfaces issus du slab
743 guez 14
744 guez 3 use indicesol
745     use clesphys
746     use abort_gcm_m, only: abort_gcm
747 guez 38 use SUPHEC_M
748 guez 3
749     ! Parametres d'entree
750     integer, intent(IN) :: klon
751     logical, intent(IN) :: debut
752     INTEGER, intent(IN) :: itap
753     REAL, intent(IN) :: dtime
754     INTEGER, intent(IN) :: ijour
755     REAL, dimension(klon), intent(IN) :: radsol
756     REAL, dimension(klon), intent(IN) :: fluxo
757     REAL, dimension(klon), intent(IN) :: fluxg
758     real, dimension(klon, nbsrf), intent(IN) :: pctsrf
759     ! Parametres de sortie
760     real, dimension(klon), intent(INOUT) :: tslab
761 guez 38 real, dimension(klon), intent(INOUT) :: seaice ! glace de mer (kg/m2)
762 guez 3 real, dimension(klon, nbsrf), intent(OUT) :: pctsrf_slab
763 guez 14
764 guez 3 ! Variables locales :
765     INTEGER, save :: lmt_pas, julien, idayvrai
766     REAL, parameter :: unjour=86400.
767     real, allocatable, dimension(:), save :: tmp_tslab, tmp_seaice
768     REAL, allocatable, dimension(:), save :: slab_bils
769     REAL, allocatable, dimension(:), save :: lmt_bils
770 guez 38 logical, save :: check = .false.
771 guez 14
772 guez 3 REAL, parameter :: cyang=50.0 * 4.228e+06 ! capacite calorifique volumetrique de l'eau J/(m2 K)
773 guez 38 REAL, parameter :: cbing=0.334e+05 ! J/kg
774     real, dimension(klon) :: siceh !hauteur de la glace de mer (m)
775 guez 3 INTEGER :: i
776     integer :: sum_error, error
777     REAL :: zz, za, zb
778 guez 14
779 guez 3 character (len = 80) :: abort_message
780     character (len = 20) :: modname = 'interfoce_slab'
781 guez 14
782     julien = MOD(ijour, 360)
783 guez 3 sum_error = 0
784     IF (debut) THEN
785     allocate(slab_bils(klon), stat = error); sum_error = sum_error + error
786     allocate(lmt_bils(klon), stat = error); sum_error = sum_error + error
787     allocate(tmp_tslab(klon), stat = error); sum_error = sum_error + error
788     allocate(tmp_seaice(klon), stat = error); sum_error = sum_error + error
789     if (sum_error /= 0) then
790 guez 14 abort_message='Pb allocation var. slab_bils, lmt_bils, tmp_tslab, tmp_seaice'
791     call abort_gcm(modname, abort_message, 1)
792 guez 3 endif
793     tmp_tslab=tslab
794     tmp_seaice=seaice
795     lmt_pas = nint(86400./dtime * 1.0) ! pour une lecture une fois par jour
796 guez 14
797 guez 3 IF (check) THEN
798 guez 14 PRINT*, 'interfoce_slab klon, debut, itap, dtime, ijour, &
799 guez 38 & lmt_pas ', klon, debut, itap, dtime, ijour, &
800     lmt_pas
801 guez 3 ENDIF !check
802 guez 14
803 guez 3 PRINT*, '************************'
804     PRINT*, 'SLAB OCEAN est actif, prenez precautions !'
805     PRINT*, '************************'
806 guez 14
807 guez 3 ! a mettre un slab_bils aussi en force !!!
808 guez 14
809 guez 3 DO i = 1, klon
810     slab_bils(i) = 0.0
811     ENDDO
812 guez 14
813 guez 3 ENDIF !debut
814 guez 14 pctsrf_slab(1:klon, 1:nbsrf) = pctsrf(1:klon, 1:nbsrf)
815    
816 guez 3 ! lecture du bilan au sol lmt_bils issu d'une simulation forcee en debut de journee
817 guez 14
818     IF (MOD(itap, lmt_pas) .EQ. 1) THEN !1er pas de temps de la journee
819 guez 3 idayvrai = ijour
820 guez 14 CALL condsurf(julien, idayvrai, lmt_bils)
821     ENDIF !(MOD(itap-1, lmt_pas) .EQ. 0) THEN
822 guez 3
823     DO i = 1, klon
824 guez 14 IF((pctsrf_slab(i, is_oce).GT.epsfra).OR. &
825 guez 38 (pctsrf_slab(i, is_sic).GT.epsfra)) THEN
826 guez 14
827 guez 3 ! fabriquer de la glace si congelation atteinte:
828 guez 14
829 guez 3 IF (tmp_tslab(i).LT.(RTT-1.8)) THEN
830 guez 38 zz = (RTT-1.8)-tmp_tslab(i)
831 guez 3 tmp_seaice(i) = tmp_seaice(i) + cyang/cbing * zz
832     seaice(i) = tmp_seaice(i)
833     tmp_tslab(i) = RTT-1.8
834     ENDIF
835 guez 14
836 guez 3 ! faire fondre de la glace si temperature est superieure a 0:
837 guez 14
838 guez 3 IF ((tmp_tslab(i).GT.RTT) .AND. (tmp_seaice(i).GT.0.0)) THEN
839     zz = cyang/cbing * (tmp_tslab(i)-RTT)
840 guez 14 zz = MIN(zz, tmp_seaice(i))
841 guez 3 tmp_seaice(i) = tmp_seaice(i) - zz
842     seaice(i) = tmp_seaice(i)
843     tmp_tslab(i) = tmp_tslab(i) - zz*cbing/cyang
844     ENDIF
845 guez 14
846 guez 3 ! limiter la glace de mer a 10 metres (10000 kg/m2)
847 guez 14
848 guez 3 IF(tmp_seaice(i).GT.45.) THEN
849 guez 14 tmp_seaice(i) = MIN(tmp_seaice(i), 10000.0)
850 guez 3 ELSE
851     tmp_seaice(i) = 0.
852     ENDIF
853     seaice(i) = tmp_seaice(i)
854     siceh(i)=tmp_seaice(i)/1000. !en metres
855 guez 14
856 guez 3 ! determiner la nature du sol (glace de mer ou ocean libre):
857 guez 14
858     ! on fait dependre la fraction de seaice "pctsrf(i, is_sic)"
859 guez 3 ! de l'epaisseur de seaice :
860 guez 14 ! pctsrf(i, is_sic)=1. si l'epaisseur de la glace de mer est >= a 20cm
861     ! et pctsrf(i, is_sic) croit lineairement avec seaice de 0. a 20cm d'epaisseur
862    
863     pctsrf_slab(i, is_sic)=MIN(siceh(i)/0.20, &
864 guez 38 1.-(pctsrf_slab(i, is_ter)+pctsrf_slab(i, is_lic)))
865 guez 14 pctsrf_slab(i, is_oce)=1.0 - &
866 guez 38 (pctsrf_slab(i, is_ter)+pctsrf_slab(i, is_lic)+pctsrf_slab(i, is_sic))
867 guez 3 ENDIF !pctsrf
868     ENDDO
869 guez 14
870 guez 3 ! Calculer le bilan du flux de chaleur au sol :
871 guez 14
872 guez 3 DO i = 1, klon
873     za = radsol(i) + fluxo(i)
874     zb = fluxg(i)
875 guez 14 IF((pctsrf_slab(i, is_oce).GT.epsfra).OR. &
876 guez 38 (pctsrf_slab(i, is_sic).GT.epsfra)) THEN
877 guez 14 slab_bils(i)=slab_bils(i)+(za*pctsrf_slab(i, is_oce) &
878 guez 38 +zb*pctsrf_slab(i, is_sic))/ FLOAT(lmt_pas)
879 guez 3 ENDIF
880     ENDDO !klon
881 guez 14
882 guez 3 ! calcul tslab
883 guez 14
884     IF (MOD(itap, lmt_pas).EQ.0) THEN !fin de journee
885 guez 3 DO i = 1, klon
886 guez 14 IF ((pctsrf_slab(i, is_oce).GT.epsfra).OR. &
887 guez 38 (pctsrf_slab(i, is_sic).GT.epsfra)) THEN
888 guez 3 tmp_tslab(i) = tmp_tslab(i) + &
889 guez 38 (slab_bils(i)-lmt_bils(i)) &
890     /cyang*unjour
891 guez 3 ! on remet l'accumulation a 0
892     slab_bils(i) = 0.
893     ENDIF !pctsrf
894     ENDDO !klon
895 guez 14 ENDIF !(MOD(itap, lmt_pas).EQ.0) THEN
896    
897 guez 3 tslab = tmp_tslab
898     seaice = tmp_seaice
899     END SUBROUTINE interfoce_slab
900    
901     !************************
902    
903 guez 38 SUBROUTINE interfoce_lim(itime, dtime, jour, &
904     klon, nisurf, knon, knindex, &
905     debut, &
906     lmt_sst, pctsrf_new)
907 guez 3
908 guez 14 ! Cette routine sert d'interface entre le modele atmospherique et
909     ! un fichier de conditions aux limites
910    
911 guez 3 ! L. Fairhead 02/2000
912    
913     use abort_gcm_m, only: abort_gcm
914     use indicesol
915    
916 guez 14 integer, intent(IN) :: itime ! numero du pas de temps courant
917 guez 38 real , intent(IN) :: dtime ! pas de temps de la physique (en s)
918 guez 14 integer, intent(IN) :: jour ! jour a lire dans l'annee
919     integer, intent(IN) :: nisurf ! index de la surface a traiter (1 = sol continental)
920     integer, intent(IN) :: knon ! nombre de points dans le domaine a traiter
921     integer, intent(IN) :: klon ! taille de la grille
922     integer, dimension(klon), intent(in) :: knindex ! index des points de la surface a traiter
923     logical, intent(IN) :: debut ! logical: 1er appel a la physique (initialisation)
924 guez 3
925     ! Parametres de sortie
926 guez 14 ! output:
927 guez 38 ! lmt_sst SST lues dans le fichier de CL
928     ! pctsrf_new sous-maille fractionnelle
929 guez 3 real, intent(out), dimension(klon) :: lmt_sst
930 guez 14 real, intent(out), dimension(klon, nbsrf) :: pctsrf_new
931 guez 3
932     ! Variables locales
933 guez 38 integer :: ii
934     INTEGER, save :: lmt_pas ! frequence de lecture des conditions limites
935 guez 3 ! (en pas de physique)
936 guez 38 logical, save :: deja_lu ! pour indiquer que le jour a lire a deja
937 guez 3 ! lu pour une surface precedente
938 guez 14 integer, save :: jour_lu
939 guez 38 integer :: ierr
940 guez 3 character (len = 20) :: modname = 'interfoce_lim'
941     character (len = 80) :: abort_message
942 guez 38 logical, save :: newlmt = .TRUE.
943     logical, save :: check = .FALSE.
944 guez 3 ! Champs lus dans le fichier de CL
945     real, allocatable , save, dimension(:) :: sst_lu, rug_lu, nat_lu
946 guez 14 real, allocatable , save, dimension(:, :) :: pct_tmp
947    
948 guez 3 ! quelques variables pour netcdf
949 guez 14
950 guez 3 include "netcdf.inc"
951 guez 38 integer :: nid, nvarid
952 guez 3 integer, dimension(2) :: start, epais
953    
954 guez 14 ! --------------------------------------------------
955    
956 guez 3 if (debut .and. .not. allocated(sst_lu)) then
957     lmt_pas = nint(86400./dtime * 1.0) ! pour une lecture une fois par jour
958     jour_lu = jour - 1
959     allocate(sst_lu(klon))
960     allocate(nat_lu(klon))
961 guez 14 allocate(pct_tmp(klon, nbsrf))
962 guez 3 endif
963    
964     if ((jour - jour_lu) /= 0) deja_lu = .false.
965    
966 guez 14 if (check) write(*, *)modname, ' :: jour, jour_lu, deja_lu', jour, jour_lu, &
967 guez 3 deja_lu
968 guez 14 if (check) write(*, *)modname, ' :: itime, lmt_pas ', itime, lmt_pas, dtime
969 guez 3
970     ! Tester d'abord si c'est le moment de lire le fichier
971     if (mod(itime-1, lmt_pas) == 0 .and. .not. deja_lu) then
972 guez 14
973 guez 3 ! Ouverture du fichier
974 guez 14
975     ierr = NF_OPEN ('limit.nc', NF_NOWRITE, nid)
976 guez 3 if (ierr.NE.NF_NOERR) then
977     abort_message &
978     = 'Pb d''ouverture du fichier de conditions aux limites'
979 guez 14 call abort_gcm(modname, abort_message, 1)
980 guez 3 endif
981 guez 14
982 guez 3 ! La tranche de donnees a lire:
983 guez 14
984 guez 3 start(1) = 1
985     start(2) = jour
986     epais(1) = klon
987     epais(2) = 1
988 guez 14
989 guez 3 if (newlmt) then
990 guez 14
991 guez 3 ! Fraction "ocean"
992 guez 14
993 guez 3 ierr = NF_INQ_VARID(nid, 'FOCE', nvarid)
994     if (ierr /= NF_NOERR) then
995     abort_message = 'Le champ <FOCE> est absent'
996 guez 14 call abort_gcm(modname, abort_message, 1)
997 guez 3 endif
998 guez 14 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, pct_tmp(1, is_oce))
999 guez 3 if (ierr /= NF_NOERR) then
1000     abort_message = 'Lecture echouee pour <FOCE>'
1001 guez 14 call abort_gcm(modname, abort_message, 1)
1002 guez 3 endif
1003 guez 14
1004 guez 3 ! Fraction "glace de mer"
1005 guez 14
1006 guez 3 ierr = NF_INQ_VARID(nid, 'FSIC', nvarid)
1007     if (ierr /= NF_NOERR) then
1008     abort_message = 'Le champ <FSIC> est absent'
1009 guez 14 call abort_gcm(modname, abort_message, 1)
1010 guez 3 endif
1011 guez 14 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, pct_tmp(1, is_sic))
1012 guez 3 if (ierr /= NF_NOERR) then
1013     abort_message = 'Lecture echouee pour <FSIC>'
1014 guez 14 call abort_gcm(modname, abort_message, 1)
1015 guez 3 endif
1016 guez 14
1017 guez 3 ! Fraction "terre"
1018 guez 14
1019 guez 3 ierr = NF_INQ_VARID(nid, 'FTER', nvarid)
1020     if (ierr /= NF_NOERR) then
1021     abort_message = 'Le champ <FTER> est absent'
1022 guez 14 call abort_gcm(modname, abort_message, 1)
1023 guez 3 endif
1024 guez 14 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, pct_tmp(1, is_ter))
1025 guez 3 if (ierr /= NF_NOERR) then
1026     abort_message = 'Lecture echouee pour <FTER>'
1027 guez 14 call abort_gcm(modname, abort_message, 1)
1028 guez 3 endif
1029 guez 14
1030 guez 3 ! Fraction "glacier terre"
1031 guez 14
1032 guez 3 ierr = NF_INQ_VARID(nid, 'FLIC', nvarid)
1033     if (ierr /= NF_NOERR) then
1034     abort_message = 'Le champ <FLIC> est absent'
1035 guez 14 call abort_gcm(modname, abort_message, 1)
1036 guez 3 endif
1037 guez 14 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, pct_tmp(1, is_lic))
1038 guez 3 if (ierr /= NF_NOERR) then
1039     abort_message = 'Lecture echouee pour <FLIC>'
1040 guez 14 call abort_gcm(modname, abort_message, 1)
1041 guez 3 endif
1042 guez 14
1043 guez 38 else ! on en est toujours a rnatur
1044 guez 14
1045 guez 3 ierr = NF_INQ_VARID(nid, 'NAT', nvarid)
1046     if (ierr /= NF_NOERR) then
1047     abort_message = 'Le champ <NAT> est absent'
1048 guez 14 call abort_gcm(modname, abort_message, 1)
1049 guez 3 endif
1050 guez 14 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, nat_lu)
1051 guez 3 if (ierr /= NF_NOERR) then
1052     abort_message = 'Lecture echouee pour <NAT>'
1053 guez 14 call abort_gcm(modname, abort_message, 1)
1054 guez 3 endif
1055 guez 14
1056 guez 3 ! Remplissage des fractions de surface
1057     ! nat = 0, 1, 2, 3 pour ocean, terre, glacier, seaice
1058 guez 14
1059 guez 3 pct_tmp = 0.0
1060     do ii = 1, klon
1061 guez 14 pct_tmp(ii, nint(nat_lu(ii)) + 1) = 1.
1062 guez 3 enddo
1063    
1064 guez 14
1065 guez 38 ! On se retrouve avec ocean en 1 et terre en 2 alors qu'on veut le contraire
1066 guez 14
1067 guez 3 pctsrf_new = pct_tmp
1068 guez 14 pctsrf_new (:, 2)= pct_tmp (:, 1)
1069     pctsrf_new (:, 1)= pct_tmp (:, 2)
1070 guez 3 pct_tmp = pctsrf_new
1071     endif ! fin test sur newlmt
1072 guez 14
1073 guez 3 ! Lecture SST
1074 guez 14
1075 guez 3 ierr = NF_INQ_VARID(nid, 'SST', nvarid)
1076     if (ierr /= NF_NOERR) then
1077     abort_message = 'Le champ <SST> est absent'
1078 guez 14 call abort_gcm(modname, abort_message, 1)
1079 guez 3 endif
1080 guez 14 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, sst_lu)
1081 guez 3 if (ierr /= NF_NOERR) then
1082     abort_message = 'Lecture echouee pour <SST>'
1083 guez 14 call abort_gcm(modname, abort_message, 1)
1084 guez 3 endif
1085    
1086 guez 14
1087 guez 3 ! Fin de lecture
1088 guez 14
1089 guez 3 ierr = NF_CLOSE(nid)
1090     deja_lu = .true.
1091     jour_lu = jour
1092     endif
1093 guez 14
1094 guez 3 ! Recopie des variables dans les champs de sortie
1095 guez 14
1096 guez 3 lmt_sst = 999999999.
1097     do ii = 1, knon
1098     lmt_sst(ii) = sst_lu(knindex(ii))
1099     enddo
1100    
1101 guez 14 pctsrf_new(:, is_oce) = pct_tmp(:, is_oce)
1102     pctsrf_new(:, is_sic) = pct_tmp(:, is_sic)
1103 guez 3
1104     END SUBROUTINE interfoce_lim
1105    
1106     !************************
1107    
1108 guez 38 SUBROUTINE interfsur_lim(itime, dtime, jour, &
1109     klon, nisurf, knon, knindex, &
1110     debut, &
1111     lmt_alb, lmt_rug)
1112 guez 3
1113     ! Cette routine sert d'interface entre le modèle atmosphérique et
1114     ! un fichier de conditions aux limites.
1115 guez 14
1116 guez 3 ! L. Fairhead 02/2000
1117 guez 14
1118     use abort_gcm_m, only: abort_gcm
1119    
1120     ! Parametres d'entree
1121 guez 3 ! input:
1122 guez 38 ! itime numero du pas de temps courant
1123     ! dtime pas de temps de la physique (en s)
1124     ! jour jour a lire dans l'annee
1125     ! nisurf index de la surface a traiter (1 = sol continental)
1126     ! knon nombre de points dans le domaine a traiter
1127     ! knindex index des points de la surface a traiter
1128     ! klon taille de la grille
1129     ! debut logical: 1er appel a la physique (initialisation)
1130 guez 3 integer, intent(IN) :: itime
1131 guez 38 real , intent(IN) :: dtime
1132 guez 3 integer, intent(IN) :: jour
1133     integer, intent(IN) :: nisurf
1134     integer, intent(IN) :: knon
1135     integer, intent(IN) :: klon
1136     integer, dimension(klon), intent(in) :: knindex
1137     logical, intent(IN) :: debut
1138    
1139     ! Parametres de sortie
1140 guez 14 ! output:
1141 guez 38 ! lmt_sst SST lues dans le fichier de CL
1142     ! lmt_alb Albedo lu
1143     ! lmt_rug longueur de rugosité lue
1144     ! pctsrf_new sous-maille fractionnelle
1145 guez 3 real, intent(out), dimension(klon) :: lmt_alb
1146     real, intent(out), dimension(klon) :: lmt_rug
1147    
1148     ! Variables locales
1149 guez 38 integer :: ii
1150     integer, save :: lmt_pas ! frequence de lecture des conditions limites
1151 guez 3 ! (en pas de physique)
1152 guez 14 logical, save :: deja_lu_sur! pour indiquer que le jour a lire a deja
1153 guez 3 ! lu pour une surface precedente
1154 guez 14 integer, save :: jour_lu_sur
1155 guez 38 integer :: ierr
1156 guez 3 character (len = 20) :: modname = 'interfsur_lim'
1157     character (len = 80) :: abort_message
1158 guez 38 logical, save :: newlmt = .false.
1159     logical, save :: check = .false.
1160 guez 3 ! Champs lus dans le fichier de CL
1161     real, allocatable , save, dimension(:) :: alb_lu, rug_lu
1162 guez 14
1163 guez 3 ! quelques variables pour netcdf
1164 guez 14
1165 guez 3 include "netcdf.inc"
1166 guez 38 integer , save :: nid, nvarid
1167 guez 14 integer, dimension(2), save :: start, epais
1168 guez 3
1169 guez 14 !------------------------------------------------------------
1170    
1171 guez 3 if (debut) then
1172     lmt_pas = nint(86400./dtime * 1.0) ! pour une lecture une fois par jour
1173     jour_lu_sur = jour - 1
1174     allocate(alb_lu(klon))
1175     allocate(rug_lu(klon))
1176     endif
1177    
1178     if ((jour - jour_lu_sur) /= 0) deja_lu_sur = .false.
1179    
1180 guez 14 if (check) write(*, *)modname, ':: jour_lu_sur, deja_lu_sur', jour_lu_sur, &
1181 guez 3 deja_lu_sur
1182 guez 14 if (check) write(*, *)modname, ':: itime, lmt_pas', itime, lmt_pas
1183 guez 3
1184     ! Tester d'abord si c'est le moment de lire le fichier
1185     if (mod(itime-1, lmt_pas) == 0 .and. .not. deja_lu_sur) then
1186 guez 38
1187 guez 3 ! Ouverture du fichier
1188 guez 38
1189 guez 14 ierr = NF_OPEN ('limit.nc', NF_NOWRITE, nid)
1190 guez 3 if (ierr.NE.NF_NOERR) then
1191     abort_message &
1192     = 'Pb d''ouverture du fichier de conditions aux limites'
1193 guez 14 call abort_gcm(modname, abort_message, 1)
1194 guez 3 endif
1195 guez 14
1196 guez 3 ! La tranche de donnees a lire:
1197    
1198     start(1) = 1
1199     start(2) = jour
1200     epais(1) = klon
1201     epais(2) = 1
1202 guez 38
1203 guez 3 ! Lecture Albedo
1204 guez 38
1205 guez 3 ierr = NF_INQ_VARID(nid, 'ALB', nvarid)
1206     if (ierr /= NF_NOERR) then
1207     abort_message = 'Le champ <ALB> est absent'
1208 guez 14 call abort_gcm(modname, abort_message, 1)
1209 guez 3 endif
1210 guez 14 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, alb_lu)
1211 guez 3 if (ierr /= NF_NOERR) then
1212     abort_message = 'Lecture echouee pour <ALB>'
1213 guez 14 call abort_gcm(modname, abort_message, 1)
1214 guez 3 endif
1215 guez 38
1216 guez 3 ! Lecture rugosité
1217 guez 38
1218 guez 3 ierr = NF_INQ_VARID(nid, 'RUG', nvarid)
1219     if (ierr /= NF_NOERR) then
1220     abort_message = 'Le champ <RUG> est absent'
1221 guez 14 call abort_gcm(modname, abort_message, 1)
1222 guez 3 endif
1223 guez 14 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, rug_lu)
1224 guez 3 if (ierr /= NF_NOERR) then
1225     abort_message = 'Lecture echouee pour <RUG>'
1226 guez 14 call abort_gcm(modname, abort_message, 1)
1227 guez 3 endif
1228    
1229 guez 38
1230 guez 3 ! Fin de lecture
1231 guez 38
1232 guez 3 ierr = NF_CLOSE(nid)
1233     deja_lu_sur = .true.
1234     jour_lu_sur = jour
1235     endif
1236 guez 14
1237 guez 3 ! Recopie des variables dans les champs de sortie
1238 guez 14
1239 guez 38 !!$ lmt_alb = 0.0
1240     !!$ lmt_rug = 0.0
1241 guez 14 lmt_alb = 999999.
1242     lmt_rug = 999999.
1243 guez 3 DO ii = 1, knon
1244     lmt_alb(ii) = alb_lu(knindex(ii))
1245     lmt_rug(ii) = rug_lu(knindex(ii))
1246     enddo
1247    
1248     END SUBROUTINE interfsur_lim
1249    
1250     !************************
1251    
1252 guez 38 SUBROUTINE calcul_fluxs( klon, knon, nisurf, dtime, &
1253     tsurf, p1lay, cal, beta, coef1lay, ps, &
1254     precip_rain, precip_snow, snow, qsurf, &
1255     radsol, dif_grnd, t1lay, q1lay, u1lay, v1lay, &
1256     petAcoef, peqAcoef, petBcoef, peqBcoef, &
1257     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
1258 guez 3
1259     ! Cette routine calcule les fluxs en h et q a l'interface et eventuellement
1260     ! une temperature de surface (au cas ou ok_veget = false)
1261 guez 14
1262 guez 3 ! L. Fairhead 4/2000
1263 guez 14
1264 guez 3 ! input:
1265 guez 38 ! knon nombre de points a traiter
1266     ! nisurf surface a traiter
1267     ! tsurf temperature de surface
1268     ! p1lay pression 1er niveau (milieu de couche)
1269     ! cal capacite calorifique du sol
1270     ! beta evap reelle
1271     ! coef1lay coefficient d'echange
1272     ! ps pression au sol
1273     ! precip_rain precipitations liquides
1274     ! precip_snow precipitations solides
1275     ! snow champs hauteur de neige
1276     ! runoff runoff en cas de trop plein
1277     ! petAcoef coeff. A de la resolution de la CL pour t
1278     ! peqAcoef coeff. A de la resolution de la CL pour q
1279     ! petBcoef coeff. B de la resolution de la CL pour t
1280     ! peqBcoef coeff. B de la resolution de la CL pour q
1281     ! radsol rayonnement net aus sol (LW + SW)
1282     ! dif_grnd coeff. diffusion vers le sol profond
1283 guez 14
1284 guez 3 ! output:
1285 guez 38 ! tsurf_new temperature au sol
1286     ! qsurf humidite de l'air au dessus du sol
1287     ! fluxsens flux de chaleur sensible
1288     ! fluxlat flux de chaleur latente
1289     ! dflux_s derivee du flux de chaleur sensible / Ts
1290     ! dflux_l derivee du flux de chaleur latente / Ts
1291 guez 3
1292 guez 14
1293 guez 3 use indicesol
1294     use abort_gcm_m, only: abort_gcm
1295 guez 38 use yoethf_m
1296 guez 3 use fcttre, only: thermcep, foeew, qsats, qsatl, foede, dqsats, dqsatl
1297 guez 38 use SUPHEC_M
1298 guez 3
1299     ! Parametres d'entree
1300     integer, intent(IN) :: knon, nisurf, klon
1301 guez 38 real , intent(IN) :: dtime
1302 guez 3 real, dimension(klon), intent(IN) :: petAcoef, peqAcoef
1303     real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
1304     real, dimension(klon), intent(IN) :: ps, q1lay
1305     real, dimension(klon), intent(IN) :: tsurf, p1lay, cal, beta, coef1lay
1306     real, dimension(klon), intent(IN) :: precip_rain, precip_snow
1307     real, dimension(klon), intent(IN) :: radsol, dif_grnd
1308     real, dimension(klon), intent(IN) :: t1lay, u1lay, v1lay
1309     real, dimension(klon), intent(INOUT) :: snow, qsurf
1310    
1311     ! Parametres sorties
1312     real, dimension(klon), intent(OUT):: tsurf_new, evap, fluxsens, fluxlat
1313     real, dimension(klon), intent(OUT):: dflux_s, dflux_l
1314    
1315     ! Variables locales
1316     integer :: i
1317     real, dimension(klon) :: zx_mh, zx_nh, zx_oh
1318     real, dimension(klon) :: zx_mq, zx_nq, zx_oq
1319     real, dimension(klon) :: zx_pkh, zx_dq_s_dt, zx_qsat, zx_coef
1320     real, dimension(klon) :: zx_sl, zx_k1
1321     real, dimension(klon) :: zx_q_0 , d_ts
1322 guez 38 real :: zdelta, zcvm5, zx_qs, zcor, zx_dq_s_dh
1323     real :: bilan_f, fq_fonte
1324     REAL :: subli, fsno
1325     REAL :: qsat_new, q1_new
1326 guez 3 real, parameter :: t_grnd = 271.35, t_coup = 273.15
1327     !! PB temporaire en attendant mieux pour le modele de neige
1328     REAL, parameter :: chasno = 3.334E+05/(2.3867E+06*0.15)
1329 guez 14
1330 guez 38 logical, save :: check = .false.
1331     character (len = 20) :: modname = 'calcul_fluxs'
1332     logical, save :: fonte_neige = .false.
1333     real, save :: max_eau_sol = 150.0
1334 guez 3 character (len = 80) :: abort_message
1335 guez 38 logical, save :: first = .true., second=.false.
1336 guez 3
1337 guez 14 if (check) write(*, *)'Entree ', modname, ' surface = ', nisurf
1338 guez 3
1339     IF (check) THEN
1340 guez 14 WRITE(*, *)' radsol (min, max)' &
1341 guez 38 , MINVAL(radsol(1:knon)), MAXVAL(radsol(1:knon))
1342 guez 3 !!CALL flush(6)
1343     ENDIF
1344    
1345     if (size(coastalflow) /= knon .AND. nisurf == is_ter) then
1346 guez 14 write(*, *)'Bizarre, le nombre de points continentaux'
1347     write(*, *)'a change entre deux appels. J''arrete ...'
1348 guez 3 abort_message='Pb run_off'
1349 guez 14 call abort_gcm(modname, abort_message, 1)
1350 guez 3 endif
1351 guez 14
1352 guez 3 ! Traitement neige et humidite du sol
1353 guez 14
1354 guez 3 ! Initialisation
1355 guez 14
1356 guez 3 evap = 0.
1357     fluxsens=0.
1358     fluxlat=0.
1359     dflux_s = 0.
1360     dflux_l = 0.
1361 guez 14
1362 guez 3 ! zx_qs = qsat en kg/kg
1363 guez 14
1364 guez 3 DO i = 1, knon
1365     zx_pkh(i) = (ps(i)/ps(i))**RKAPPA
1366     IF (thermcep) THEN
1367 guez 14 zdelta=MAX(0., SIGN(1., rtt-tsurf(i)))
1368 guez 3 zcvm5 = R5LES*RLVTT*(1.-zdelta) + R5IES*RLSTT*zdelta
1369     zcvm5 = zcvm5 / RCPD / (1.0+RVTMP2*q1lay(i))
1370 guez 14 zx_qs= r2es * FOEEW(tsurf(i), zdelta)/ps(i)
1371     zx_qs=MIN(0.5, zx_qs)
1372 guez 3 zcor=1./(1.-retv*zx_qs)
1373     zx_qs=zx_qs*zcor
1374 guez 14 zx_dq_s_dh = FOEDE(tsurf(i), zdelta, zcvm5, zx_qs, zcor) &
1375 guez 38 /RLVTT / zx_pkh(i)
1376 guez 3 ELSE
1377     IF (tsurf(i).LT.t_coup) THEN
1378     zx_qs = qsats(tsurf(i)) / ps(i)
1379 guez 14 zx_dq_s_dh = dqsats(tsurf(i), zx_qs)/RLVTT &
1380 guez 38 / zx_pkh(i)
1381 guez 3 ELSE
1382     zx_qs = qsatl(tsurf(i)) / ps(i)
1383 guez 14 zx_dq_s_dh = dqsatl(tsurf(i), zx_qs)/RLVTT &
1384 guez 38 / zx_pkh(i)
1385 guez 3 ENDIF
1386     ENDIF
1387     zx_dq_s_dt(i) = RCPD * zx_pkh(i) * zx_dq_s_dh
1388     zx_qsat(i) = zx_qs
1389     zx_coef(i) = coef1lay(i) &
1390 guez 38 * (1.0+SQRT(u1lay(i)**2+v1lay(i)**2)) &
1391     * p1lay(i)/(RD*t1lay(i))
1392 guez 3
1393     ENDDO
1394    
1395     ! === Calcul de la temperature de surface ===
1396 guez 14
1397 guez 3 ! zx_sl = chaleur latente d'evaporation ou de sublimation
1398 guez 14
1399 guez 3 do i = 1, knon
1400     zx_sl(i) = RLVTT
1401     if (tsurf(i) .LT. RTT) zx_sl(i) = RLSTT
1402     zx_k1(i) = zx_coef(i)
1403     enddo
1404    
1405     do i = 1, knon
1406     ! Q
1407     zx_oq(i) = 1. - (beta(i) * zx_k1(i) * peqBcoef(i) * dtime)
1408     zx_mq(i) = beta(i) * zx_k1(i) * &
1409 guez 38 (peqAcoef(i) - zx_qsat(i) &
1410     + zx_dq_s_dt(i) * tsurf(i)) &
1411     / zx_oq(i)
1412 guez 3 zx_nq(i) = beta(i) * zx_k1(i) * (-1. * zx_dq_s_dt(i)) &
1413 guez 38 / zx_oq(i)
1414 guez 3
1415     ! H
1416     zx_oh(i) = 1. - (zx_k1(i) * petBcoef(i) * dtime)
1417     zx_mh(i) = zx_k1(i) * petAcoef(i) / zx_oh(i)
1418     zx_nh(i) = - (zx_k1(i) * RCPD * zx_pkh(i))/ zx_oh(i)
1419    
1420     ! Tsurface
1421     tsurf_new(i) = (tsurf(i) + cal(i)/(RCPD * zx_pkh(i)) * dtime * &
1422 guez 38 (radsol(i) + zx_mh(i) + zx_sl(i) * zx_mq(i)) &
1423     + dif_grnd(i) * t_grnd * dtime)/ &
1424     ( 1. - dtime * cal(i)/(RCPD * zx_pkh(i)) * ( &
1425     zx_nh(i) + zx_sl(i) * zx_nq(i)) &
1426     + dtime * dif_grnd(i))
1427 guez 3
1428 guez 14
1429 guez 3 ! Y'a-t-il fonte de neige?
1430 guez 14
1431 guez 38 ! fonte_neige = (nisurf /= is_oce) .AND. &
1432     ! & (snow(i) > epsfra .OR. nisurf == is_sic .OR. nisurf == is_lic) &
1433     ! & .AND. (tsurf_new(i) >= RTT)
1434     ! if (fonte_neige) tsurf_new(i) = RTT
1435 guez 3 d_ts(i) = tsurf_new(i) - tsurf(i)
1436 guez 38 ! zx_h_ts(i) = tsurf_new(i) * RCPD * zx_pkh(i)
1437     ! zx_q_0(i) = zx_qsat(i) + zx_dq_s_dt(i) * d_ts(i)
1438     !== flux_q est le flux de vapeur d'eau: kg/(m**2 s) positive vers bas
1439 guez 3 !== flux_t est le flux de cpt (energie sensible): j/(m**2 s)
1440     evap(i) = - zx_mq(i) - zx_nq(i) * tsurf_new(i)
1441     fluxlat(i) = - evap(i) * zx_sl(i)
1442     fluxsens(i) = zx_mh(i) + zx_nh(i) * tsurf_new(i)
1443     ! Derives des flux dF/dTs (W m-2 K-1):
1444     dflux_s(i) = zx_nh(i)
1445     dflux_l(i) = (zx_sl(i) * zx_nq(i))
1446     ! Nouvelle valeure de l'humidite au dessus du sol
1447     qsat_new=zx_qsat(i) + zx_dq_s_dt(i) * d_ts(i)
1448     q1_new = peqAcoef(i) - peqBcoef(i)*evap(i)*dtime
1449     qsurf(i)=q1_new*(1.-beta(i)) + beta(i)*qsat_new
1450     ENDDO
1451    
1452     END SUBROUTINE calcul_fluxs
1453    
1454     !************************
1455    
1456 guez 38 SUBROUTINE fonte_neige( klon, knon, nisurf, dtime, &
1457     tsurf, p1lay, cal, beta, coef1lay, ps, &
1458     precip_rain, precip_snow, snow, qsol, &
1459     radsol, dif_grnd, t1lay, q1lay, u1lay, v1lay, &
1460     petAcoef, peqAcoef, petBcoef, peqBcoef, &
1461     tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l, &
1462     fqcalving, ffonte, run_off_lic_0)
1463 guez 3
1464     ! Routine de traitement de la fonte de la neige dans le cas du traitement
1465     ! de sol simplifié
1466 guez 14
1467 guez 3 ! LF 03/2001
1468     ! input:
1469 guez 38 ! knon nombre de points a traiter
1470     ! nisurf surface a traiter
1471     ! tsurf temperature de surface
1472     ! p1lay pression 1er niveau (milieu de couche)
1473     ! cal capacite calorifique du sol
1474     ! beta evap reelle
1475     ! coef1lay coefficient d'echange
1476     ! ps pression au sol
1477     ! precip_rain precipitations liquides
1478     ! precip_snow precipitations solides
1479     ! snow champs hauteur de neige
1480     ! qsol hauteur d'eau contenu dans le sol
1481     ! runoff runoff en cas de trop plein
1482     ! petAcoef coeff. A de la resolution de la CL pour t
1483     ! peqAcoef coeff. A de la resolution de la CL pour q
1484     ! petBcoef coeff. B de la resolution de la CL pour t
1485     ! peqBcoef coeff. B de la resolution de la CL pour q
1486     ! radsol rayonnement net aus sol (LW + SW)
1487     ! dif_grnd coeff. diffusion vers le sol profond
1488 guez 14
1489 guez 3 ! output:
1490 guez 38 ! tsurf_new temperature au sol
1491     ! fluxsens flux de chaleur sensible
1492     ! fluxlat flux de chaleur latente
1493     ! dflux_s derivee du flux de chaleur sensible / Ts
1494     ! dflux_l derivee du flux de chaleur latente / Ts
1495 guez 3 ! in/out:
1496 guez 38 ! run_off_lic_0 run off glacier du pas de temps précedent
1497 guez 3
1498 guez 14
1499 guez 3 use indicesol
1500 guez 38 use SUPHEC_M
1501     use yoethf_m
1502 guez 3 use fcttre
1503     !IM cf JLD
1504    
1505     ! Parametres d'entree
1506     integer, intent(IN) :: knon, nisurf, klon
1507 guez 38 real , intent(IN) :: dtime
1508 guez 3 real, dimension(klon), intent(IN) :: petAcoef, peqAcoef
1509     real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
1510     real, dimension(klon), intent(IN) :: ps, q1lay
1511     real, dimension(klon), intent(IN) :: tsurf, p1lay, cal, beta, coef1lay
1512     real, dimension(klon), intent(IN) :: precip_rain, precip_snow
1513     real, dimension(klon), intent(IN) :: radsol, dif_grnd
1514     real, dimension(klon), intent(IN) :: t1lay, u1lay, v1lay
1515     real, dimension(klon), intent(INOUT) :: snow, qsol
1516    
1517     ! Parametres sorties
1518     real, dimension(klon), intent(INOUT):: tsurf_new, evap, fluxsens, fluxlat
1519     real, dimension(klon), intent(INOUT):: dflux_s, dflux_l
1520     ! Flux thermique utiliser pour fondre la neige
1521     real, dimension(klon), intent(INOUT):: ffonte
1522     ! Flux d'eau "perdue" par la surface et necessaire pour que limiter la
1523     ! hauteur de neige, en kg/m2/s
1524     real, dimension(klon), intent(INOUT):: fqcalving
1525     real, dimension(klon), intent(INOUT):: run_off_lic_0
1526     ! Variables locales
1527     ! Masse maximum de neige (kg/m2). Au dessus de ce seuil, la neige
1528     ! en exces "s'ecoule" (calving)
1529 guez 38 ! real, parameter :: snow_max=1.
1530 guez 3 !IM cf JLD/GK
1531     real, parameter :: snow_max=3000.
1532     integer :: i
1533     real, dimension(klon) :: zx_mh, zx_nh, zx_oh
1534     real, dimension(klon) :: zx_mq, zx_nq, zx_oq
1535     real, dimension(klon) :: zx_pkh, zx_dq_s_dt, zx_qsat, zx_coef
1536     real, dimension(klon) :: zx_sl, zx_k1
1537     real, dimension(klon) :: zx_q_0 , d_ts
1538 guez 38 real :: zdelta, zcvm5, zx_qs, zcor, zx_dq_s_dh
1539     real :: bilan_f, fq_fonte
1540     REAL :: subli, fsno
1541 guez 3 REAL, DIMENSION(klon) :: bil_eau_s, snow_evap
1542     real, parameter :: t_grnd = 271.35, t_coup = 273.15
1543     !! PB temporaire en attendant mieux pour le modele de neige
1544     ! REAL, parameter :: chasno = RLMLT/(2.3867E+06*0.15)
1545     REAL, parameter :: chasno = 3.334E+05/(2.3867E+06*0.15)
1546     !IM cf JLD/ GKtest
1547     REAL, parameter :: chaice = 3.334E+05/(2.3867E+06*0.15)
1548     ! fin GKtest
1549 guez 14
1550 guez 38 logical, save :: check = .FALSE.
1551     character (len = 20) :: modname = 'fonte_neige'
1552     logical, save :: neige_fond = .false.
1553     real, save :: max_eau_sol = 150.0
1554 guez 3 character (len = 80) :: abort_message
1555 guez 38 logical, save :: first = .true., second=.false.
1556     real :: coeff_rel
1557 guez 3
1558 guez 14 if (check) write(*, *)'Entree ', modname, ' surface = ', nisurf
1559 guez 3
1560     ! Initialisations
1561     coeff_rel = dtime/(tau_calv * rday)
1562 guez 14 bil_eau_s = 0.
1563 guez 3 DO i = 1, knon
1564     zx_pkh(i) = (ps(i)/ps(i))**RKAPPA
1565     IF (thermcep) THEN
1566 guez 14 zdelta=MAX(0., SIGN(1., rtt-tsurf(i)))
1567 guez 3 zcvm5 = R5LES*RLVTT*(1.-zdelta) + R5IES*RLSTT*zdelta
1568     zcvm5 = zcvm5 / RCPD / (1.0+RVTMP2*q1lay(i))
1569 guez 14 zx_qs= r2es * FOEEW(tsurf(i), zdelta)/ps(i)
1570     zx_qs=MIN(0.5, zx_qs)
1571 guez 3 zcor=1./(1.-retv*zx_qs)
1572     zx_qs=zx_qs*zcor
1573 guez 14 zx_dq_s_dh = FOEDE(tsurf(i), zdelta, zcvm5, zx_qs, zcor) &
1574 guez 38 /RLVTT / zx_pkh(i)
1575 guez 3 ELSE
1576     IF (tsurf(i).LT.t_coup) THEN
1577     zx_qs = qsats(tsurf(i)) / ps(i)
1578 guez 14 zx_dq_s_dh = dqsats(tsurf(i), zx_qs)/RLVTT &
1579 guez 38 / zx_pkh(i)
1580 guez 3 ELSE
1581     zx_qs = qsatl(tsurf(i)) / ps(i)
1582 guez 14 zx_dq_s_dh = dqsatl(tsurf(i), zx_qs)/RLVTT &
1583 guez 38 / zx_pkh(i)
1584 guez 3 ENDIF
1585     ENDIF
1586     zx_dq_s_dt(i) = RCPD * zx_pkh(i) * zx_dq_s_dh
1587     zx_qsat(i) = zx_qs
1588     zx_coef(i) = coef1lay(i) &
1589 guez 38 * (1.0+SQRT(u1lay(i)**2+v1lay(i)**2)) &
1590     * p1lay(i)/(RD*t1lay(i))
1591 guez 3 ENDDO
1592    
1593     ! === Calcul de la temperature de surface ===
1594 guez 14
1595 guez 3 ! zx_sl = chaleur latente d'evaporation ou de sublimation
1596 guez 14
1597 guez 3 do i = 1, knon
1598     zx_sl(i) = RLVTT
1599     if (tsurf(i) .LT. RTT) zx_sl(i) = RLSTT
1600     zx_k1(i) = zx_coef(i)
1601     enddo
1602    
1603     do i = 1, knon
1604     ! Q
1605     zx_oq(i) = 1. - (beta(i) * zx_k1(i) * peqBcoef(i) * dtime)
1606     zx_mq(i) = beta(i) * zx_k1(i) * &
1607 guez 38 (peqAcoef(i) - zx_qsat(i) &
1608     + zx_dq_s_dt(i) * tsurf(i)) &
1609     / zx_oq(i)
1610 guez 3 zx_nq(i) = beta(i) * zx_k1(i) * (-1. * zx_dq_s_dt(i)) &
1611 guez 38 / zx_oq(i)
1612 guez 3
1613     ! H
1614     zx_oh(i) = 1. - (zx_k1(i) * petBcoef(i) * dtime)
1615     zx_mh(i) = zx_k1(i) * petAcoef(i) / zx_oh(i)
1616     zx_nh(i) = - (zx_k1(i) * RCPD * zx_pkh(i))/ zx_oh(i)
1617     enddo
1618    
1619     WHERE (precip_snow > 0.) snow = snow + (precip_snow * dtime)
1620     snow_evap = 0.
1621     WHERE (evap > 0. )
1622     snow_evap = MIN (snow / dtime, evap)
1623     snow = snow - snow_evap * dtime
1624     snow = MAX(0.0, snow)
1625     end where
1626    
1627 guez 38 ! bil_eau_s = bil_eau_s + (precip_rain * dtime) - (evap - snow_evap) * dtime
1628 guez 3 bil_eau_s = (precip_rain * dtime) - (evap - snow_evap) * dtime
1629    
1630 guez 14
1631 guez 3 ! Y'a-t-il fonte de neige?
1632 guez 14
1633 guez 3 ffonte=0.
1634     do i = 1, knon
1635     neige_fond = ((snow(i) > epsfra .OR. nisurf == is_sic .OR. nisurf == is_lic) &
1636 guez 38 .AND. tsurf_new(i) >= RTT)
1637 guez 3 if (neige_fond) then
1638 guez 14 fq_fonte = MIN( MAX((tsurf_new(i)-RTT )/chasno, 0.0), snow(i))
1639 guez 3 ffonte(i) = fq_fonte * RLMLT/dtime
1640     snow(i) = max(0., snow(i) - fq_fonte)
1641     bil_eau_s(i) = bil_eau_s(i) + fq_fonte
1642 guez 38 tsurf_new(i) = tsurf_new(i) - fq_fonte * chasno
1643     !IM cf JLD OK
1644 guez 3 !IM cf JLD/ GKtest fonte aussi pour la glace
1645     IF (nisurf == is_sic .OR. nisurf == is_lic ) THEN
1646 guez 14 fq_fonte = MAX((tsurf_new(i)-RTT )/chaice, 0.0)
1647 guez 3 ffonte(i) = ffonte(i) + fq_fonte * RLMLT/dtime
1648     bil_eau_s(i) = bil_eau_s(i) + fq_fonte
1649     tsurf_new(i) = RTT
1650     ENDIF
1651     d_ts(i) = tsurf_new(i) - tsurf(i)
1652     endif
1653 guez 14
1654 guez 38 ! s'il y a une hauteur trop importante de neige, elle s'coule
1655 guez 3 fqcalving(i) = max(0., snow(i) - snow_max)/dtime
1656 guez 14 snow(i)=min(snow(i), snow_max)
1657    
1658 guez 3 IF (nisurf == is_ter) then
1659     qsol(i) = qsol(i) + bil_eau_s(i)
1660     run_off(i) = run_off(i) + MAX(qsol(i) - max_eau_sol, 0.0)
1661     qsol(i) = MIN(qsol(i), max_eau_sol)
1662     else if (nisurf == is_lic) then
1663 guez 38 run_off_lic(i) = (coeff_rel * fqcalving(i)) + &
1664     (1. - coeff_rel) * run_off_lic_0(i)
1665 guez 3 run_off_lic_0(i) = run_off_lic(i)
1666     run_off_lic(i) = run_off_lic(i) + bil_eau_s(i)/dtime
1667     endif
1668     enddo
1669    
1670     END SUBROUTINE fonte_neige
1671    
1672     END MODULE interface_surf

  ViewVC Help
Powered by ViewVC 1.1.21