/[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 12 - (show annotations)
Mon Jul 21 16:05:07 2008 UTC (15 years, 9 months ago) by guez
File size: 64594 byte(s)
-- Minor modification of input/output:

Created procedure "read_logic". Variables of module "logic" are read
by "read_logic" instead of "conf_gcm". Variable "offline" of module
"conf_gcm" is read from namelist instead of "*.def".

Deleted arguments "dtime", "co2_ppm_etat0", "solaire_etat0",
"tabcntr0" and local variables "radpas", "tab_cntrl" of
"phyetat0". "phyetat0" does not read "controle" in "startphy.nc" any
longer. "phyetat0" now reads global attribute "itau_phy" from
"startphy.nc". "phyredem" does not create variable "controle" in
"startphy.nc" any longer. "phyredem" now writes global attribute
"itau_phy" of "startphy.nc". Deleted argument "tabcntr0" of
"printflag". Removed diagnostic messages written by "printflag" for
comparison of the variable "controle" of "startphy.nc" and the
variables read from "*.def" or namelist input.

-- Removing unwanted functionality:

Removed variable "lunout" from module "iniprint", replaced everywhere
by standard output.

Removed case "ocean == 'couple'" in "clmain", "interfsurf_hq" and
"physiq". Removed procedure "interfoce_cpl".

-- Should not change anything at run time:

Automated creation of graphs in documentation. More documentation on
input files.

Converted Fortran files to free format: "phyredem.f90", "printflag.f90".

Split module "clesphy" into "clesphys" and "clesphys2".

Removed variables "conser", "leapf", "forward", "apphys", "apdiss" and
"statcl" from module "logic". Added arguments "conser" to "advect",
"leapf" to "integrd". Added local variables "forward", "leapf",
"apphys", "conser", "apdiss" in "leapfrog".

Added intent attributes.

Deleted arguments "dtime" of "phyredem", "pdtime" of "flxdtdq", "sh"
of "phytrac", "dt" of "yamada".

Deleted local variables "dtime", "co2_ppm_etat0", "solaire_etat0",
"length", "tabcntr0" in "physiq". Replaced all references to "dtime"
by references to "pdtphys".

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

  ViewVC Help
Powered by ViewVC 1.1.21