source: LMDZ.3.3/branches/rel-LF/libf/phylmd/interface_surf.F90 @ 147

Last change on this file since 147 was 147, checked in by lmdzadmin, 24 years ago

Dimensionnement de tous les tableaux a klon plutot qu'a knon pour cause
de compilateur NEC deficient (?)
LF

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.4 KB
Line 
1
2  MODULE interface_surf
3
4! Ce module regroupe toutes les routines gerant l'interface entre le modele
5! atmospherique et les modeles de surface (sols continentaux, oceans, glaces)
6! Les routines sont les suivantes:
7!
8!   interfsurf_*: routines d'aiguillage vers les interfaces avec les
9!                 differents modeles de surface
10!   interfsol\
11!             > routines d'interface proprement dite
12!   interfoce/
13!
14!   interfstart: routine d'initialisation et de lecture de l'etat initial
15!                "interface"
16!   interffin  : routine d'ecriture de l'etat de redemmarage de l'interface
17!
18!
19! L. Fairhead, LMD, 02/2000
20
21  USE ioipsl
22!  USE constantes
23
24  IMPLICIT none
25
26  PRIVATE
27  PUBLIC :: interfsurf,interfsurf_hq
28
29  INTERFACE interfsurf
30    module procedure interfsurf_hq, interfsurf_vent
31  END INTERFACE
32
33  INTERFACE interfoce
34    module procedure interfoce_cpl, interfoce_slab, interfoce_lim
35  END INTERFACE
36
37#include "YOMCST.inc"
38#include "indicesol.inc"
39
40
41! run_off      ruissellement total
42  real, allocatable, dimension(:),save    :: run_off
43
44
45
46  CONTAINS
47!
48!############################################################################
49!
50  SUBROUTINE interfsurf_hq(itime, dtime, jour, rmu0, &
51      & klon, iim, jjm, nisurf, knon, knindex, pctsrf, rlon, rlat, &
52      & debut, lafin, ok_veget, &
53      & zlev,  u1_lay, v1_lay, temp_air, spechum, hum_air, ccanopy, &
54      & tq_cdrag, petAcoef, peqAcoef, petBcoef, peqBcoef, &
55      & precip_rain, precip_snow, lwdown, swnet, swdown, &
56      & fder, taux, tauy, &
57      & albedo, snow, qsol, &
58      & tsurf, p1lay, ps, radsol, &
59      & ocean, npas, nexca, zmasq, &
60      & evap, fluxsens, fluxlat, dflux_l, dflux_s, &             
61      & tsol_rad, tsurf_new, alb_new, emis_new, z0_new, pctsrf_new, agesno)
62
63
64! Cette routine sert d'aiguillage entre l'atmosphere et la surface en general
65! (sols continentaux, oceans, glaces) pour les fluxs de chaleur et d'humidite.
66! En pratique l'interface se fait entre la couche limite du modele
67! atmospherique (clmain.F) et les routines de surface (sechiba, oasis, ...)
68!
69!
70! L.Fairhead 02/2000
71!
72! input:
73!   itime        numero du pas de temps
74!   klon         nombre total de points de grille
75!   iim, jjm     nbres de pts de grille
76!   dtime        pas de temps de la physique (en s)
77!   jour         jour dans l'annee en cours,
78!   rmu0         cosinus de l'angle solaire zenithal
79!   nexca        pas de temps couplage
80!   nisurf       index de la surface a traiter (1 = sol continental)
81!   knon         nombre de points de la surface a traiter
82!   knindex      index des points de la surface a traiter
83!   pctsrf       tableau des pourcentages de surface de chaque maille
84!   rlon         longitudes
85!   rlat         latitudes
86!   debut        logical: 1er appel a la physique
87!   lafin        logical: dernier appel a la physique
88!   ok_veget     logical: appel ou non au schema de surface continental
89!                     (si false calcul simplifie des fluxs sur les continents)
90!   zlev         hauteur de la premiere couche
91!   u1_lay       vitesse u 1ere couche
92!   v1_lay       vitesse v 1ere couche
93!   temp_air     temperature de l'air 1ere couche
94!   spechum      humidite specifique 1ere couche
95!   hum_air      humidite de l'air
96!   ccanopy      concentration CO2 canopee
97!   tq_cdrag     cdrag
98!   petAcoef     coeff. A de la resolution de la CL pour t
99!   peqAcoef     coeff. A de la resolution de la CL pour q
100!   petBcoef     coeff. B de la resolution de la CL pour t
101!   peqBcoef     coeff. B de la resolution de la CL pour q
102!   precip_rain  precipitation liquide
103!   precip_snow  precipitation solide
104!   lwdown       flux IR entrant a la surface
105!   swnet        flux solaire net
106!   swdown       flux solaire entrant a la surface
107!   albedo       albedo de la surface
108!   tsurf        temperature de surface
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, slab, couple)
113!   fder         derivee des flux (pour le couplage)
114!   taux, tauy   tension de vents
115!   zmasq        masque terre/ocean
116!
117! output:
118!   evap         evaporation totale
119!   fluxsens     flux de chaleur sensible
120!   fluxlat      flux de chaleur latente
121!   tsol_rad     
122!   tsurf_new    temperature au sol
123!   alb_new      albedo
124!   emis_new     emissivite
125!   z0_new       surface roughness
126!   pctsrf_new   nouvelle repartition des surfaces
127
128
129! Parametres d'entree
130  integer, intent(IN) :: itime
131  integer, intent(IN) :: iim, jjm
132  integer, intent(IN) :: klon
133  real, intent(IN) :: dtime
134  integer, intent(IN) :: jour
135  real, intent(IN)    :: rmu0(klon)
136  integer, intent(IN) :: nisurf
137  integer, intent(IN) :: knon
138  integer, dimension(klon), intent(in) :: knindex
139  real, dimension(klon,nbsrf), intent(IN) :: pctsrf
140  logical, intent(IN) :: debut, lafin, ok_veget
141  real, dimension(klon), intent(IN) :: rlon, rlat
142  real, dimension(klon), intent(IN) :: zlev
143  real, dimension(klon), intent(IN) :: u1_lay, v1_lay
144  real, dimension(klon), intent(IN) :: temp_air, spechum
145  real, dimension(klon), intent(IN) :: hum_air, ccanopy
146  real, dimension(klon), intent(IN) :: tq_cdrag, petAcoef, peqAcoef
147  real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
148  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
149  real, dimension(klon), intent(IN) :: lwdown, swnet, swdown, ps, albedo
150  real, dimension(klon), intent(IN) :: tsurf, p1lay
151  real, dimension(klon), intent(IN) :: radsol
152  real, dimension(klon), intent(IN) :: zmasq
153  real, dimension(klon), intent(IN) :: fder, taux, tauy
154  character (len = 6)  :: ocean
155  integer              :: npas, nexca ! nombre et pas de temps couplage
156  real, dimension(klon), intent(INOUT) :: evap, snow, qsol
157
158! Parametres de sortie
159  real, dimension(klon), intent(OUT):: fluxsens, fluxlat
160  real, dimension(klon), intent(OUT):: tsol_rad, tsurf_new, alb_new
161  real, dimension(klon), intent(OUT):: emis_new, z0_new
162  real, dimension(klon), intent(OUT):: dflux_l, dflux_s
163  real, dimension(klon,nbsrf), intent(OUT) :: pctsrf_new
164  real, dimension(klon), intent(INOUT):: agesno
165
166! Local
167  character (len = 20) :: modname = 'interfsurf_hq'
168  character (len = 80) :: abort_message
169  logical, save        :: first_call = .true.
170  INTEGER              :: error, ii
171  logical              :: check = .true.
172  real, dimension(klon):: cal, beta, dif_grnd, capsol
173  real, parameter      :: calice=1.0/(5.1444e+06*0.15), tau_gl=1./86400.*5.
174  real, parameter      :: calsno=1./(2.3867e+06*.15)
175  real, dimension(klon):: alb_ice
176  real, dimension(klon):: tsurf_temp
177  real, dimension(klon):: alb_neig_grid, alb_eau
178  real, dimension(klon):: alb_neig
179  real, DIMENSION(klon):: zfra
180
181  if (check) write(*,*) 'Entree ', modname
182!
183! On doit commencer par appeler les schemas de surfaces continentales
184! car l'ocean a besoin du ruissellement qui est y calcule
185!
186  if (first_call) then
187    if (nisurf /= is_ter .and. klon > 1) then
188      write(*,*)' *** Warning ***'
189      write(*,*)' nisurf = ',nisurf,' /= is_ter = ',is_ter
190      write(*,*)'or on doit commencer par les surfaces continentales'
191      abort_message='voir ci-dessus'
192      call abort_gcm(modname,abort_message,1)
193    endif
194    if (ocean /= 'slab  ' .and. ocean /= 'force ' .and. ocean /= 'couple') then
195      write(*,*)' *** Warning ***'
196      write(*,*)'Option couplage pour l''ocean = ', ocean
197      abort_message='option pour l''ocean non valable'
198      call abort_gcm(modname,abort_message,1)
199    endif
200    if ( is_oce > is_sic ) then
201      write(*,*)' *** Warning ***'
202      write(*,*)' Pour des raisons de sequencement dans le code'
203      write(*,*)' l''ocean doit etre traite avant la banquise'
204      write(*,*)' or is_oce = ',is_oce, '> is_sic = ',is_sic
205      abort_message='voir ci-dessus'
206      call abort_gcm(modname,abort_message,1)
207    endif
208  endif
209  first_call = .false.
210 
211! Aiguillage vers les differents schemas de surface
212
213  if (nisurf == is_ter) then
214!
215! Surface "terre" appel a l'interface avec les sols continentaux
216!
217! allocation du run-off
218    if (.not. allocated(run_off)) then
219      allocate(run_off(knon), stat = error)
220      if (error /= 0) then
221        abort_message='Pb allocation run_off'
222        call abort_gcm(modname,abort_message,1)
223      endif
224    else if (size(run_off) /= knon) then
225      write(*,*)'Bizarre, le nombre de points continentaux'
226      write(*,*)'a change entre deux appels. Je continue ...'
227      deallocate(run_off, stat = error)
228      allocate(run_off(knon), stat = error)
229      if (error /= 0) then
230        abort_message='Pb allocation run_off'
231        call abort_gcm(modname,abort_message,1)
232      endif
233    endif
234!
235! Calcul age de la neige
236!
237
238  CALL albsno(klon,agesno,alb_neig_grid) 
239 
240 
241 
242    if (.not. ok_veget) then
243!
244! calcul snow et qsol, hydrol adapté
245!
246      call calbeta(dtime, nisurf, knon, snow, qsol, beta, capsol, dif_grnd)
247      cal = RCPD * capsol
248      call calcul_fluxs( klon, knon, nisurf, dtime, &
249     &   tsurf, p1lay, cal, beta, tq_cdrag, ps, &
250     &   precip_rain, precip_snow, snow, qsol,  &
251     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
252     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
253     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
254
255!
256! calcul albedo: lecture albedo fichier CL puis ajout albedo neige
257!
258       call interfsur_lim(itime, dtime, jour, &
259     & klon, nisurf, knon, knindex, debut,  &
260     & alb_new, z0_new)
261!
262!
263       DO ii = 1, knon
264         alb_neig(ii) = alb_neig_grid(knindex(ii))
265       enddo
266       zfra = MAX(0.0,MIN(1.0,snow/(snow+10.0)))
267       alb_new = alb_neig*zfra + alb_new*(1.0-zfra)
268    else
269!
270!  appel a sechiba
271!
272      call interfsol(itime, klon, dtime, nisurf, knon, &
273     &  knindex, rlon, rlat, &
274     &  debut, lafin, ok_veget, &
275     &  zlev,  u1_lay, v1_lay, temp_air, spechum, hum_air, ccanopy, &
276     &  tq_cdrag, petAcoef, peqAcoef, petBcoef, peqBcoef, &
277     &  precip_rain, precip_snow, lwdown, swnet, swdown, &
278     &  tsurf, p1lay, ps, radsol, &
279     &  evap, fluxsens, fluxlat, &             
280     &  tsol_rad, tsurf_new, alb_new, emis_new, z0_new, dflux_l, dflux_s)
281    endif   
282!
283! Remplissage des pourcentages de surface
284!
285    pctsrf_new(:,nisurf) = pctsrf(:,nisurf)
286
287  else if (nisurf == is_oce) then
288
289    if (check) write(*,*)'ocean, nisurf = ',nisurf
290
291
292!
293! Surface "ocean" appel a l'interface avec l'ocean
294!
295    if (ocean == 'couple') then
296!     nexca = 0
297      if (nexca == 0) then
298        abort_message='nexca = 0 dans interfoce_cpl'
299        call abort_gcm(modname,abort_message,1)
300      endif
301
302      call interfoce(itime, dtime, &
303      & klon, iim, jjm, nisurf, pctsrf, knon, knindex, rlon, rlat, &
304      & ocean, npas, nexca, debut, lafin, &
305      & swdown, lwdown, precip_rain, precip_snow, evap, tsurf, &
306      & fder, albedo, taux, tauy, zmasq, &
307      & tsurf_new, alb_new, alb_ice, pctsrf_new)
308
309!    else if (ocean == 'slab  ') then
310!      call interfoce(nisurf)
311    else                              ! lecture conditions limites
312      call interfoce(itime, dtime, jour, &
313     &  klon, nisurf, knon, knindex, &
314     &  debut, &
315     &  tsurf_new, pctsrf_new)
316
317    endif
318
319    tsurf_temp = tsurf_new
320    cal = 0.
321    beta = 1.
322    dif_grnd = 0.
323
324    call calcul_fluxs( klon, knon, nisurf, dtime, &
325     &   tsurf_temp, p1lay, cal, beta, tq_cdrag, ps, &
326     &   precip_rain, precip_snow, snow, qsol,  &
327     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
328     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
329     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
330!
331! calcul albedo
332!
333
334    if ( minval(rmu0) == maxval(rmu0) .and. minval(rmu0) == -999.999 ) then
335      CALL alboc(FLOAT(jour),rlat,alb_eau)
336    else  ! cycle diurne
337      CALL alboc_cd(rmu0,alb_eau)
338    endif
339    DO ii =1, knon
340      alb_new(ii) = alb_eau(knindex(ii))
341    enddo
342!
343  else if (nisurf == is_sic) then
344
345    if (check) write(*,*)'sea ice, nisurf = ',nisurf
346
347!
348! Surface "glace de mer" appel a l'interface avec l'ocean
349!
350!
351    if (ocean == 'couple') then
352
353      call interfoce(itime, dtime, &
354      & klon, iim, jjm, nisurf, pctsrf, knon, knindex, rlon, rlat, &
355      & ocean, npas, nexca, debut, lafin, &
356      & swdown, lwdown, precip_rain, precip_snow, evap, tsurf, &
357      & fder, albedo, taux, tauy, zmasq, &
358      & tsurf_new, alb_new, alb_ice, pctsrf_new)
359
360      tsurf_temp = tsurf_new
361      dif_grnd = 0.
362      beta = 1.0
363
364!    else if (ocean == 'slab  ') then
365!      call interfoce(nisurf)
366    else                              ! lecture conditions limites
367      call interfoce(itime, dtime, jour, &
368     &  klon, nisurf, knon, knindex, &
369     &  debut, &
370     &  tsurf_new, pctsrf_new)
371
372      tsurf_temp = tsurf
373      dif_grnd = 1.0 / tau_gl
374      beta = 1.0
375    endif
376
377    cal = calice
378    where (snow > 0.0) cal = calsno
379
380    call calcul_fluxs( klon, knon, nisurf, dtime, &
381     &   tsurf_temp, p1lay, cal, beta, tq_cdrag, ps, &
382     &   precip_rain, precip_snow, snow, qsol,  &
383     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
384     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
385     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
386
387!
388! calcul albedo
389!
390       zfra = MAX(0.0,MIN(1.0,snow/(snow+10.0)))
391       DO ii = 1, knon
392         alb_neig = alb_neig_grid(knindex(ii))
393       enddo
394       alb_new = alb_neig*zfra + 0.6 * (1.0-zfra)
395
396  else if (nisurf == is_lic) then
397
398    if (check) write(*,*)'glacier, nisurf = ',nisurf
399
400!
401! Surface "glacier continentaux" appel a l'interface avec le sol
402!
403!    call interfsol(nisurf)
404
405    cal = calice
406    where (snow > 0.0) cal = calsno
407    beta = 1.0
408    dif_grnd = 0.0
409
410    call calcul_fluxs( klon, knon, nisurf, dtime, &
411     &   tsurf, p1lay, cal, beta, tq_cdrag, ps, &
412     &   precip_rain, precip_snow, snow, qsol,  &
413     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
414     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
415     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
416
417!
418! calcul albedo
419!
420       zfra = MAX(0.0,MIN(1.0,snow/(snow+10.0)))
421       DO ii =1, knon
422         alb_neig = alb_neig_grid(knindex(ii))
423       enddo
424       alb_new = alb_neig*zfra + 0.6 * (1.0-zfra)
425!
426! Remplissage des pourcentages de surface
427!
428    pctsrf_new(:,nisurf) = pctsrf(:,nisurf)
429
430  else
431    write(*,*)'Index surface = ',nisurf
432    abort_message = 'Index surface non valable'
433    call abort_gcm(modname,abort_message,1)
434  endif
435
436  END SUBROUTINE interfsurf_hq
437
438!
439!#########################################################################
440!
441  SUBROUTINE interfsurf_vent(nisurf, knon   &         
442  &                     )
443!
444! Cette routine sert d'aiguillage entre l'atmosphere et la surface en general
445! (sols continentaux, oceans, glaces) pour les tensions de vents.
446! En pratique l'interface se fait entre la couche limite du modele
447! atmospherique (clmain.F) et les routines de surface (sechiba, oasis, ...)
448!
449!
450! L.Fairhead 02/2000
451!
452! input:
453!   nisurf       index de la surface a traiter (1 = sol continental)
454!   knon         nombre de points de la surface a traiter
455
456! Parametres d'entree
457  integer, intent(IN) :: nisurf
458  integer, intent(IN) :: knon
459
460
461  return
462  END SUBROUTINE interfsurf_vent
463!
464!#########################################################################
465!
466  SUBROUTINE interfsol(itime, klon, dtime, nisurf, knon, &
467     & knindex, rlon, rlat, &
468     & debut, lafin, ok_veget, &
469     & zlev,  u1_lay, v1_lay, temp_air, spechum, hum_air, ccanopy, &
470     & tq_cdrag, petAcoef, peqAcoef, petBcoef, peqBcoef, &
471     & precip_rain, precip_snow, lwdown, swnet, swdown, &
472     & tsurf, p1lay, ps, radsol, &
473     & evap, fluxsens, fluxlat, &             
474     & tsol_rad, tsurf_new, alb_new, emis_new, z0_new, dflux_l, dflux_s)
475
476! Cette routine sert d'interface entre le modele atmospherique et le
477! modele de sol continental. Appel a sechiba
478!
479! L. Fairhead 02/2000
480!
481! input:
482!   itime        numero du pas de temps
483!   klon         nombre total de points de grille
484!   dtime        pas de temps de la physique (en s)
485!   nisurf       index de la surface a traiter (1 = sol continental)
486!   knon         nombre de points de la surface a traiter
487!   knindex      index des points de la surface a traiter
488!   rlon         longitudes de la grille entiere
489!   rlat         latitudes de la grille entiere
490!   debut        logical: 1er appel a la physique (lire les restart)
491!   lafin        logical: dernier appel a la physique (ecrire les restart)
492!   ok_veget     logical: appel ou non au schema de surface continental
493!                     (si false calcul simplifie des fluxs sur les continents)
494!   zlev         hauteur de la premiere couche       
495!   u1_lay       vitesse u 1ere couche
496!   v1_lay       vitesse v 1ere couche
497!   temp_air     temperature de l'air 1ere couche
498!   spechum      humidite specifique 1ere couche
499!   hum_air      humidite de l'air
500!   ccanopy      concentration CO2 canopee
501!   tq_cdrag     cdrag
502!   petAcoef     coeff. A de la resolution de la CL pour t
503!   peqAcoef     coeff. A de la resolution de la CL pour q
504!   petBcoef     coeff. B de la resolution de la CL pour t
505!   peqBcoef     coeff. B de la resolution de la CL pour q
506!   precip_rain  precipitation liquide
507!   precip_snow  precipitation solide
508!   lwdown       flux IR entrant a la surface
509!   swnet        flux solaire net
510!   swdown       flux solaire entrant a la surface
511!   tsurf        temperature de surface
512!   p1lay        pression 1er niveau (milieu de couche)
513!   ps           pression au sol
514!   radsol       rayonnement net aus sol (LW + SW)
515!   
516!
517! input/output
518!   run_off      ruissellement total
519!
520! output:
521!   evap         evaporation totale
522!   fluxsens     flux de chaleur sensible
523!   fluxlat      flux de chaleur latente
524!   tsol_rad     
525!   tsurf_new    temperature au sol
526!   alb_new      albedo
527!   emis_new     emissivite
528!   z0_new       surface roughness
529
530
531! Parametres d'entree
532  integer, intent(IN) :: itime
533  integer, intent(IN) :: klon
534  real, intent(IN)    :: dtime
535  integer, intent(IN) :: nisurf
536  integer, intent(IN) :: knon
537  integer, dimension(klon), intent(IN) :: knindex
538  logical, intent(IN) :: debut, lafin, ok_veget
539  real, dimension(klon), intent(IN) :: rlon, rlat
540  real, dimension(klon), intent(IN) :: zlev
541  real, dimension(klon), intent(IN) :: u1_lay, v1_lay
542  real, dimension(klon), intent(IN) :: temp_air, spechum
543  real, dimension(klon), intent(IN) :: hum_air, ccanopy
544  real, dimension(klon), intent(IN) :: tq_cdrag, petAcoef, peqAcoef
545  real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
546  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
547  real, dimension(klon), intent(IN) :: lwdown, swnet, swdown, ps
548  real, dimension(klon), intent(IN) :: tsurf, p1lay
549  real, dimension(klon), intent(IN) :: radsol
550! Parametres de sortie
551  real, dimension(klon), intent(OUT):: evap, fluxsens, fluxlat
552  real, dimension(klon), intent(OUT):: tsol_rad, tsurf_new, alb_new
553  real, dimension(klon), intent(OUT):: emis_new, z0_new
554  real, dimension(klon), intent(OUT):: dflux_s, dflux_l
555
556! Local
557!
558  integer              :: ii
559  integer              :: error
560  character (len = 20) :: modname = 'interfsol'
561  character (len = 80) :: abort_message
562  logical              :: check = .true.
563  real, dimension(klon) :: cal, beta, dif_grnd, capsol
564! type de couplage dans sechiba
565!  character (len=10)   :: coupling = 'implicit'
566! drapeaux controlant les appels dans SECHIBA
567!  type(control_type), save   :: control_in
568! coordonnees geographiques
569  real, allocatable, dimension(:,:), save :: lalo
570! pts voisins
571  integer,allocatable, dimension(:,:), save :: neighbours
572! resolution de la grille
573  real, allocatable, dimension (:,:), save :: resolution
574! Identifieurs des fichiers restart et histoire
575  integer, save          :: rest_id, hist_id
576  integer, save          :: rest_id_stom, hist_id_stom
577
578  real, dimension(klon):: snow, qsol
579
580  if (check) write(*,*)'Entree ', modname
581  if (check) write(*,*)'ok_veget = ',ok_veget
582
583! initialisation
584!    if (debut) then
585!      !
586!      ! Configuration de parametres specifiques a la SSL
587!      !
588!      call intsurf_config(control_in)
589!      !
590!      ! Allouer et initialiser le tableau de coordonnees du sol
591!      !
592!      if (( .not. allocated(lalo))) then
593!        allocate(lalo(knon,2), stat = error)
594!        if (error /= 0) then
595!          abort_message='Pb allocation lalo'
596!          call abort_gcm(modname,abort_message,1)
597!        endif     
598!      endif
599!      do ii = 1, knon
600!        lalo(ii,1) = rlat(knindex(ii))
601!        lalo(ii,2) = rlon(knindex(ii))
602!      enddo
603      !-
604      !- Compute variable to help describe the grid
605      !- once the points are gathered.
606      !-
607!      IF ( (.NOT.ALLOCATED(neighbours))) THEN
608!        ALLOCATE(neighbours(knon,4), stat = error)
609!        if (error /= 0) then
610!          abort_message='Pb allocation neighbours'
611!          call abort_gcm(modname,abort_message,1)
612!        endif
613!      ENDIF
614!      IF ( (.NOT.ALLOCATED(resolution))) THEN
615!        ALLOCATE(resolution(knon,2), stat = error)
616!        if (error /= 0) then
617!          abort_message='Pb allocation resolution'
618!          call abort_gcm(modname,abort_message,1)
619!        endif
620!      ENDIF
621
622! call grid_stuff
623! call sechiba_restart_init
624! call sechiba_history_init
625
626!    endif                          ! (fin debut)
627
628!
629! Appel a la routine sols continentaux
630!
631
632!    call sechiba_main(itime, klon, knon, knindex, dtime, &
633!     & debut, lafin, coupling, control_in, &
634!     & lalo, neighbours, resolution,&
635!     & zlev,  u1_lay, v1_lay, spechum, temp_air,hum_air , ccanopy, &
636!     & tq_cdrag, petAcoef, peqAcoef, petBcoef, peqBcoef, &
637!     & precip_rain, precip_snow, lwdown, swnet, swdown, ps, &
638!     & evap, fluxsens, fluxlat, &
639!     & tsol_rad, tsurf_new, alb_new, emis_new, z0_new, &
640!     & rest_id, hist_id, rest_id_stom, hist_id_stom)
641
642!
643! Sauvegarde dans fichiers histoire
644!
645
646  END SUBROUTINE interfsol
647!
648!#########################################################################
649!
650  SUBROUTINE interfoce_cpl(itime, dtime, &
651      & klon, iim, jjm, nisurf, pctsrf, knon, knindex, rlon, rlat, &
652      & ocean, npas, nexca, debut, lafin, &
653      & swdown, lwdown, precip_rain, precip_snow, evap, tsurf, &
654      & fder, albsol, taux, tauy, zmasq, &
655      & tsurf_new, alb_new, alb_ice, pctsrf_new)
656
657! Cette routine sert d'interface entre le modele atmospherique et un
658! coupleur avec un modele d'ocean 'complet' derriere
659!
660! Le modele de glace qu'il est prevu d'utiliser etant couple directement a
661! l'ocean presentement, on va passer deux fois dans cette routine par pas de
662! temps physique, une fois avec les points oceans et l'autre avec les points
663! glace. A chaque pas de temps de couplage, la lecture des champs provenant
664! du coupleur se fera "dans" l'ocean et l'ecriture des champs a envoyer
665! au coupleur "dans" la glace. Il faut donc des tableaux de travail "tampons"
666! dimensionnes sur toute la grille qui remplissent les champs sur les
667! domaines ocean/glace quand il le faut. Il est aussi necessaire que l'index
668! ocean soit traiter avant l'index glace (sinon tout intervertir)
669!
670!
671! L. Fairhead 02/2000
672!
673! input:
674!   itime        numero du pas de temps
675!   iim, jjm     nbres de pts de grille
676!   dtime        pas de tempsde la physique
677!   klon         nombre total de points de grille
678!   nisurf       index de la surface a traiter (1 = sol continental)
679!   pctsrf       tableau des fractions de surface de chaque maille
680!   knon         nombre de points de la surface a traiter
681!   knindex      index des points de la surface a traiter
682!   rlon         longitudes
683!   rlat         latitudes
684!   debut        logical: 1er appel a la physique
685!   lafin        logical: dernier appel a la physique
686!   ocean        type d'ocean
687!   nexca        frequence de couplage
688!   swdown       flux solaire entrant a la surface
689!   lwdown       flux IR entrant a la surface
690!   precip_rain  precipitation liquide
691!   precip_snow  precipitation solide
692!   evap         evaporation
693!   tsurf        temperature de surface
694!   fder         derivee dF/dT
695!   albsol       albedo du sol (coherent avec swdown)
696!   taux         tension de vent en x
697!   tauy         tension de vent en y
698!   nexca        frequence de couplage
699!   zmasq        masque terre/ocean
700!
701!
702! output:
703!   tsurf_new    temperature au sol
704!   alb_new      albedo
705!   pctsrf_new   nouvelle repartition des surfaces
706!   alb_ice      albedo de la glace
707!
708
709
710! Parametres d'entree
711  integer, intent(IN) :: itime
712  integer, intent(IN) :: iim, jjm
713  real, intent(IN) :: dtime
714  integer, intent(IN) :: klon
715  integer, intent(IN) :: nisurf
716  integer, intent(IN) :: knon
717  real, dimension(klon,nbsrf), intent(IN) :: pctsrf
718  integer, dimension(klon), intent(in) :: knindex
719  logical, intent(IN) :: debut, lafin
720  real, dimension(klon), intent(IN) :: rlon, rlat
721  character (len = 6)  :: ocean
722  real, dimension(klon), intent(IN) :: lwdown, swdown
723  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
724  real, dimension(klon), intent(IN) :: tsurf, fder, albsol, taux, tauy
725  INTEGER              :: nexca, npas, kstep
726  real, dimension(klon), intent(IN) :: zmasq
727
728  real, dimension(klon), intent(INOUT) :: evap
729
730! Parametres de sortie
731  real, dimension(klon), intent(OUT):: tsurf_new, alb_new, alb_ice
732  real, dimension(klon,nbsrf), intent(OUT) :: pctsrf_new
733
734! Variables locales
735  integer                    :: j, error, sum_error, ig, cpl_index,i
736  character (len = 20) :: modname = 'interfoce_cpl'
737  character (len = 80) :: abort_message
738  logical              :: check = .true.
739! variables pour moyenner les variables de couplage
740  real, allocatable, dimension(:,:),save :: cpl_sols, cpl_nsol, cpl_rain
741  real, allocatable, dimension(:,:),save :: cpl_snow, cpl_evap, cpl_tsol
742  real, allocatable, dimension(:,:),save :: cpl_fder, cpl_albe, cpl_taux
743  real, allocatable, dimension(:,:),save :: cpl_tauy, cpl_rriv, cpl_rcoa
744! variables tampons avant le passage au coupleur
745  real, allocatable, dimension(:,:,:),save :: tmp_sols, tmp_nsol, tmp_rain
746  real, allocatable, dimension(:,:,:),save :: tmp_snow, tmp_evap, tmp_tsol
747  real, allocatable, dimension(:,:,:),save :: tmp_fder, tmp_albe, tmp_taux
748  real, allocatable, dimension(:,:,:),save :: tmp_tauy, tmp_rriv, tmp_rcoa
749! variables a passer au coupleur
750  real, dimension(iim, jjm+1) :: wri_sol_ice, wri_sol_sea, wri_nsol_ice
751  real, dimension(iim, jjm+1) :: wri_nsol_sea, wri_fder_ice, wri_evap_ice
752  real, dimension(iim, jjm+1) :: wri_evap_sea
753  real, dimension(iim, jjm+1) :: wri_rain, wri_snow, wri_taux
754  real, dimension(iim, jjm+1) :: wri_tauy, wri_rriv, wri_rcoa
755! variables relues par le coupleur
756! read_sic = fraction de glace
757! read_sit = temperature de glace
758  real, allocatable, dimension(:,:),save :: read_sst, read_sic, read_sit
759  real, allocatable, dimension(:,:),save :: read_alb_sic
760! variable tampon
761  real, dimension(klon)       :: tamp
762  real, dimension(klon)       :: tamp_sic
763! sauvegarde des fractions de surface d'un pas de temps a l'autre apres
764! l'avoir lu
765  real, allocatable,dimension(:,:),save :: pctsrf_sav
766  real, dimension(iim, jjm+1, 2) :: tamp_srf
767  integer, allocatable, dimension(:), save :: tamp_ind
768  real, allocatable, dimension(:,:),save :: tamp_zmasq
769  real, dimension(iim, jjm+1) :: deno
770  integer                     :: idtime
771  integer, allocatable, dimension(:,:) :: isst
772  integer, allocatable,save,dimension(:) :: unity
773!
774  logical, save    :: first_appel = .true.
775  logical          :: print
776
777!
778! Initialisation
779!
780  if (check) write(*,*)'Entree ',modname,'nisurf = ',nisurf
781 
782  if (first_appel) then
783    error = 0
784    allocate(unity(klon), stat = error)
785    if ( error  /=0) then
786      abort_message='Pb allocation variable unity'
787      call abort_gcm(modname,abort_message,1)
788    endif
789    allocate(pctsrf_sav(klon,nbsrf), stat = error)
790    if ( error  /=0) then
791      abort_message='Pb allocation variable pctsrf_sav'
792      call abort_gcm(modname,abort_message,1)
793    endif
794    pctsrf_sav = 0.
795
796    do ig = 1, klon
797      unity(ig) = ig
798    enddo
799    sum_error = 0
800    allocate(cpl_sols(klon,2), stat = error); sum_error = sum_error + error
801    allocate(cpl_nsol(klon,2), stat = error); sum_error = sum_error + error
802    allocate(cpl_rain(klon,2), stat = error); sum_error = sum_error + error
803    allocate(cpl_snow(klon,2), stat = error); sum_error = sum_error + error
804    allocate(cpl_evap(klon,2), stat = error); sum_error = sum_error + error
805    allocate(cpl_tsol(klon,2), stat = error); sum_error = sum_error + error
806    allocate(cpl_fder(klon,2), stat = error); sum_error = sum_error + error
807    allocate(cpl_albe(klon,2), stat = error); sum_error = sum_error + error
808    allocate(cpl_taux(klon,2), stat = error); sum_error = sum_error + error
809    allocate(cpl_tauy(klon,2), stat = error); sum_error = sum_error + error
810    allocate(cpl_rcoa(klon,2), stat = error); sum_error = sum_error + error
811    allocate(cpl_rriv(klon,2), stat = error); sum_error = sum_error + error
812    allocate(read_sst(iim, jjm+1), stat = error); sum_error = sum_error + error
813    allocate(read_sic(iim, jjm+1), stat = error); sum_error = sum_error + error
814    allocate(read_sit(iim, jjm+1), stat = error); sum_error = sum_error + error
815    allocate(read_alb_sic(iim, jjm+1), stat = error); sum_error = sum_error + error
816
817    if (sum_error /= 0) then
818      abort_message='Pb allocation variables couplees'
819      call abort_gcm(modname,abort_message,1)
820    endif
821    cpl_sols = 0.; cpl_nsol = 0.; cpl_rain = 0.; cpl_snow = 0.
822    cpl_evap = 0.; cpl_tsol = 0.; cpl_fder = 0.; cpl_albe = 0.
823    cpl_taux = 0.; cpl_tauy = 0.; cpl_rriv = 0.; cpl_rcoa = 0.
824
825    sum_error = 0
826    allocate(tamp_ind(klon), stat = error); sum_error = sum_error + error
827    allocate(tamp_zmasq(iim, jjm+1), stat = error); sum_error = sum_error + error   
828    do ig = 1, klon
829      tamp_ind(ig) = ig
830    enddo
831    call gath2cpl(zmasq, tamp_zmasq, klon, klon, iim, jjm, tamp_ind)
832!
833! initialisation couplage
834!
835    idtime = int(dtime)
836    call inicma(npas , nexca, idtime,(jjm+1)*iim)
837
838    first_appel = .false.
839  endif ! fin if (first_appel)
840
841! fichier restart et fichiers histoires
842
843! calcul des fluxs a passer
844
845  cpl_index = 1
846  if (nisurf == is_sic) cpl_index = 2
847  do ig = 1, knon
848    cpl_sols(ig,cpl_index) = cpl_sols(ig,cpl_index) &
849     &                               + swdown(ig)      / FLOAT(nexca)
850    cpl_nsol(ig,cpl_index) = cpl_nsol(ig,cpl_index) &
851     &                               + lwdown(ig)      / FLOAT(nexca)
852    cpl_rain(ig,cpl_index) = cpl_rain(ig,cpl_index) &
853     &                               + precip_rain(ig) / FLOAT(nexca)
854    cpl_snow(ig,cpl_index) = cpl_snow(ig,cpl_index) &
855     &                               + precip_snow(ig) / FLOAT(nexca)
856    cpl_evap(ig,cpl_index) = cpl_evap(ig,cpl_index) &
857     &                               + evap(ig)        / FLOAT(nexca)
858    cpl_tsol(ig,cpl_index) = cpl_tsol(ig,cpl_index) &
859     &                               + tsurf(ig)       / FLOAT(nexca)
860    cpl_fder(ig,cpl_index) = cpl_fder(ig,cpl_index) &
861     &                               + fder(ig)        / FLOAT(nexca)
862    cpl_albe(ig,cpl_index) = cpl_albe(ig,cpl_index) &
863     &                               + albsol(ig)      / FLOAT(nexca)
864    cpl_taux(ig,cpl_index) = cpl_taux(ig,cpl_index) &
865     &                               + taux(ig)        / FLOAT(nexca)
866    cpl_tauy(ig,cpl_index) = cpl_tauy(ig,cpl_index) &
867     &                               + tauy(ig)        / FLOAT(nexca)
868    cpl_rriv(ig,cpl_index) = cpl_rriv(ig,cpl_index) &
869     &                               + 0.     / FLOAT(nexca)/dtime
870    cpl_rcoa(ig,cpl_index) = cpl_rcoa(ig,cpl_index) &
871     &                               + 0.     / FLOAT(nexca)/dtime
872  enddo
873
874  if (mod(itime, nexca) == 1) then
875!
876! Passage des champs au coupleur
877!
878! Si le domaine considere est l'ocean, on lit les champs venant du coupleur
879!
880    if (nisurf == is_oce) then
881      if (check) write(*,*)'rentree fromcpl, itime-1 = ',itime-1
882      call fromcpl(itime-1,(jjm+1)*iim,                                  &
883     &        read_sst, read_sic, read_sit, read_alb_sic)
884      do j = 1, jjm + 1
885        do ig = 1, iim
886          if (abs(1. - read_sic(ig,j)) < 0.00001) then
887            read_sst(ig,j) = RTT - 1.8
888            read_sit(ig,j) = read_sit(ig,j) / read_sic(ig,j)
889            read_alb_sic(ig,j) = read_alb_sic(ig,j) / read_sic(ig,j)
890          else if (abs(read_sic(ig,j)) < 0.00001) then
891            read_sst(ig,j) = read_sst(ig,j) / (1. - read_sic(ig,j))
892            read_sit(ig,j) = read_sst(ig,j)
893            read_alb_sic(ig,j) =  0.6
894          else
895            read_sst(ig,j) = read_sst(ig,j) / (1. - read_sic(ig,j))
896            read_sit(ig,j) = read_sit(ig,j) / read_sic(ig,j)
897            read_alb_sic(ig,j) = read_alb_sic(ig,j) / read_sic(ig,j)
898          endif
899        enddo
900      enddo
901!
902! transformer read_sic en pctsrf_sav
903!
904    call cpl2gath(read_sic, tamp_sic , klon, klon,iim,jjm, unity)
905    do ig = 1, klon
906      IF (pctsrf(ig,is_oce) > epsfra .OR.            &
907     &             pctsrf(ig,is_sic) > epsfra) THEN
908          pctsrf_sav(ig,is_sic) = (pctsrf(ig,is_oce) + pctsrf(ig,is_sic)) &
909     &                               * tamp_sic(ig)
910          pctsrf_sav(ig,is_oce) = (pctsrf(ig,is_oce) + pctsrf(ig,is_sic)) &
911     &                        - pctsrf_sav(ig,is_sic)
912        endif
913      enddo
914      if (check) then
915        write(46,*)'pct_srf_sav_ice = '
916        write(46,'(72f8.3)')pctsrf_sav(:,is_sic)
917      endif
918      if (minval(pctsrf_new(:,is_oce)) < 0.) then
919        write(*,*)'Pb fraction ocean inferieure a 0'
920        write(*,*)'au point ',minloc(pctsrf_new(:,is_oce))
921        write(*,*)'valeur = ',minval(pctsrf_new(:,is_oce))
922        abort_message = 'voir ci-dessus'
923        call abort_gcm(modname,abort_message,1)
924      endif
925      if (minval(pctsrf_new(:,is_sic)) < 0.) then
926        write(*,*)'Pb fraction glace inferieure a 0'
927        write(*,*)'au point ',minloc(pctsrf_new(:,is_sic))
928        write(*,*)'valeur = ',minval(pctsrf_new(:,is_sic))
929        abort_message = 'voir ci-dessus'
930        call abort_gcm(modname,abort_message,1)
931      endif
932    endif
933  endif                         ! fin mod(itime, nexca) == 1
934
935  if (mod(itime, nexca) == 0) then
936!
937! allocation memoire
938    if (nisurf == is_oce) then
939      sum_error = 0
940      allocate(tmp_sols(iim,jjm+1,2), stat=error); sum_error = sum_error + error
941      allocate(tmp_nsol(iim,jjm+1,2), stat=error); sum_error = sum_error + error
942      allocate(tmp_rain(iim,jjm+1,2), stat=error); sum_error = sum_error + error
943      allocate(tmp_snow(iim,jjm+1,2), stat=error); sum_error = sum_error + error
944      allocate(tmp_evap(iim,jjm+1,2), stat=error); sum_error = sum_error + error
945      allocate(tmp_tsol(iim,jjm+1,2), stat=error); sum_error = sum_error + error
946      allocate(tmp_fder(iim,jjm+1,2), stat=error); sum_error = sum_error + error
947      allocate(tmp_albe(iim,jjm+1,2), stat=error); sum_error = sum_error + error
948      allocate(tmp_taux(iim,jjm+1,2), stat=error); sum_error = sum_error + error
949      allocate(tmp_tauy(iim,jjm+1,2), stat=error); sum_error = sum_error + error
950      allocate(tmp_rriv(iim,jjm+1,2), stat=error); sum_error = sum_error + error
951      allocate(tmp_rcoa(iim,jjm+1,2), stat=error); sum_error = sum_error + error
952      if (sum_error /= 0) then
953        abort_message='Pb allocation variables couplees pour l''ecriture'
954        call abort_gcm(modname,abort_message,1)
955      endif
956    endif
957
958!
959! Mise sur la bonne grille des champs a passer au coupleur
960!
961    cpl_index = 1
962    if (nisurf == is_sic) cpl_index = 2
963    call gath2cpl(cpl_sols(1,cpl_index), tmp_sols(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
964    call gath2cpl(cpl_nsol(1,cpl_index), tmp_nsol(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
965    call gath2cpl(cpl_rain(1,cpl_index), tmp_rain(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
966    call gath2cpl(cpl_snow(1,cpl_index), tmp_snow(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
967    call gath2cpl(cpl_evap(1,cpl_index), tmp_evap(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
968    call gath2cpl(cpl_tsol(1,cpl_index), tmp_tsol(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
969    call gath2cpl(cpl_fder(1,cpl_index), tmp_fder(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
970    call gath2cpl(cpl_albe(1,cpl_index), tmp_albe(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
971    call gath2cpl(cpl_taux(1,cpl_index), tmp_taux(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
972    call gath2cpl(cpl_tauy(1,cpl_index), tmp_tauy(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
973    call gath2cpl(cpl_rriv(1,cpl_index), tmp_rriv(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
974    call gath2cpl(cpl_rcoa(1,cpl_index), tmp_rcoa(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
975
976!
977! Si le domaine considere est la banquise, on envoie les champs au coupleur
978!
979    if (nisurf == is_sic) then
980      wri_rain = 0.; wri_snow = 0.; wri_rcoa = 0.; wri_rriv = 0.
981      wri_taux = 0.; wri_tauy = 0.
982      call gath2cpl(pctsrf(1,is_oce), tamp_srf(1,1,1), klon, klon, iim, jjm, tamp_ind)
983      call gath2cpl(pctsrf(1,is_sic), tamp_srf(1,1,2), klon, klon, iim, jjm, tamp_ind)
984
985      wri_sol_ice = tmp_sols(:,:,2)
986      wri_sol_sea = tmp_sols(:,:,1)
987      wri_nsol_ice = tmp_nsol(:,:,2)
988      wri_nsol_sea = tmp_nsol(:,:,1)
989      wri_fder_ice = tmp_fder(:,:,2)
990      wri_evap_ice = tmp_evap(:,:,2)
991      wri_evap_sea = tmp_evap(:,:,1)
992      where (tamp_zmasq /= 1.)
993        deno =  tamp_srf(:,:,1) + tamp_srf(:,:,2)
994        wri_rain = tmp_rain(:,:,1) * tamp_srf(:,:,1) / deno +    &
995      &            tmp_rain(:,:,2) * tamp_srf(:,:,2) / deno
996        wri_snow = tmp_snow(:,:,1) * tamp_srf(:,:,1) / deno +    &
997      &            tmp_snow(:,:,2) * tamp_srf(:,:,2) / deno
998        wri_rriv = tmp_rriv(:,:,1) * tamp_srf(:,:,1) / deno +    &
999      &            tmp_rriv(:,:,2) * tamp_srf(:,:,2) / deno
1000        wri_rcoa = tmp_rcoa(:,:,1) * tamp_srf(:,:,1) / deno +    &
1001      &            tmp_rcoa(:,:,2) * tamp_srf(:,:,2) / deno
1002        wri_taux = tmp_taux(:,:,1) * tamp_srf(:,:,1) / deno +    &
1003      &            tmp_taux(:,:,2) * tamp_srf(:,:,2) / deno
1004        wri_tauy = tmp_tauy(:,:,1) * tamp_srf(:,:,1) / deno +    &
1005      &            tmp_tauy(:,:,2) * tamp_srf(:,:,2) / deno
1006      endwhere
1007
1008      call intocpl(itime, (jjm+1)*iim, wri_sol_ice, wri_sol_sea, wri_nsol_ice,&
1009      & wri_nsol_sea, wri_fder_ice, wri_evap_ice, wri_evap_sea, wri_rain, &
1010      & wri_snow, wri_rcoa, wri_rriv, wri_taux, wri_tauy, wri_taux, wri_tauy, &
1011      & lafin )
1012      cpl_sols = 0.; cpl_nsol = 0.; cpl_rain = 0.; cpl_snow = 0.
1013      cpl_evap = 0.; cpl_tsol = 0.; cpl_fder = 0.; cpl_albe = 0.
1014      cpl_taux = 0.; cpl_tauy = 0.; cpl_rriv = 0.; cpl_rcoa = 0.
1015!
1016! deallocation memoire variables temporaires
1017!
1018      sum_error = 0
1019      deallocate(tmp_sols, stat=error); sum_error = sum_error + error
1020      deallocate(tmp_nsol, stat=error); sum_error = sum_error + error
1021      deallocate(tmp_rain, stat=error); sum_error = sum_error + error
1022      deallocate(tmp_snow, stat=error); sum_error = sum_error + error
1023      deallocate(tmp_evap, stat=error); sum_error = sum_error + error
1024      deallocate(tmp_fder, stat=error); sum_error = sum_error + error
1025      deallocate(tmp_tsol, stat=error); sum_error = sum_error + error
1026      deallocate(tmp_albe, stat=error); sum_error = sum_error + error
1027      deallocate(tmp_taux, stat=error); sum_error = sum_error + error
1028      deallocate(tmp_tauy, stat=error); sum_error = sum_error + error
1029      deallocate(tmp_rriv, stat=error); sum_error = sum_error + error
1030      deallocate(tmp_rcoa, stat=error); sum_error = sum_error + error
1031      if (sum_error /= 0) then
1032        abort_message='Pb deallocation variables couplees'
1033        call abort_gcm(modname,abort_message,1)
1034      endif
1035
1036    endif
1037
1038  endif            ! fin (mod(itime, nexca) == 0)
1039!
1040! on range les variables lues/sauvegardees dans les bonnes variables de sortie
1041!
1042  if (nisurf == is_oce) then
1043    call cpl2gath(read_sst, tsurf_new, klon, knon,iim,jjm, knindex)
1044  else if (nisurf == is_sic) then
1045    call cpl2gath(read_sit, tsurf_new, klon, knon,iim,jjm, knindex)
1046    call cpl2gath(read_alb_sic, alb_new, klon, knon,iim,jjm, knindex)
1047  endif
1048  pctsrf_new(:,nisurf) = pctsrf_sav(:,nisurf)
1049 
1050!  if (lafin) call quitcpl
1051
1052  END SUBROUTINE interfoce_cpl
1053!
1054!#########################################################################
1055!
1056
1057  SUBROUTINE interfoce_slab(nisurf)
1058
1059! Cette routine sert d'interface entre le modele atmospherique et un
1060! modele de 'slab' ocean
1061!
1062! L. Fairhead 02/2000
1063!
1064! input:
1065!   nisurf       index de la surface a traiter (1 = sol continental)
1066!
1067! output:
1068!
1069
1070! Parametres d'entree
1071  integer, intent(IN) :: nisurf
1072
1073  END SUBROUTINE interfoce_slab
1074!
1075!#########################################################################
1076!
1077  SUBROUTINE interfoce_lim(itime, dtime, jour, &
1078     & klon, nisurf, knon, knindex, &
1079     & debut,  &
1080     & lmt_sst, pctsrf_new)
1081
1082! Cette routine sert d'interface entre le modele atmospherique et un fichier
1083! de conditions aux limites
1084!
1085! L. Fairhead 02/2000
1086!
1087! input:
1088!   itime        numero du pas de temps courant
1089!   dtime        pas de temps de la physique (en s)
1090!   jour         jour a lire dans l'annee
1091!   nisurf       index de la surface a traiter (1 = sol continental)
1092!   knon         nombre de points dans le domaine a traiter
1093!   knindex      index des points de la surface a traiter
1094!   klon         taille de la grille
1095!   debut        logical: 1er appel a la physique (initialisation)
1096!
1097! output:
1098!   lmt_sst      SST lues dans le fichier de CL
1099!   pctsrf_new   sous-maille fractionnelle
1100!
1101
1102
1103! Parametres d'entree
1104  integer, intent(IN) :: itime
1105  real   , intent(IN) :: dtime
1106  integer, intent(IN) :: jour
1107  integer, intent(IN) :: nisurf
1108  integer, intent(IN) :: knon
1109  integer, intent(IN) :: klon
1110  integer, dimension(klon), intent(in) :: knindex
1111  logical, intent(IN) :: debut
1112
1113! Parametres de sortie
1114  real, intent(out), dimension(klon) :: lmt_sst
1115  real, intent(out), dimension(klon,nbsrf) :: pctsrf_new
1116
1117! Variables locales
1118  integer     :: ii
1119  INTEGER,save :: lmt_pas     ! frequence de lecture des conditions limites
1120                             ! (en pas de physique)
1121  logical,save :: deja_lu    ! pour indiquer que le jour a lire a deja
1122                             ! lu pour une surface precedente
1123  integer,save :: jour_lu
1124  integer      :: ierr
1125  character (len = 20) :: modname = 'interfoce_lim'
1126  character (len = 80) :: abort_message
1127  character (len = 20) :: fich ='limit.nc'
1128  LOGICAL     :: newlmt = .TRUE.
1129  logical     :: check = .true.
1130! Champs lus dans le fichier de CL
1131  real, allocatable , save, dimension(:) :: sst_lu, rug_lu, nat_lu
1132  real, allocatable , save, dimension(:,:) :: pct_tmp
1133!
1134! quelques variables pour netcdf
1135!
1136#include "netcdf.inc"
1137  integer              :: nid, nvarid
1138  integer, dimension(2) :: start, epais
1139!
1140! Fin déclaration
1141!
1142   
1143  if (debut .and. .not. allocated(sst_lu)) then
1144    lmt_pas = nint(86400./dtime * 1.0) ! pour une lecture une fois par jour
1145    jour_lu = jour - 1
1146    allocate(sst_lu(klon))
1147    allocate(nat_lu(klon))
1148    allocate(pct_tmp(klon,nbsrf))
1149  endif
1150
1151  if ((jour - jour_lu) /= 0) deja_lu = .false.
1152 
1153  if (check) write(*,*)modname,' :: jour_lu, deja_lu', jour_lu, deja_lu
1154  if (check) write(*,*)modname,' :: itime, lmt_pas ', itime, lmt_pas,dtime
1155
1156! Tester d'abord si c'est le moment de lire le fichier
1157  if (mod(itime-1, lmt_pas) == 0 .and. .not. deja_lu) then
1158!
1159! Ouverture du fichier
1160!
1161    fich = trim(fich)
1162    ierr = NF_OPEN (fich, NF_NOWRITE,nid)
1163    if (ierr.NE.NF_NOERR) then
1164      abort_message = 'Pb d''ouverture du fichier de conditions aux limites'
1165      call abort_gcm(modname,abort_message,1)
1166    endif
1167!
1168! La tranche de donnees a lire:
1169!
1170    start(1) = 1
1171    start(2) = jour + 1
1172    epais(1) = klon
1173    epais(2) = 1
1174!
1175    if (newlmt) then
1176!
1177! Fraction "ocean"
1178!
1179      ierr = NF_INQ_VARID(nid, 'FOCE', nvarid)
1180      if (ierr /= NF_NOERR) then
1181        abort_message = 'Le champ <FOCE> est absent'
1182        call abort_gcm(modname,abort_message,1)
1183      endif
1184#ifdef NC_DOUBLE
1185      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais,pct_tmp(1,is_oce))
1186#else
1187      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais,pct_tmp(1,is_oce))
1188#endif
1189      if (ierr /= NF_NOERR) then
1190        abort_message = 'Lecture echouee pour <FOCE>'
1191        call abort_gcm(modname,abort_message,1)
1192      endif
1193!
1194! Fraction "glace de mer"
1195!
1196      ierr = NF_INQ_VARID(nid, 'FSIC', nvarid)
1197      if (ierr /= NF_NOERR) then
1198        abort_message = 'Le champ <FSIC> est absent'
1199        call abort_gcm(modname,abort_message,1)
1200      endif
1201#ifdef NC_DOUBLE
1202      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais,pct_tmp(1,is_sic))
1203#else
1204      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais,pct_tmp(1,is_sic))
1205#endif
1206      if (ierr /= NF_NOERR) then
1207        abort_message = 'Lecture echouee pour <FSIC>'
1208        call abort_gcm(modname,abort_message,1)
1209      endif
1210!
1211! Fraction "terre"
1212!
1213      ierr = NF_INQ_VARID(nid, 'FTER', nvarid)
1214      if (ierr /= NF_NOERR) then
1215        abort_message = 'Le champ <FTER> est absent'
1216        call abort_gcm(modname,abort_message,1)
1217      endif
1218#ifdef NC_DOUBLE
1219      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais,pct_tmp(1,is_ter))
1220#else
1221      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais,pct_tmp(1,is_ter))
1222#endif
1223      if (ierr /= NF_NOERR) then
1224        abort_message = 'Lecture echouee pour <FTER>'
1225        call abort_gcm(modname,abort_message,1)
1226      endif
1227!
1228! Fraction "glacier terre"
1229!
1230      ierr = NF_INQ_VARID(nid, 'FLIC', nvarid)
1231      if (ierr /= NF_NOERR) then
1232        abort_message = 'Le champ <FLIC> est absent'
1233        call abort_gcm(modname,abort_message,1)
1234      endif
1235#ifdef NC_DOUBLE
1236      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais,pct_tmp(1,is_lic))
1237#else
1238      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais,pct_tmp(1,is_lic))
1239#endif
1240      if (ierr /= NF_NOERR) then
1241        abort_message = 'Lecture echouee pour <FLIC>'
1242        call abort_gcm(modname,abort_message,1)
1243      endif
1244!
1245    else  ! on en est toujours a rnatur
1246!
1247      ierr = NF_INQ_VARID(nid, 'NAT', nvarid)
1248      if (ierr /= NF_NOERR) then
1249        abort_message = 'Le champ <NAT> est absent'
1250        call abort_gcm(modname,abort_message,1)
1251      endif
1252#ifdef NC_DOUBLE
1253      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais, nat_lu)
1254#else
1255      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais, nat_lu)
1256#endif
1257      if (ierr /= NF_NOERR) then
1258        abort_message = 'Lecture echouee pour <NAT>'
1259        call abort_gcm(modname,abort_message,1)
1260      endif
1261!
1262! Remplissage des fractions de surface
1263! nat = 0, 1, 2, 3 pour ocean, terre, glacier, seaice
1264!
1265      pct_tmp = 0.0
1266      do ii = 1, klon
1267        pct_tmp(ii,nint(nat_lu(ii)) + 1) = 1.
1268      enddo
1269
1270!
1271!  On se retrouve avec ocean en 1 et terre en 2 alors qu'on veut le contraire
1272!
1273      pctsrf_new = pct_tmp
1274      pctsrf_new (:,2)= pct_tmp (:,1)
1275      pctsrf_new (:,1)= pct_tmp (:,2)
1276      pct_tmp = pctsrf_new
1277    endif ! fin test sur newlmt
1278!
1279! Lecture SST
1280!
1281    ierr = NF_INQ_VARID(nid, 'SST', nvarid)
1282    if (ierr /= NF_NOERR) then
1283      abort_message = 'Le champ <SST> est absent'
1284      call abort_gcm(modname,abort_message,1)
1285    endif
1286#ifdef NC_DOUBLE
1287    ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais, sst_lu)
1288#else
1289    ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais, sst_lu)
1290#endif
1291    if (ierr /= NF_NOERR) then
1292      abort_message = 'Lecture echouee pour <SST>'
1293      call abort_gcm(modname,abort_message,1)
1294    endif   
1295
1296!
1297! Fin de lecture
1298!
1299    ierr = NF_CLOSE(nid)
1300    deja_lu = .true.
1301    jour_lu = jour
1302  endif
1303!
1304! Recopie des variables dans les champs de sortie
1305!
1306  do ii = 1, knon
1307    lmt_sst(ii) = sst_lu(knindex(ii))
1308  enddo
1309! je peux pas utiliser la ligne suivante a cause du compilo Sun
1310!  lmt_sst = sst_lu(knindex)
1311  pctsrf_new = pct_tmp
1312
1313  END SUBROUTINE interfoce_lim
1314
1315!
1316!#########################################################################
1317!
1318  SUBROUTINE interfsur_lim(itime, dtime, jour, &
1319     & klon, nisurf, knon, knindex, &
1320     & debut,  &
1321     & lmt_alb, lmt_rug)
1322
1323! Cette routine sert d'interface entre le modele atmospherique et un fichier
1324! de conditions aux limites
1325!
1326! L. Fairhead 02/2000
1327!
1328! input:
1329!   itime        numero du pas de temps courant
1330!   dtime        pas de temps de la physique (en s)
1331!   jour         jour a lire dans l'annee
1332!   nisurf       index de la surface a traiter (1 = sol continental)
1333!   knon         nombre de points dans le domaine a traiter
1334!   knindex      index des points de la surface a traiter
1335!   klon         taille de la grille
1336!   debut        logical: 1er appel a la physique (initialisation)
1337!
1338! output:
1339!   lmt_sst      SST lues dans le fichier de CL
1340!   lmt_alb      Albedo lu
1341!   lmt_rug      longueur de rugosité lue
1342!   pctsrf_new   sous-maille fractionnelle
1343!
1344
1345
1346! Parametres d'entree
1347  integer, intent(IN) :: itime
1348  real   , intent(IN) :: dtime
1349  integer, intent(IN) :: jour
1350  integer, intent(IN) :: nisurf
1351  integer, intent(IN) :: knon
1352  integer, intent(IN) :: klon
1353  integer, dimension(klon), intent(in) :: knindex
1354  logical, intent(IN) :: debut
1355
1356! Parametres de sortie
1357  real, intent(out), dimension(klon) :: lmt_alb
1358  real, intent(out), dimension(klon) :: lmt_rug
1359
1360! Variables locales
1361  integer     :: ii
1362  integer,save :: lmt_pas     ! frequence de lecture des conditions limites
1363                             ! (en pas de physique)
1364  logical,save :: deja_lu_sur! pour indiquer que le jour a lire a deja
1365                             ! lu pour une surface precedente
1366  integer,save :: jour_lu_sur
1367  integer      :: ierr
1368  character (len = 20) :: modname = 'interfsur_lim'
1369  character (len = 80) :: abort_message
1370  character (len = 20) :: fich ='limit.nc'
1371  logical     :: newlmt = .false.
1372  logical     :: check = .true.
1373! Champs lus dans le fichier de CL
1374  real, allocatable , save, dimension(:) :: alb_lu, rug_lu
1375!
1376! quelques variables pour netcdf
1377!
1378#include "netcdf.inc"
1379  integer              :: nid, nvarid
1380  integer, dimension(2) :: start, epais
1381!
1382! Fin déclaration
1383!
1384   
1385  if (debut) then
1386    lmt_pas = nint(86400./dtime * 1.0) ! pour une lecture une fois par jour
1387    jour_lu_sur = jour - 1
1388    allocate(alb_lu(klon))
1389    allocate(rug_lu(klon))
1390  endif
1391
1392  if ((jour - jour_lu_sur) /= 0) deja_lu_sur = .false.
1393 
1394  if (check) write(*,*)modname,':: jour_lu_sur, deja_lu_sur', jour_lu_sur, deja_lu_sur
1395  if (check) write(*,*)modname,':: itime, lmt_pas', itime, lmt_pas
1396  call flush(6)
1397
1398! Tester d'abord si c'est le moment de lire le fichier
1399  if (mod(itime-1, lmt_pas) == 0 .and. .not. deja_lu_sur) then
1400!
1401! Ouverture du fichier
1402!
1403    fich = trim(fich)
1404    ierr = NF_OPEN (fich, NF_NOWRITE,nid)
1405    if (ierr.NE.NF_NOERR) then
1406      abort_message = 'Pb d''ouverture du fichier de conditions aux limites'
1407      call abort_gcm(modname,abort_message,1)
1408    endif
1409!
1410! La tranche de donnees a lire:
1411 
1412    start(1) = 1
1413    start(2) = jour + 1
1414    epais(1) = klon
1415    epais(2) = 1
1416!
1417! Lecture Albedo
1418!
1419    ierr = NF_INQ_VARID(nid, 'ALB', nvarid)
1420    if (ierr /= NF_NOERR) then
1421      abort_message = 'Le champ <ALB> est absent'
1422      call abort_gcm(modname,abort_message,1)
1423    endif
1424#ifdef NC_DOUBLE
1425    ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais, alb_lu)
1426#else
1427    ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais, alb_lu)
1428#endif
1429    if (ierr /= NF_NOERR) then
1430      abort_message = 'Lecture echouee pour <ALB>'
1431      call abort_gcm(modname,abort_message,1)
1432    endif
1433!
1434! Lecture rugosité
1435!
1436    ierr = NF_INQ_VARID(nid, 'RUG', nvarid)
1437    if (ierr /= NF_NOERR) then
1438      abort_message = 'Le champ <RUG> est absent'
1439      call abort_gcm(modname,abort_message,1)
1440    endif
1441#ifdef NC_DOUBLE
1442    ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais, rug_lu)
1443#else
1444    ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais, rug_lu)
1445#endif
1446    if (ierr /= NF_NOERR) then
1447      abort_message = 'Lecture echouee pour <RUG>'
1448      call abort_gcm(modname,abort_message,1)
1449    endif
1450
1451!
1452! Fin de lecture
1453!
1454    ierr = NF_CLOSE(nid)
1455    deja_lu_sur = .true.
1456    jour_lu_sur = jour
1457  endif
1458!
1459! Recopie des variables dans les champs de sortie
1460!
1461  DO ii = 1, knon
1462    lmt_alb(ii) = alb_lu(knindex(ii))
1463    lmt_rug(ii) = rug_lu(knindex(ii))
1464  enddo
1465
1466  END SUBROUTINE interfsur_lim
1467
1468!
1469!#########################################################################
1470!
1471
1472  SUBROUTINE calcul_fluxs( klon, knon, nisurf, dtime, &
1473     & tsurf, p1lay, cal, beta, coef1lay, ps, &
1474     & precip_rain, precip_snow, snow, qsol, &
1475     & radsol, dif_grnd, t1lay, q1lay, u1lay, v1lay, &
1476     & petAcoef, peqAcoef, petBcoef, peqBcoef, &
1477     & tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
1478
1479! Cette routine calcule les fluxs en h et q a l'interface et eventuellement
1480! une temperature de surface (au cas ou ok_veget = false)
1481!
1482! L. Fairhead 4/2000
1483!
1484! input:
1485!   knon         nombre de points a traiter
1486!   nisurf       surface a traiter
1487!   tsurf        temperature de surface
1488!   p1lay        pression 1er niveau (milieu de couche)
1489!   cal          capacite calorifique du sol
1490!   beta         evap reelle
1491!   coef1lay     coefficient d'echange
1492!   ps           pression au sol
1493!   precip_rain  precipitations liquides
1494!   precip_snow  precipitations solides
1495!   snow         champs hauteur de neige
1496!   qsol         humidite du sol
1497!   runoff       runoff en cas de trop plein
1498!   petAcoef     coeff. A de la resolution de la CL pour t
1499!   peqAcoef     coeff. A de la resolution de la CL pour q
1500!   petBcoef     coeff. B de la resolution de la CL pour t
1501!   peqBcoef     coeff. B de la resolution de la CL pour q
1502!   radsol       rayonnement net aus sol (LW + SW)
1503!   dif_grnd     coeff. diffusion vers le sol profond
1504!
1505! output:
1506!   tsurf_new    temperature au sol
1507!   fluxsens     flux de chaleur sensible
1508!   fluxlat      flux de chaleur latente
1509!   dflux_s      derivee du flux de chaleur sensible / Ts
1510!   dflux_l      derivee du flux de chaleur latente  / Ts
1511!
1512
1513#include "YOETHF.inc"
1514#include "FCTTRE.inc"
1515
1516! Parametres d'entree
1517  integer, intent(IN) :: knon, nisurf, klon
1518  real   , intent(IN) :: dtime
1519  real, dimension(klon), intent(IN) :: petAcoef, peqAcoef
1520  real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
1521  real, dimension(klon), intent(IN) :: ps, q1lay
1522  real, dimension(klon), intent(IN) :: tsurf, p1lay, cal, beta, coef1lay
1523  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
1524  real, dimension(klon), intent(IN) :: radsol, dif_grnd
1525  real, dimension(klon), intent(IN) :: t1lay, u1lay, v1lay
1526  real, dimension(klon), intent(INOUT) :: snow, qsol
1527
1528! Parametres sorties
1529  real, dimension(klon), intent(OUT):: tsurf_new, evap, fluxsens, fluxlat
1530  real, dimension(klon), intent(OUT):: dflux_s, dflux_l
1531
1532! Variables locales
1533  integer :: i
1534  real, dimension(klon) :: zx_mh, zx_nh, zx_oh
1535  real, dimension(klon) :: zx_mq, zx_nq, zx_oq
1536  real, dimension(klon) :: zx_pkh, zx_dq_s_dt, zx_qsat, zx_coef
1537  real, dimension(klon) :: zx_sl, zx_k1,  zx_dq,  zx_cq,  zx_dh, zx_ch
1538  real, dimension(klon) :: zx_h_ts, zx_q_0 , d_ts
1539  real                  :: zdelta, zcvm5, zx_qs, zcor, zx_dq_s_dh
1540  real                  :: bilan_f, fq_fonte
1541  real, parameter :: t_grnd = 271.35, t_coup = 273.15
1542  logical         :: check = .false.
1543  character (len = 20)  :: modname = 'calcul_fluxs'
1544  logical         :: fonte_neige = .false.
1545  real            :: max_eau_sol = 150.0
1546  character (len = 80) :: abort_message
1547
1548  if (check) write(*,*)'Entree ', modname,' surface = ',nisurf
1549
1550  if (size(run_off) /= knon .AND. nisurf == is_ter) then
1551    write(*,*)'Bizarre, le nombre de points continentaux'
1552    write(*,*)'a change entre deux appels. J''arrete ...'
1553    abort_message='Pb run_off'
1554    call abort_gcm(modname,abort_message,1)
1555  endif
1556!
1557! Traitement neige et humidite du sol
1558!
1559    if (nisurf == is_oce) then
1560      snow = 0.
1561      qsol = max_eau_sol
1562    else
1563      snow = max(0.0, snow + (precip_snow - evap) * dtime)
1564      qsol = qsol + (precip_rain - evap) * dtime
1565    endif
1566
1567
1568!
1569! Initialisation
1570!
1571!
1572! zx_qs = qsat en kg/kg
1573!
1574  DO i = 1, knon
1575    zx_pkh(i) = (ps(i)/ps(i))**RKAPPA
1576  IF (thermcep) THEN
1577      zdelta=MAX(0.,SIGN(1.,rtt-tsurf(i)))
1578      zcvm5 = R5LES*RLVTT*(1.-zdelta) + R5IES*RLSTT*zdelta
1579      zcvm5 = zcvm5 / RCPD / (1.0+RVTMP2*q1lay(i))
1580      zx_qs= r2es * FOEEW(tsurf(i),zdelta)/ps(i)
1581      zx_qs=MIN(0.5,zx_qs)
1582      zcor=1./(1.-retv*zx_qs)
1583      zx_qs=zx_qs*zcor
1584      zx_dq_s_dh = FOEDE(tsurf(i),zdelta,zcvm5,zx_qs,zcor) &
1585     &                 /RLVTT / zx_pkh(i)
1586    ELSE
1587      IF (tsurf(i).LT.t_coup) THEN
1588        zx_qs = qsats(tsurf(i)) / ps(i)
1589        zx_dq_s_dh = dqsats(tsurf(i),zx_qs)/RLVTT &
1590     &                    / zx_pkh(i)
1591      ELSE
1592        zx_qs = qsatl(tsurf(i)) / ps(i)
1593        zx_dq_s_dh = dqsatl(tsurf(i),zx_qs)/RLVTT &
1594     &               / zx_pkh(i)
1595      ENDIF
1596    ENDIF
1597    zx_dq_s_dt(i) = RCPD * zx_pkh(i) * zx_dq_s_dh
1598    zx_qsat(i) = zx_qs
1599    zx_coef(i) = coef1lay(i) &
1600     & * (1.0+SQRT(u1lay(i)**2+v1lay(i)**2)) &
1601     & * p1lay(i)/(RD*t1lay(i))
1602   
1603  ENDDO
1604
1605
1606! === Calcul de la temperature de surface ===
1607!
1608! zx_sl = chaleur latente d'evaporation ou de sublimation
1609!
1610  do i = 1, knon
1611    zx_sl(i) = RLVTT
1612    if (tsurf(i) .LT. RTT) zx_sl(i) = RLSTT
1613    zx_k1(i) = zx_coef(i)
1614  enddo
1615
1616
1617  do i = 1, knon
1618! Q
1619    zx_oq(i) = 1. - (beta(i) * zx_k1(i) * peqBcoef(i) * dtime)
1620    zx_mq(i) = beta(i) * zx_k1(i) * &
1621     &             (peqAcoef(i) - zx_qsat(i) &
1622     &                          + zx_dq_s_dt(i) * tsurf(i)) &
1623     &             / zx_oq(i)
1624    zx_nq(i) = beta(i) * zx_k1(i) * (-1. * zx_dq_s_dt(i)) &
1625     &                              / zx_oq(i)
1626
1627! H
1628    zx_oh(i) = 1. - (zx_k1(i) * petBcoef(i) * dtime)
1629    zx_mh(i) = zx_k1(i) * petAcoef(i) / zx_oh(i)
1630    zx_nh(i) = - (zx_k1(i) * RCPD * zx_pkh(i))/ zx_oh(i)
1631
1632! Tsurface
1633    tsurf_new(i) = (tsurf(i) + cal(i)/(RCPD * zx_pkh(i)) * dtime * &
1634     &             (radsol(i) + zx_mh(i) + zx_sl(i) * zx_mq(i)) &
1635     &                 + dif_grnd(i) * t_grnd * dtime)/ &
1636     &          ( 1. - dtime * cal(i)/(RCPD * zx_pkh(i)) * ( &
1637     &                       zx_nh(i) + zx_sl(i) * zx_nq(i)) & 
1638     &                     + dtime * dif_grnd(i))
1639
1640!
1641! Y'a-t-il fonte de neige?
1642!
1643    fonte_neige = (nisurf /= is_oce) .AND. &
1644     & (snow(i) > epsfra .OR. nisurf == is_sic .OR. nisurf == is_lic) &
1645     & .AND. (tsurf_new(i) >= RTT)
1646    if (fonte_neige) tsurf_new(i) = RTT 
1647    zx_h_ts(i) = tsurf_new(i) * RCPD * zx_pkh(i)
1648    d_ts(i) = tsurf_new(i) - tsurf(i)
1649    zx_q_0(i) = zx_qsat(i) + zx_dq_s_dt(i) * d_ts(i)
1650!== flux_q est le flux de vapeur d'eau: kg/(m**2 s)  positive vers bas
1651!== flux_t est le flux de cpt (energie sensible): j/(m**2 s)
1652    evap(i) = - zx_mq(i) - zx_nq(i) * tsurf_new(i)
1653    fluxlat(i) = - evap(i) * zx_sl(i)
1654    fluxsens(i) = zx_mh(i) + zx_nh(i) * tsurf_new(i)
1655! Derives des flux dF/dTs (W m-2 K-1):
1656    dflux_s(i) = zx_nh(i)
1657    dflux_l(i) = (zx_sl(i) * zx_nq(i))
1658!
1659! en cas de fonte de neige
1660!
1661    if (fonte_neige) then
1662      bilan_f = radsol(i) + fluxsens(i) - (zx_sl(i) * evap (i)) - &
1663     &          dif_grnd(i) * (tsurf_new(i) - t_grnd) - &
1664     &          RCPD * (zx_pkh(i))/cal(i)/dtime * (tsurf_new(i) - tsurf(i))
1665      bilan_f = max(0., bilan_f)
1666      fq_fonte = bilan_f / zx_sl(i)
1667      snow(i) = max(0., snow(i) - fq_fonte * dtime)
1668      qsol(i) = qsol(i) + (fq_fonte * dtime)
1669    endif
1670    if (nisurf == is_ter)  &
1671     &  run_off(i) = run_off(i) + max(qsol(i) - max_eau_sol, 0.0)
1672    qsol(i) = min(qsol(i), max_eau_sol)
1673  ENDDO
1674
1675  END SUBROUTINE calcul_fluxs
1676!
1677!#########################################################################
1678!
1679  SUBROUTINE gath2cpl(champ_in, champ_out, klon, knon, iim, jjm, knindex)
1680
1681! Cette routine ecrit un champ 'gathered' sur la grille 2D pour le passer
1682! au coupleur.
1683!
1684!
1685! input:         
1686!   champ_in     champ sur la grille gathere       
1687!   knon         nombre de points dans le domaine a traiter
1688!   knindex      index des points de la surface a traiter
1689!   klon         taille de la grille
1690!   iim,jjm      dimension de la grille 2D
1691!
1692! output:
1693!   champ_out    champ sur la grille 2D
1694!
1695! input
1696  integer                   :: klon, knon, iim, jjm
1697  real, dimension(klon)     :: champ_in
1698  integer, dimension(klon)  :: knindex
1699! output
1700  real, dimension(iim,jjm+1)  :: champ_out
1701! local
1702  integer                   :: i, ig, j
1703  real, dimension(klon)     :: tamp
1704
1705  tamp = 0.
1706  do i = 1, knon
1707    ig = knindex(i)
1708    tamp(ig) = champ_in(i)
1709  enddo   
1710  ig = 1
1711  champ_out(:,1) = tamp(ig)
1712  do j = 2, jjm
1713    do i = 1, iim
1714      ig = ig + 1
1715      champ_out(i,j) = tamp(ig)
1716    enddo
1717  enddo
1718  ig = ig + 1
1719  champ_out(:,jjm+1) = tamp(ig)
1720
1721  END SUBROUTINE gath2cpl
1722!
1723!#########################################################################
1724!
1725  SUBROUTINE cpl2gath(champ_in, champ_out, klon, knon, iim, jjm, knindex)
1726
1727! Cette routine ecrit un champ 'gathered' sur la grille 2D pour le passer
1728! au coupleur.
1729!
1730!
1731! input:         
1732!   champ_in     champ sur la grille gathere       
1733!   knon         nombre de points dans le domaine a traiter
1734!   knindex      index des points de la surface a traiter
1735!   klon         taille de la grille
1736!   iim,jjm      dimension de la grille 2D
1737!
1738! output:
1739!   champ_out    champ sur la grille 2D
1740!
1741! input
1742  integer                   :: klon, knon, iim, jjm
1743  real, dimension(iim,jjm+1)     :: champ_in
1744  integer, dimension(klon)  :: knindex
1745! output
1746  real, dimension(klon)  :: champ_out
1747! local
1748  integer                   :: i, ig, j
1749  real, dimension(klon)     :: tamp
1750  logical                   :: check = .false.
1751
1752  ig = 1
1753  tamp(ig) = champ_in(1,1)
1754  do j = 2, jjm
1755    do i = 1, iim
1756      ig = ig + 1
1757      tamp(ig) = champ_in(i,j)
1758    enddo
1759  enddo
1760  ig = ig + 1
1761  tamp(ig) = champ_in(1,jjm+1)
1762
1763  do i = 1, knon
1764    ig = knindex(i)
1765    champ_out(i) = tamp(ig)
1766  enddo   
1767
1768  END SUBROUTINE cpl2gath
1769!
1770!#########################################################################
1771!
1772  SUBROUTINE albsno(klon, agesno,alb_neig_grid)
1773  IMPLICIT none
1774 
1775  integer :: klon
1776  INTEGER, PARAMETER :: nvm = 8
1777  REAL, dimension(klon,nvm) :: veget
1778  REAL, DIMENSION(klon) :: alb_neig_grid, agesno
1779 
1780  INTEGER :: i, nv
1781 
1782  REAL, DIMENSION(nvm),SAVE :: init, decay
1783  REAL :: as
1784  DATA init /0.55, 0.14, 0.18, 0.29, 0.15, 0.15, 0.14, 0./
1785  DATA decay/0.30, 0.67, 0.63, 0.45, 0.40, 0.14, 0.06, 1./
1786 
1787  veget = 0.
1788  veget(:,1) = 1.     ! desert partout
1789  DO i = 1, klon
1790    alb_neig_grid(i) = 0.0
1791  ENDDO
1792  DO nv = 1, nvm
1793    DO i = 1, klon
1794      as = init(nv)+decay(nv)*EXP(-agesno(i)/5.)
1795      alb_neig_grid(i) = alb_neig_grid(i) + veget(i,nv)*as
1796    ENDDO
1797  ENDDO
1798 
1799  END SUBROUTINE albsno
1800!
1801!#########################################################################
1802!
1803  END MODULE interface_surf
Note: See TracBrowser for help on using the repository browser.