/[lmdze]/trunk/libf/phylmd/interface_surf.f90
ViewVC logotype

Contents of /trunk/libf/phylmd/interface_surf.f90

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (show annotations)
Fri Apr 8 12:43:31 2011 UTC (13 years, 1 month ago) by guez
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 MODULE interface_surf
2
3 ! From phylmd/interface_surf.F90, version 1.8 2005/05/25 13:10:09
4
5 ! 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
12 ! L. Fairhead, LMD, february 2000
13
14 IMPLICIT none
15
16 PRIVATE
17 PUBLIC :: interfsurf_hq
18
19 ! run_off ruissellement total
20 REAL, ALLOCATABLE, DIMENSION(:), SAVE :: run_off, run_off_lic
21 real, allocatable, dimension(:), save :: coastalflow, riverflow
22
23 REAL, ALLOCATABLE, DIMENSION(:, :), SAVE :: tmp_rriv, tmp_rcoa, tmp_rlic
24 ! pour simuler la fonte des glaciers antarctiques
25 REAL, ALLOCATABLE, DIMENSION(:, :), SAVE :: coeff_iceberg
26 real, save :: surf_maille
27 real, save :: cte_flux_iceberg = 6.3e7
28 integer, save :: num_antarctic = 1
29 REAL, save :: tau_calv
30
31 CONTAINS
32
33 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
51 ! Cette routine sert d'aiguillage entre l'atmosphère et la surface
52 ! en général (sols continentaux, océans, glaces) pour les flux de
53 ! 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 use abort_gcm_m, only: abort_gcm
61 use gath_cpl, only: gath2cpl
62 use indicesol
63 use SUPHEC_M
64 use albsno_m, only: albsno
65
66 ! Parametres d'entree
67 ! input:
68 ! 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 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 real, intent(IN) :: rmu0(klon)
127 integer, intent(IN) :: nisurf
128 integer, intent(IN) :: knon
129 integer, dimension(klon), intent(in) :: knindex
130 real, dimension(klon, nbsrf), intent(IN) :: pctsrf
131 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 real, dimension(klon), intent(INOUT) :: seaice ! glace de mer (kg/m2)
150 REAL, DIMENSION(klon), INTENT(INOUT) :: radsol, fder
151 real, dimension(klon), intent(IN) :: zmasq
152 real, dimension(klon), intent(IN) :: taux, tauy, rugos, rugoro
153 real, dimension(klon), intent(IN) :: windsp
154 character(len=*), intent(IN):: ocean
155 integer :: npas, nexca ! nombre et pas de temps couplage
156 real, dimension(klon), intent(INOUT) :: evap, snow, qsurf
157 !! PB ajout pour soil
158 logical, intent(in):: soil_model
159 integer :: nsoilmx
160 REAL, DIMENSION(klon, nsoilmx) :: tsoil
161 REAL, dimension(klon), intent(INOUT) :: qsol
162 REAL, dimension(klon) :: soilcap
163 REAL, dimension(klon) :: soilflux
164
165 ! Parametres de sortie
166 ! output:
167 ! 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 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 real, dimension(klon, nbsrf), intent(OUT) :: pctsrf_new
182 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 !jld a rajouter real, dimension(klon), intent(INOUT):: ffonte
187 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 !jld a rajouter real, dimension(klon), intent(INOUT):: fqcalving
191 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 real, allocatable, dimension(:, :), save :: tmp_pctsrf_slab
199 real, allocatable, dimension(:), save :: tmp_seaice
200
201 ! Local
202 character (len = 20), save :: modname = 'interfsurf_hq'
203 character (len = 80) :: abort_message
204 logical, save :: first_call = .true.
205 integer, save :: error
206 integer :: ii
207 logical, save :: check = .false.
208 real, dimension(klon):: cal, beta, dif_grnd, capsol
209 real, parameter :: calice=1.0/(5.1444e+06*0.15), tau_gl=86400.*5.
210 real, parameter :: calsno=1./(2.3867e+06*.15)
211 real, dimension(klon):: tsurf_temp
212 real, dimension(klon):: alb_neig, alb_eau
213 real, DIMENSION(klon):: zfra
214 logical :: cumul = .false.
215 INTEGER, dimension(1) :: iloc
216 real, dimension(klon):: fder_prev
217 REAL, dimension(klon) :: bidule
218
219 !-------------------------------------------------------------
220
221 if (check) write(*, *) 'Entree ', modname
222
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 write(*, *)' *** Warning ***'
230 write(*, *)' nisurf = ', nisurf, ' /= is_ter = ', is_ter
231 write(*, *)'or on doit commencer par les surfaces continentales'
232 abort_message='voir ci-dessus'
233 call abort_gcm(modname, abort_message, 1)
234 endif
235 if (ocean /= 'slab' .and. ocean /= 'force') then
236 write(*, *)' *** Warning ***'
237 write(*, *)'Option couplage pour l''ocean = ', ocean
238 abort_message='option pour l''ocean non valable'
239 call abort_gcm(modname, abort_message, 1)
240 endif
241 if ( is_oce > is_sic ) then
242 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 abort_message='voir ci-dessus'
247 call abort_gcm(modname, abort_message, 1)
248 endif
249 endif
250 first_call = .false.
251
252 ! Initialisations diverses
253
254 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
266 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 call abort_gcm(modname, abort_message, 1)
274 endif
275 endif
276 if (.not. allocated(tmp_flux_g)) then
277 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 call abort_gcm(modname, abort_message, 1)
284 endif
285 endif
286 if (.not. allocated(tmp_radsol)) then
287 allocate(tmp_radsol(klon), stat = error)
288 if (error /= 0) then
289 abort_message='Pb allocation tmp_radsol'
290 call abort_gcm(modname, abort_message, 1)
291 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 allocate(tmp_pctsrf_slab(klon, nbsrf), stat = error)
298 if (error /= 0) then
299 abort_message='Pb allocation tmp_pctsrf_slab'
300 call abort_gcm(modname, abort_message, 1)
301 endif
302 DO i=1, klon
303 tmp_pctsrf_slab(i, 1:nbsrf)=pctsrf(i, 1:nbsrf)
304 ENDDO
305 endif
306
307 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 call abort_gcm(modname, abort_message, 1)
312 endif
313 DO i=1, klon
314 tmp_seaice(i)=seaice(i)
315 ENDDO
316 endif
317
318 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 call abort_gcm(modname, abort_message, 1)
323 endif
324 endif
325 DO i=1, klon
326 tmp_tslab(i)=tslab(i)
327 ENDDO
328
329 ! Aiguillage vers les differents schemas de surface
330
331 if (nisurf == is_ter) then
332
333 ! Surface "terre" appel a l'interface avec les sols continentaux
334
335 ! 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 call abort_gcm(modname, abort_message, 1)
341 endif
342 allocate(riverflow(knon), stat = error)
343 if (error /= 0) then
344 abort_message='Pb allocation riverflow'
345 call abort_gcm(modname, abort_message, 1)
346 endif
347 allocate(run_off(knon), stat = error)
348 if (error /= 0) then
349 abort_message='Pb allocation run_off'
350 call abort_gcm(modname, abort_message, 1)
351 endif
352 !cym
353 run_off=0.0
354 !cym
355
356 !!$PB
357 ALLOCATE (tmp_rriv(iim, jjm+1), stat=error)
358 if (error /= 0) then
359 abort_message='Pb allocation tmp_rriv'
360 call abort_gcm(modname, abort_message, 1)
361 endif
362 ALLOCATE (tmp_rcoa(iim, jjm+1), stat=error)
363 if (error /= 0) then
364 abort_message='Pb allocation tmp_rcoa'
365 call abort_gcm(modname, abort_message, 1)
366 endif
367 ALLOCATE (tmp_rlic(iim, jjm+1), stat=error)
368 if (error /= 0) then
369 abort_message='Pb allocation tmp_rlic'
370 call abort_gcm(modname, abort_message, 1)
371 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 write(*, *)'Bizarre, le nombre de points continentaux'
379 write(*, *)'a change entre deux appels. J''arrete ...'
380 abort_message='voir ci-dessus'
381 call abort_gcm(modname, abort_message, 1)
382 endif
383 coastalflow = 0.
384 riverflow = 0.
385
386 ! Calcul age de la neige
387
388 if (.not. ok_veget) then
389 ! 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 ! 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 CALL soil(dtime, nisurf, knon, snow, tsurf, tsoil, soilcap, &
399 soilflux)
400 cal(1:knon) = RCPD / soilcap(1:knon)
401 radsol(1:knon) = radsol(1:knon) + soilflux(1:knon)
402 ELSE
403 cal = RCPD * capsol
404 ENDIF
405 CALL calcul_fluxs( klon, knon, nisurf, dtime, &
406 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
412 CALL fonte_neige( klon, knon, nisurf, dtime, &
413 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
420 call albsno(klon, knon, dtime, agesno, alb_neig, precip_snow)
421 where (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
422 zfra(1:knon) = max(0.0, min(1.0, snow(1:knon)/(snow(1:knon)+10.0)))
423 alb_new(1 : knon) = alb_neig(1 : knon) *zfra(1:knon) + &
424 alb_new(1 : knon)*(1.0-zfra(1:knon))
425 z0_new = sqrt(z0_new**2+rugoro**2)
426 alblw(1 : knon) = alb_new(1 : knon)
427 endif
428
429 ! Remplissage des pourcentages de surface
430 pctsrf_new(:, nisurf) = pctsrf(:, nisurf)
431 else if (nisurf == is_oce) then
432 ! Surface "ocean" appel a l'interface avec l'ocean
433 if (ocean == 'slab') then
434 tsurf_new = tsurf
435 pctsrf_new = tmp_pctsrf_slab
436 else
437 ! lecture conditions limites
438 call interfoce_lim(itime, dtime, jour, klon, nisurf, knon, knindex, &
439 debut, tsurf_new, pctsrf_new)
440 endif
441
442 tsurf_temp = tsurf_new
443 cal = 0.
444 beta = 1.
445 dif_grnd = 0.
446 alb_neig = 0.
447 agesno = 0.
448
449 call calcul_fluxs( klon, knon, nisurf, dtime, &
450 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
456 fder_prev = fder
457 fder = fder_prev + dflux_s + dflux_l
458
459 iloc = maxloc(fder(1:klon))
460 if (check.and.fder(iloc(1))> 0.) then
461 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 dflux_s(iloc(1)), dflux_l(iloc(1))
465 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
476 ! 2eme appel a interfoce pour le cumul des champs (en particulier
477 ! fluxsens et fluxlat calcules dans calcul_fluxs)
478
479 if (ocean == 'slab ') then
480 seaice=tmp_seaice
481 cumul = .true.
482 call interfoce_slab(klon, debut, itime, dtime, jour, &
483 tmp_radsol, tmp_flux_o, tmp_flux_g, pctsrf, &
484 tslab, seaice, pctsrf_new)
485
486 tmp_pctsrf_slab=pctsrf_new
487 DO i=1, knon
488 tsurf_new(i)=tslab(knindex(i))
489 ENDDO
490 endif
491
492 ! calcul albedo
493 if ( minval(rmu0) == maxval(rmu0) .and. minval(rmu0) == -999.999 ) then
494 CALL alboc(FLOAT(jour), rlat, alb_eau)
495 else ! cycle diurne
496 CALL alboc_cd(rmu0, alb_eau)
497 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 if (check) write(*, *)'sea ice, nisurf = ', nisurf
506
507 ! Surface "glace de mer" appel a l'interface avec l'ocean
508
509
510 if (ocean == 'slab ') then
511 pctsrf_new=tmp_pctsrf_slab
512
513 DO ii = 1, knon
514 tsurf_new(ii) = tsurf(ii)
515 IF (pctsrf_new(knindex(ii), nisurf) < EPSFRA) then
516 snow(ii) = 0.0
517 tsurf_new(ii) = RTT - 1.8
518 IF (soil_model) tsoil(ii, :) = RTT -1.8
519 ENDIF
520 ENDDO
521
522 CALL calbeta(dtime, nisurf, knon, snow, qsol, beta, capsol, dif_grnd)
523
524 IF (soil_model) THEN
525 CALL soil(dtime, nisurf, knon, snow, tsurf_new, tsoil, soilcap, soilflux)
526 cal(1:knon) = RCPD / soilcap(1:knon)
527 radsol(1:knon) = radsol(1:knon) + soilflux(1:knon)
528 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
536 ELSE
537 ! ! lecture conditions limites
538 CALL interfoce_lim(itime, dtime, jour, &
539 klon, nisurf, knon, knindex, &
540 debut, &
541 tsurf_new, pctsrf_new)
542
543 !IM cf LF
544 DO ii = 1, knon
545 tsurf_new(ii) = tsurf(ii)
546 !IMbad IF (pctsrf_new(ii, nisurf) < EPSFRA) then
547 IF (pctsrf_new(knindex(ii), nisurf) < EPSFRA) then
548 snow(ii) = 0.0
549 !IM cf LF/JLD tsurf(ii) = RTT - 1.8
550 tsurf_new(ii) = RTT - 1.8
551 IF (soil_model) tsoil(ii, :) = RTT -1.8
552 endif
553 enddo
554
555 CALL calbeta(dtime, nisurf, knon, snow, qsol, beta, capsol, dif_grnd)
556
557 IF (soil_model) THEN
558 !IM cf LF/JLD CALL soil(dtime, nisurf, knon, snow, tsurf, tsoil, soilcap, soilflux)
559 CALL soil(dtime, nisurf, knon, snow, tsurf_new, tsoil, soilcap, soilflux)
560 cal(1:knon) = RCPD / soilcap(1:knon)
561 radsol(1:knon) = radsol(1:knon) + soilflux(1:knon)
562 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 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
580 !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
584 !IM: faire dependre le coefficient de conduction de la glace de mer
585 ! 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
588 ! 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
596 IF (cal(i).GT.1.0e-15) flux_g(i)=(tsurf_new(i)-t_grnd) &
597 * dif_grnd(i) *RCPD/cal(i)
598 ! & * new_dif_grnd(i) *RCPD/cal(i)
599 tmp_flux_g(knindex(i))=flux_g(i)
600 tmp_radsol(knindex(i))=radsol(i)
601 ENDDO
602
603 CALL fonte_neige( klon, knon, nisurf, dtime, &
604 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
611 ! calcul albedo
612
613 CALL albsno(klon, knon, dtime, agesno, alb_neig, precip_snow)
614 WHERE (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
615 zfra(1:knon) = MAX(0.0, MIN(1.0, snow(1:knon)/(snow(1:knon)+10.0)))
616 alb_new(1 : knon) = alb_neig(1 : knon) *zfra(1:knon) + &
617 0.6 * (1.0-zfra(1:knon))
618
619 fder_prev = fder
620 fder = fder_prev + dflux_s + dflux_l
621
622 iloc = maxloc(fder(1:klon))
623 if (check.and.fder(iloc(1))> 0.) then
624 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 dflux_s(iloc(1)), dflux_l(iloc(1))
628 endif
629
630
631 ! 2eme appel a interfoce pour le cumul et le passage des flux a l'ocean
632
633 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 if (check) write(*, *)'glacier, nisurf = ', nisurf
640
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 call abort_gcm(modname, abort_message, 1)
646 endif
647 run_off_lic = 0.
648 endif
649
650 ! Surface "glacier continentaux" appel a l'interface avec le sol
651
652 IF (soil_model) THEN
653 CALL soil(dtime, nisurf, knon, snow, tsurf, tsoil, soilcap, soilflux)
654 cal(1:knon) = RCPD / soilcap(1:knon)
655 radsol(1:knon) = radsol(1:knon) + soilflux(1:knon)
656 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 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
670 call fonte_neige( klon, knon, nisurf, dtime, &
671 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
678 ! passage du run-off des glaciers calcule dans fonte_neige au coupleur
679 bidule=0.
680 bidule(1:knon)= run_off_lic(1:knon)
681 call gath2cpl(bidule, tmp_rlic, klon, knon, iim, jjm, knindex)
682
683 ! calcul albedo
684
685 CALL albsno(klon, knon, dtime, agesno, alb_neig, precip_snow)
686 WHERE (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
687 zfra(1:knon) = MAX(0.0, MIN(1.0, snow(1:knon)/(snow(1:knon)+10.0)))
688 alb_new(1 : knon) = alb_neig(1 : knon)*zfra(1:knon) + &
689 0.6 * (1.0-zfra(1:knon))
690
691 !IM: plusieurs choix/tests sur l'albedo des "glaciers continentaux"
692 ! 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
699
700 ! Rugosite
701
702 z0_new = rugoro
703
704 ! Remplissage des pourcentages de surface
705
706 pctsrf_new(:, nisurf) = pctsrf(:, nisurf)
707
708 alblw(1:knon) = alb_new(1:knon)
709 else
710 write(*, *)'Index surface = ', nisurf
711 abort_message = 'Index surface non valable'
712 call abort_gcm(modname, abort_message, 1)
713 endif
714
715 END SUBROUTINE interfsurf_hq
716
717 !************************
718
719 SUBROUTINE interfoce_slab(klon, debut, itap, dtime, ijour, &
720 radsol, fluxo, fluxg, pctsrf, &
721 tslab, seaice, pctsrf_slab)
722
723 ! 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
727 ! I. Musat 04.02.2005
728
729 ! input:
730 ! 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 ! output:
740 ! 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
744 use indicesol
745 use clesphys
746 use abort_gcm_m, only: abort_gcm
747 use SUPHEC_M
748
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 real, dimension(klon), intent(INOUT) :: seaice ! glace de mer (kg/m2)
762 real, dimension(klon, nbsrf), intent(OUT) :: pctsrf_slab
763
764 ! 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 logical, save :: check = .false.
771
772 REAL, parameter :: cyang=50.0 * 4.228e+06 ! capacite calorifique volumetrique de l'eau J/(m2 K)
773 REAL, parameter :: cbing=0.334e+05 ! J/kg
774 real, dimension(klon) :: siceh !hauteur de la glace de mer (m)
775 INTEGER :: i
776 integer :: sum_error, error
777 REAL :: zz, za, zb
778
779 character (len = 80) :: abort_message
780 character (len = 20) :: modname = 'interfoce_slab'
781
782 julien = MOD(ijour, 360)
783 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 abort_message='Pb allocation var. slab_bils, lmt_bils, tmp_tslab, tmp_seaice'
791 call abort_gcm(modname, abort_message, 1)
792 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
797 IF (check) THEN
798 PRINT*, 'interfoce_slab klon, debut, itap, dtime, ijour, &
799 & lmt_pas ', klon, debut, itap, dtime, ijour, &
800 lmt_pas
801 ENDIF !check
802
803 PRINT*, '************************'
804 PRINT*, 'SLAB OCEAN est actif, prenez precautions !'
805 PRINT*, '************************'
806
807 ! a mettre un slab_bils aussi en force !!!
808
809 DO i = 1, klon
810 slab_bils(i) = 0.0
811 ENDDO
812
813 ENDIF !debut
814 pctsrf_slab(1:klon, 1:nbsrf) = pctsrf(1:klon, 1:nbsrf)
815
816 ! lecture du bilan au sol lmt_bils issu d'une simulation forcee en debut de journee
817
818 IF (MOD(itap, lmt_pas) .EQ. 1) THEN !1er pas de temps de la journee
819 idayvrai = ijour
820 CALL condsurf(julien, idayvrai, lmt_bils)
821 ENDIF !(MOD(itap-1, lmt_pas) .EQ. 0) THEN
822
823 DO i = 1, klon
824 IF((pctsrf_slab(i, is_oce).GT.epsfra).OR. &
825 (pctsrf_slab(i, is_sic).GT.epsfra)) THEN
826
827 ! fabriquer de la glace si congelation atteinte:
828
829 IF (tmp_tslab(i).LT.(RTT-1.8)) THEN
830 zz = (RTT-1.8)-tmp_tslab(i)
831 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
836 ! faire fondre de la glace si temperature est superieure a 0:
837
838 IF ((tmp_tslab(i).GT.RTT) .AND. (tmp_seaice(i).GT.0.0)) THEN
839 zz = cyang/cbing * (tmp_tslab(i)-RTT)
840 zz = MIN(zz, tmp_seaice(i))
841 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
846 ! limiter la glace de mer a 10 metres (10000 kg/m2)
847
848 IF(tmp_seaice(i).GT.45.) THEN
849 tmp_seaice(i) = MIN(tmp_seaice(i), 10000.0)
850 ELSE
851 tmp_seaice(i) = 0.
852 ENDIF
853 seaice(i) = tmp_seaice(i)
854 siceh(i)=tmp_seaice(i)/1000. !en metres
855
856 ! determiner la nature du sol (glace de mer ou ocean libre):
857
858 ! on fait dependre la fraction de seaice "pctsrf(i, is_sic)"
859 ! de l'epaisseur de seaice :
860 ! 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 1.-(pctsrf_slab(i, is_ter)+pctsrf_slab(i, is_lic)))
865 pctsrf_slab(i, is_oce)=1.0 - &
866 (pctsrf_slab(i, is_ter)+pctsrf_slab(i, is_lic)+pctsrf_slab(i, is_sic))
867 ENDIF !pctsrf
868 ENDDO
869
870 ! Calculer le bilan du flux de chaleur au sol :
871
872 DO i = 1, klon
873 za = radsol(i) + fluxo(i)
874 zb = fluxg(i)
875 IF((pctsrf_slab(i, is_oce).GT.epsfra).OR. &
876 (pctsrf_slab(i, is_sic).GT.epsfra)) THEN
877 slab_bils(i)=slab_bils(i)+(za*pctsrf_slab(i, is_oce) &
878 +zb*pctsrf_slab(i, is_sic))/ FLOAT(lmt_pas)
879 ENDIF
880 ENDDO !klon
881
882 ! calcul tslab
883
884 IF (MOD(itap, lmt_pas).EQ.0) THEN !fin de journee
885 DO i = 1, klon
886 IF ((pctsrf_slab(i, is_oce).GT.epsfra).OR. &
887 (pctsrf_slab(i, is_sic).GT.epsfra)) THEN
888 tmp_tslab(i) = tmp_tslab(i) + &
889 (slab_bils(i)-lmt_bils(i)) &
890 /cyang*unjour
891 ! on remet l'accumulation a 0
892 slab_bils(i) = 0.
893 ENDIF !pctsrf
894 ENDDO !klon
895 ENDIF !(MOD(itap, lmt_pas).EQ.0) THEN
896
897 tslab = tmp_tslab
898 seaice = tmp_seaice
899 END SUBROUTINE interfoce_slab
900
901 !************************
902
903 SUBROUTINE interfoce_lim(itime, dtime, jour, &
904 klon, nisurf, knon, knindex, &
905 debut, &
906 lmt_sst, pctsrf_new)
907
908 ! Cette routine sert d'interface entre le modele atmospherique et
909 ! un fichier de conditions aux limites
910
911 ! L. Fairhead 02/2000
912
913 use abort_gcm_m, only: abort_gcm
914 use indicesol
915
916 integer, intent(IN) :: itime ! numero du pas de temps courant
917 real , intent(IN) :: dtime ! pas de temps de la physique (en s)
918 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
925 ! Parametres de sortie
926 ! output:
927 ! lmt_sst SST lues dans le fichier de CL
928 ! pctsrf_new sous-maille fractionnelle
929 real, intent(out), dimension(klon) :: lmt_sst
930 real, intent(out), dimension(klon, nbsrf) :: pctsrf_new
931
932 ! Variables locales
933 integer :: ii
934 INTEGER, save :: lmt_pas ! frequence de lecture des conditions limites
935 ! (en pas de physique)
936 logical, save :: deja_lu ! pour indiquer que le jour a lire a deja
937 ! lu pour une surface precedente
938 integer, save :: jour_lu
939 integer :: ierr
940 character (len = 20) :: modname = 'interfoce_lim'
941 character (len = 80) :: abort_message
942 logical, save :: newlmt = .TRUE.
943 logical, save :: check = .FALSE.
944 ! Champs lus dans le fichier de CL
945 real, allocatable , save, dimension(:) :: sst_lu, rug_lu, nat_lu
946 real, allocatable , save, dimension(:, :) :: pct_tmp
947
948 ! quelques variables pour netcdf
949
950 include "netcdf.inc"
951 integer :: nid, nvarid
952 integer, dimension(2) :: start, epais
953
954 ! --------------------------------------------------
955
956 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 allocate(pct_tmp(klon, nbsrf))
962 endif
963
964 if ((jour - jour_lu) /= 0) deja_lu = .false.
965
966 if (check) write(*, *)modname, ' :: jour, jour_lu, deja_lu', jour, jour_lu, &
967 deja_lu
968 if (check) write(*, *)modname, ' :: itime, lmt_pas ', itime, lmt_pas, dtime
969
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
973 ! Ouverture du fichier
974
975 ierr = NF_OPEN ('limit.nc', NF_NOWRITE, nid)
976 if (ierr.NE.NF_NOERR) then
977 abort_message &
978 = 'Pb d''ouverture du fichier de conditions aux limites'
979 call abort_gcm(modname, abort_message, 1)
980 endif
981
982 ! La tranche de donnees a lire:
983
984 start(1) = 1
985 start(2) = jour
986 epais(1) = klon
987 epais(2) = 1
988
989 if (newlmt) then
990
991 ! Fraction "ocean"
992
993 ierr = NF_INQ_VARID(nid, 'FOCE', nvarid)
994 if (ierr /= NF_NOERR) then
995 abort_message = 'Le champ <FOCE> est absent'
996 call abort_gcm(modname, abort_message, 1)
997 endif
998 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, pct_tmp(1, is_oce))
999 if (ierr /= NF_NOERR) then
1000 abort_message = 'Lecture echouee pour <FOCE>'
1001 call abort_gcm(modname, abort_message, 1)
1002 endif
1003
1004 ! Fraction "glace de mer"
1005
1006 ierr = NF_INQ_VARID(nid, 'FSIC', nvarid)
1007 if (ierr /= NF_NOERR) then
1008 abort_message = 'Le champ <FSIC> est absent'
1009 call abort_gcm(modname, abort_message, 1)
1010 endif
1011 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, pct_tmp(1, is_sic))
1012 if (ierr /= NF_NOERR) then
1013 abort_message = 'Lecture echouee pour <FSIC>'
1014 call abort_gcm(modname, abort_message, 1)
1015 endif
1016
1017 ! Fraction "terre"
1018
1019 ierr = NF_INQ_VARID(nid, 'FTER', nvarid)
1020 if (ierr /= NF_NOERR) then
1021 abort_message = 'Le champ <FTER> est absent'
1022 call abort_gcm(modname, abort_message, 1)
1023 endif
1024 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, pct_tmp(1, is_ter))
1025 if (ierr /= NF_NOERR) then
1026 abort_message = 'Lecture echouee pour <FTER>'
1027 call abort_gcm(modname, abort_message, 1)
1028 endif
1029
1030 ! Fraction "glacier terre"
1031
1032 ierr = NF_INQ_VARID(nid, 'FLIC', nvarid)
1033 if (ierr /= NF_NOERR) then
1034 abort_message = 'Le champ <FLIC> est absent'
1035 call abort_gcm(modname, abort_message, 1)
1036 endif
1037 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, pct_tmp(1, is_lic))
1038 if (ierr /= NF_NOERR) then
1039 abort_message = 'Lecture echouee pour <FLIC>'
1040 call abort_gcm(modname, abort_message, 1)
1041 endif
1042
1043 else ! on en est toujours a rnatur
1044
1045 ierr = NF_INQ_VARID(nid, 'NAT', nvarid)
1046 if (ierr /= NF_NOERR) then
1047 abort_message = 'Le champ <NAT> est absent'
1048 call abort_gcm(modname, abort_message, 1)
1049 endif
1050 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, nat_lu)
1051 if (ierr /= NF_NOERR) then
1052 abort_message = 'Lecture echouee pour <NAT>'
1053 call abort_gcm(modname, abort_message, 1)
1054 endif
1055
1056 ! Remplissage des fractions de surface
1057 ! nat = 0, 1, 2, 3 pour ocean, terre, glacier, seaice
1058
1059 pct_tmp = 0.0
1060 do ii = 1, klon
1061 pct_tmp(ii, nint(nat_lu(ii)) + 1) = 1.
1062 enddo
1063
1064
1065 ! On se retrouve avec ocean en 1 et terre en 2 alors qu'on veut le contraire
1066
1067 pctsrf_new = pct_tmp
1068 pctsrf_new (:, 2)= pct_tmp (:, 1)
1069 pctsrf_new (:, 1)= pct_tmp (:, 2)
1070 pct_tmp = pctsrf_new
1071 endif ! fin test sur newlmt
1072
1073 ! Lecture SST
1074
1075 ierr = NF_INQ_VARID(nid, 'SST', nvarid)
1076 if (ierr /= NF_NOERR) then
1077 abort_message = 'Le champ <SST> est absent'
1078 call abort_gcm(modname, abort_message, 1)
1079 endif
1080 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, sst_lu)
1081 if (ierr /= NF_NOERR) then
1082 abort_message = 'Lecture echouee pour <SST>'
1083 call abort_gcm(modname, abort_message, 1)
1084 endif
1085
1086
1087 ! Fin de lecture
1088
1089 ierr = NF_CLOSE(nid)
1090 deja_lu = .true.
1091 jour_lu = jour
1092 endif
1093
1094 ! Recopie des variables dans les champs de sortie
1095
1096 lmt_sst = 999999999.
1097 do ii = 1, knon
1098 lmt_sst(ii) = sst_lu(knindex(ii))
1099 enddo
1100
1101 pctsrf_new(:, is_oce) = pct_tmp(:, is_oce)
1102 pctsrf_new(:, is_sic) = pct_tmp(:, is_sic)
1103
1104 END SUBROUTINE interfoce_lim
1105
1106 !************************
1107
1108 SUBROUTINE interfsur_lim(itime, dtime, jour, &
1109 klon, nisurf, knon, knindex, &
1110 debut, &
1111 lmt_alb, lmt_rug)
1112
1113 ! Cette routine sert d'interface entre le modèle atmosphérique et
1114 ! un fichier de conditions aux limites.
1115
1116 ! L. Fairhead 02/2000
1117
1118 use abort_gcm_m, only: abort_gcm
1119
1120 ! Parametres d'entree
1121 ! input:
1122 ! 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 integer, intent(IN) :: itime
1131 real , intent(IN) :: dtime
1132 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 ! output:
1141 ! 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 real, intent(out), dimension(klon) :: lmt_alb
1146 real, intent(out), dimension(klon) :: lmt_rug
1147
1148 ! Variables locales
1149 integer :: ii
1150 integer, save :: lmt_pas ! frequence de lecture des conditions limites
1151 ! (en pas de physique)
1152 logical, save :: deja_lu_sur! pour indiquer que le jour a lire a deja
1153 ! lu pour une surface precedente
1154 integer, save :: jour_lu_sur
1155 integer :: ierr
1156 character (len = 20) :: modname = 'interfsur_lim'
1157 character (len = 80) :: abort_message
1158 logical, save :: newlmt = .false.
1159 logical, save :: check = .false.
1160 ! Champs lus dans le fichier de CL
1161 real, allocatable , save, dimension(:) :: alb_lu, rug_lu
1162
1163 ! quelques variables pour netcdf
1164
1165 include "netcdf.inc"
1166 integer , save :: nid, nvarid
1167 integer, dimension(2), save :: start, epais
1168
1169 !------------------------------------------------------------
1170
1171 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 if (check) write(*, *)modname, ':: jour_lu_sur, deja_lu_sur', jour_lu_sur, &
1181 deja_lu_sur
1182 if (check) write(*, *)modname, ':: itime, lmt_pas', itime, lmt_pas
1183
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
1187 ! Ouverture du fichier
1188
1189 ierr = NF_OPEN ('limit.nc', NF_NOWRITE, nid)
1190 if (ierr.NE.NF_NOERR) then
1191 abort_message &
1192 = 'Pb d''ouverture du fichier de conditions aux limites'
1193 call abort_gcm(modname, abort_message, 1)
1194 endif
1195
1196 ! La tranche de donnees a lire:
1197
1198 start(1) = 1
1199 start(2) = jour
1200 epais(1) = klon
1201 epais(2) = 1
1202
1203 ! Lecture Albedo
1204
1205 ierr = NF_INQ_VARID(nid, 'ALB', nvarid)
1206 if (ierr /= NF_NOERR) then
1207 abort_message = 'Le champ <ALB> est absent'
1208 call abort_gcm(modname, abort_message, 1)
1209 endif
1210 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, alb_lu)
1211 if (ierr /= NF_NOERR) then
1212 abort_message = 'Lecture echouee pour <ALB>'
1213 call abort_gcm(modname, abort_message, 1)
1214 endif
1215
1216 ! Lecture rugosité
1217
1218 ierr = NF_INQ_VARID(nid, 'RUG', nvarid)
1219 if (ierr /= NF_NOERR) then
1220 abort_message = 'Le champ <RUG> est absent'
1221 call abort_gcm(modname, abort_message, 1)
1222 endif
1223 ierr = NF_GET_VARA_REAL(nid, nvarid, start, epais, rug_lu)
1224 if (ierr /= NF_NOERR) then
1225 abort_message = 'Lecture echouee pour <RUG>'
1226 call abort_gcm(modname, abort_message, 1)
1227 endif
1228
1229
1230 ! Fin de lecture
1231
1232 ierr = NF_CLOSE(nid)
1233 deja_lu_sur = .true.
1234 jour_lu_sur = jour
1235 endif
1236
1237 ! Recopie des variables dans les champs de sortie
1238
1239 !!$ lmt_alb = 0.0
1240 !!$ lmt_rug = 0.0
1241 lmt_alb = 999999.
1242 lmt_rug = 999999.
1243 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 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
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
1262 ! L. Fairhead 4/2000
1263
1264 ! input:
1265 ! 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
1284 ! output:
1285 ! 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
1292
1293 use indicesol
1294 use abort_gcm_m, only: abort_gcm
1295 use yoethf_m
1296 use fcttre, only: thermcep, foeew, qsats, qsatl, foede, dqsats, dqsatl
1297 use SUPHEC_M
1298
1299 ! Parametres d'entree
1300 integer, intent(IN) :: knon, nisurf, klon
1301 real , intent(IN) :: dtime
1302 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 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 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
1330 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 character (len = 80) :: abort_message
1335 logical, save :: first = .true., second=.false.
1336
1337 if (check) write(*, *)'Entree ', modname, ' surface = ', nisurf
1338
1339 IF (check) THEN
1340 WRITE(*, *)' radsol (min, max)' &
1341 , MINVAL(radsol(1:knon)), MAXVAL(radsol(1:knon))
1342 !!CALL flush(6)
1343 ENDIF
1344
1345 if (size(coastalflow) /= knon .AND. nisurf == is_ter) then
1346 write(*, *)'Bizarre, le nombre de points continentaux'
1347 write(*, *)'a change entre deux appels. J''arrete ...'
1348 abort_message='Pb run_off'
1349 call abort_gcm(modname, abort_message, 1)
1350 endif
1351
1352 ! Traitement neige et humidite du sol
1353
1354 ! Initialisation
1355
1356 evap = 0.
1357 fluxsens=0.
1358 fluxlat=0.
1359 dflux_s = 0.
1360 dflux_l = 0.
1361
1362 ! zx_qs = qsat en kg/kg
1363
1364 DO i = 1, knon
1365 zx_pkh(i) = (ps(i)/ps(i))**RKAPPA
1366 IF (thermcep) THEN
1367 zdelta=MAX(0., SIGN(1., rtt-tsurf(i)))
1368 zcvm5 = R5LES*RLVTT*(1.-zdelta) + R5IES*RLSTT*zdelta
1369 zcvm5 = zcvm5 / RCPD / (1.0+RVTMP2*q1lay(i))
1370 zx_qs= r2es * FOEEW(tsurf(i), zdelta)/ps(i)
1371 zx_qs=MIN(0.5, zx_qs)
1372 zcor=1./(1.-retv*zx_qs)
1373 zx_qs=zx_qs*zcor
1374 zx_dq_s_dh = FOEDE(tsurf(i), zdelta, zcvm5, zx_qs, zcor) &
1375 /RLVTT / zx_pkh(i)
1376 ELSE
1377 IF (tsurf(i).LT.t_coup) THEN
1378 zx_qs = qsats(tsurf(i)) / ps(i)
1379 zx_dq_s_dh = dqsats(tsurf(i), zx_qs)/RLVTT &
1380 / zx_pkh(i)
1381 ELSE
1382 zx_qs = qsatl(tsurf(i)) / ps(i)
1383 zx_dq_s_dh = dqsatl(tsurf(i), zx_qs)/RLVTT &
1384 / zx_pkh(i)
1385 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 * (1.0+SQRT(u1lay(i)**2+v1lay(i)**2)) &
1391 * p1lay(i)/(RD*t1lay(i))
1392
1393 ENDDO
1394
1395 ! === Calcul de la temperature de surface ===
1396
1397 ! zx_sl = chaleur latente d'evaporation ou de sublimation
1398
1399 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 (peqAcoef(i) - zx_qsat(i) &
1410 + zx_dq_s_dt(i) * tsurf(i)) &
1411 / zx_oq(i)
1412 zx_nq(i) = beta(i) * zx_k1(i) * (-1. * zx_dq_s_dt(i)) &
1413 / zx_oq(i)
1414
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 (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
1428
1429 ! Y'a-t-il fonte de neige?
1430
1431 ! 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 d_ts(i) = tsurf_new(i) - tsurf(i)
1436 ! 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 !== 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 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
1464 ! Routine de traitement de la fonte de la neige dans le cas du traitement
1465 ! de sol simplifié
1466
1467 ! LF 03/2001
1468 ! input:
1469 ! 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
1489 ! output:
1490 ! 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 ! in/out:
1496 ! run_off_lic_0 run off glacier du pas de temps précedent
1497
1498
1499 use indicesol
1500 use SUPHEC_M
1501 use yoethf_m
1502 use fcttre
1503 !IM cf JLD
1504
1505 ! Parametres d'entree
1506 integer, intent(IN) :: knon, nisurf, klon
1507 real , intent(IN) :: dtime
1508 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 ! real, parameter :: snow_max=1.
1530 !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 real :: zdelta, zcvm5, zx_qs, zcor, zx_dq_s_dh
1539 real :: bilan_f, fq_fonte
1540 REAL :: subli, fsno
1541 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
1550 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 character (len = 80) :: abort_message
1555 logical, save :: first = .true., second=.false.
1556 real :: coeff_rel
1557
1558 if (check) write(*, *)'Entree ', modname, ' surface = ', nisurf
1559
1560 ! Initialisations
1561 coeff_rel = dtime/(tau_calv * rday)
1562 bil_eau_s = 0.
1563 DO i = 1, knon
1564 zx_pkh(i) = (ps(i)/ps(i))**RKAPPA
1565 IF (thermcep) THEN
1566 zdelta=MAX(0., SIGN(1., rtt-tsurf(i)))
1567 zcvm5 = R5LES*RLVTT*(1.-zdelta) + R5IES*RLSTT*zdelta
1568 zcvm5 = zcvm5 / RCPD / (1.0+RVTMP2*q1lay(i))
1569 zx_qs= r2es * FOEEW(tsurf(i), zdelta)/ps(i)
1570 zx_qs=MIN(0.5, zx_qs)
1571 zcor=1./(1.-retv*zx_qs)
1572 zx_qs=zx_qs*zcor
1573 zx_dq_s_dh = FOEDE(tsurf(i), zdelta, zcvm5, zx_qs, zcor) &
1574 /RLVTT / zx_pkh(i)
1575 ELSE
1576 IF (tsurf(i).LT.t_coup) THEN
1577 zx_qs = qsats(tsurf(i)) / ps(i)
1578 zx_dq_s_dh = dqsats(tsurf(i), zx_qs)/RLVTT &
1579 / zx_pkh(i)
1580 ELSE
1581 zx_qs = qsatl(tsurf(i)) / ps(i)
1582 zx_dq_s_dh = dqsatl(tsurf(i), zx_qs)/RLVTT &
1583 / zx_pkh(i)
1584 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 * (1.0+SQRT(u1lay(i)**2+v1lay(i)**2)) &
1590 * p1lay(i)/(RD*t1lay(i))
1591 ENDDO
1592
1593 ! === Calcul de la temperature de surface ===
1594
1595 ! zx_sl = chaleur latente d'evaporation ou de sublimation
1596
1597 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 (peqAcoef(i) - zx_qsat(i) &
1608 + zx_dq_s_dt(i) * tsurf(i)) &
1609 / zx_oq(i)
1610 zx_nq(i) = beta(i) * zx_k1(i) * (-1. * zx_dq_s_dt(i)) &
1611 / zx_oq(i)
1612
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 ! bil_eau_s = bil_eau_s + (precip_rain * dtime) - (evap - snow_evap) * dtime
1628 bil_eau_s = (precip_rain * dtime) - (evap - snow_evap) * dtime
1629
1630
1631 ! Y'a-t-il fonte de neige?
1632
1633 ffonte=0.
1634 do i = 1, knon
1635 neige_fond = ((snow(i) > epsfra .OR. nisurf == is_sic .OR. nisurf == is_lic) &
1636 .AND. tsurf_new(i) >= RTT)
1637 if (neige_fond) then
1638 fq_fonte = MIN( MAX((tsurf_new(i)-RTT )/chasno, 0.0), snow(i))
1639 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 tsurf_new(i) = tsurf_new(i) - fq_fonte * chasno
1643 !IM cf JLD OK
1644 !IM cf JLD/ GKtest fonte aussi pour la glace
1645 IF (nisurf == is_sic .OR. nisurf == is_lic ) THEN
1646 fq_fonte = MAX((tsurf_new(i)-RTT )/chaice, 0.0)
1647 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
1654 ! s'il y a une hauteur trop importante de neige, elle s'coule
1655 fqcalving(i) = max(0., snow(i) - snow_max)/dtime
1656 snow(i)=min(snow(i), snow_max)
1657
1658 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 run_off_lic(i) = (coeff_rel * fqcalving(i)) + &
1664 (1. - coeff_rel) * run_off_lic_0(i)
1665 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