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

Last change on this file since 281 was 281, checked in by lmdzadmin, 23 years ago

Passage des deux albedos de surface (vis et nir)
Modif dans interfsol sur les indicages des variables passees a ORCHIDEE pour
ne plus avoir de decalage dans les sorties ORCHIDEE
LF

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 88.3 KB
RevLine 
[223]1! $Header$
[90]2
3  MODULE interface_surf
4
5! Ce module regroupe toutes les routines gerant l'interface entre le modele
6! atmospherique et les modeles de surface (sols continentaux, oceans, glaces)
7! Les routines sont les suivantes:
8!
9!   interfsurf_*: routines d'aiguillage vers les interfaces avec les
10!                 differents modeles de surface
11!   interfsol\
12!             > routines d'interface proprement dite
13!   interfoce/
14!
15!   interfstart: routine d'initialisation et de lecture de l'etat initial
16!                "interface"
17!   interffin  : routine d'ecriture de l'etat de redemmarage de l'interface
18!
19!
20! L. Fairhead, LMD, 02/2000
21
22  USE ioipsl
23
24  IMPLICIT none
25
26  PRIVATE
[224]27  PUBLIC :: interfsurf,interfsurf_hq, gath2cpl
[90]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
[109]37#include "YOMCST.inc"
[112]38#include "indicesol.inc"
[90]39
[109]40
[112]41! run_off      ruissellement total
[90]42  real, allocatable, dimension(:),save    :: run_off
[177]43  real, allocatable, dimension(:),save    :: coastalflow, riverflow
[90]44
45
46  CONTAINS
47!
48!############################################################################
49!
[205]50  SUBROUTINE interfsurf_hq(itime, dtime, date0, jour, rmu0, &
[177]51      & klon, iim, jjm, nisurf, knon, knindex, pctsrf, &
52      & rlon, rlat, cufi, cvfi,&
53      & debut, lafin, ok_veget, soil_model, nsoilmx, tsoil,&
54      & zlev,  u1_lay, v1_lay, temp_air, spechum, epot_air, ccanopy, &
[90]55      & tq_cdrag, petAcoef, peqAcoef, petBcoef, peqBcoef, &
[177]56      & precip_rain, precip_snow, sollw, sollwdown, swnet, swdown, &
[171]57      & fder, taux, tauy, rugos, rugoro, &
[98]58      & albedo, snow, qsol, &
[105]59      & tsurf, p1lay, ps, radsol, &
[112]60      & ocean, npas, nexca, zmasq, &
[90]61      & evap, fluxsens, fluxlat, dflux_l, dflux_s, &             
[281]62      & tsol_rad, tsurf_new, alb_new, alblw, emis_new, &
63      & z0_new, pctsrf_new, agesno)
[90]64
65
66! Cette routine sert d'aiguillage entre l'atmosphere et la surface en general
67! (sols continentaux, oceans, glaces) pour les fluxs de chaleur et d'humidite.
68! En pratique l'interface se fait entre la couche limite du modele
69! atmospherique (clmain.F) et les routines de surface (sechiba, oasis, ...)
70!
71!
72! L.Fairhead 02/2000
73!
74! input:
75!   itime        numero du pas de temps
76!   klon         nombre total de points de grille
[98]77!   iim, jjm     nbres de pts de grille
[90]78!   dtime        pas de temps de la physique (en s)
[205]79!   date0        jour initial
[109]80!   jour         jour dans l'annee en cours,
81!   rmu0         cosinus de l'angle solaire zenithal
[101]82!   nexca        pas de temps couplage
[90]83!   nisurf       index de la surface a traiter (1 = sol continental)
84!   knon         nombre de points de la surface a traiter
85!   knindex      index des points de la surface a traiter
[98]86!   pctsrf       tableau des pourcentages de surface de chaque maille
[90]87!   rlon         longitudes
88!   rlat         latitudes
[177]89!   cufi,cvfi    resolution des mailles en x et y (m)
[90]90!   debut        logical: 1er appel a la physique
91!   lafin        logical: dernier appel a la physique
92!   ok_veget     logical: appel ou non au schema de surface continental
93!                     (si false calcul simplifie des fluxs sur les continents)
94!   zlev         hauteur de la premiere couche
95!   u1_lay       vitesse u 1ere couche
96!   v1_lay       vitesse v 1ere couche
97!   temp_air     temperature de l'air 1ere couche
98!   spechum      humidite specifique 1ere couche
[177]99!   epot_air     temp potentielle de l'air
[90]100!   ccanopy      concentration CO2 canopee
101!   tq_cdrag     cdrag
102!   petAcoef     coeff. A de la resolution de la CL pour t
103!   peqAcoef     coeff. A de la resolution de la CL pour q
104!   petBcoef     coeff. B de la resolution de la CL pour t
105!   peqBcoef     coeff. B de la resolution de la CL pour q
106!   precip_rain  precipitation liquide
107!   precip_snow  precipitation solide
[177]108!   sollw        flux IR net a la surface
109!   sollwdown    flux IR descendant a la surface
[90]110!   swnet        flux solaire net
111!   swdown       flux solaire entrant a la surface
[98]112!   albedo       albedo de la surface
[90]113!   tsurf        temperature de surface
114!   p1lay        pression 1er niveau (milieu de couche)
115!   ps           pression au sol
116!   radsol       rayonnement net aus sol (LW + SW)
117!   ocean        type d'ocean utilise (force, slab, couple)
[101]118!   fder         derivee des flux (pour le couplage)
119!   taux, tauy   tension de vents
[157]120!   rugos        rugosite
[105]121!   zmasq        masque terre/ocean
[171]122!   rugoro       rugosite orographique
[90]123!
124! output:
125!   evap         evaporation totale
126!   fluxsens     flux de chaleur sensible
127!   fluxlat      flux de chaleur latente
128!   tsol_rad     
129!   tsurf_new    temperature au sol
130!   alb_new      albedo
131!   emis_new     emissivite
132!   z0_new       surface roughness
[98]133!   pctsrf_new   nouvelle repartition des surfaces
[90]134
135
136! Parametres d'entree
137  integer, intent(IN) :: itime
[98]138  integer, intent(IN) :: iim, jjm
[90]139  integer, intent(IN) :: klon
140  real, intent(IN) :: dtime
[205]141  real, intent(IN) :: date0
[90]142  integer, intent(IN) :: jour
[109]143  real, intent(IN)    :: rmu0(klon)
[90]144  integer, intent(IN) :: nisurf
145  integer, intent(IN) :: knon
[147]146  integer, dimension(klon), intent(in) :: knindex
[98]147  real, dimension(klon,nbsrf), intent(IN) :: pctsrf
[90]148  logical, intent(IN) :: debut, lafin, ok_veget
149  real, dimension(klon), intent(IN) :: rlon, rlat
[177]150  real, dimension(klon), intent(IN) :: cufi, cvfi
151  real, dimension(klon), intent(INOUT) :: tq_cdrag
[147]152  real, dimension(klon), intent(IN) :: zlev
153  real, dimension(klon), intent(IN) :: u1_lay, v1_lay
154  real, dimension(klon), intent(IN) :: temp_air, spechum
[177]155  real, dimension(klon), intent(IN) :: epot_air, ccanopy
156  real, dimension(klon), intent(IN) :: petAcoef, peqAcoef
[147]157  real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
158  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
[177]159  real, dimension(klon), intent(IN) :: sollw, sollwdown, swnet, swdown
160  real, dimension(klon), intent(IN) :: ps, albedo
[147]161  real, dimension(klon), intent(IN) :: tsurf, p1lay
[235]162  REAL, DIMENSION(klon), INTENT(INOUT) :: radsol,fder
[98]163  real, dimension(klon), intent(IN) :: zmasq
[235]164  real, dimension(klon), intent(IN) :: taux, tauy, rugos, rugoro
[90]165  character (len = 6)  :: ocean
[112]166  integer              :: npas, nexca ! nombre et pas de temps couplage
[147]167  real, dimension(klon), intent(INOUT) :: evap, snow, qsol
[177]168!! PB ajout pour soil
169  logical          :: soil_model
170  integer          :: nsoilmx
171  REAL, DIMENSION(klon, nsoilmx) :: tsoil
172  REAL, dimension(klon)          :: soilcap
173  REAL, dimension(klon)          :: soilflux
[90]174! Parametres de sortie
[147]175  real, dimension(klon), intent(OUT):: fluxsens, fluxlat
176  real, dimension(klon), intent(OUT):: tsol_rad, tsurf_new, alb_new
[281]177  real, dimension(klon), intent(OUT):: alblw
[147]178  real, dimension(klon), intent(OUT):: emis_new, z0_new
179  real, dimension(klon), intent(OUT):: dflux_l, dflux_s
[90]180  real, dimension(klon,nbsrf), intent(OUT) :: pctsrf_new
[112]181  real, dimension(klon), intent(INOUT):: agesno
[90]182
183! Local
[179]184  character (len = 20),save :: modname = 'interfsurf_hq'
[90]185  character (len = 80) :: abort_message
186  logical, save        :: first_call = .true.
[179]187  integer, save        :: error
[236]188  integer              :: ii, index
[179]189  logical,save              :: check = .true.
[147]190  real, dimension(klon):: cal, beta, dif_grnd, capsol
[177]191!!$PB  real, parameter      :: calice=1.0/(5.1444e+06*0.15), tau_gl=86400.*5.
192  real, parameter      :: calice=1.0/(5.1444e+06*0.15), tau_gl=86400.*5.
[98]193  real, parameter      :: calsno=1./(2.3867e+06*.15)
[147]194  real, dimension(klon):: alb_ice
195  real, dimension(klon):: tsurf_temp
[258]196!!  real, allocatable, dimension(:), save :: alb_neig_grid
[157]197  real, dimension(klon):: alb_neig, alb_eau
[147]198  real, DIMENSION(klon):: zfra
[177]199  logical              :: cumul = .false.
[90]200
201  if (check) write(*,*) 'Entree ', modname
202!
203! On doit commencer par appeler les schemas de surfaces continentales
204! car l'ocean a besoin du ruissellement qui est y calcule
205!
206  if (first_call) then
207    if (nisurf /= is_ter .and. klon > 1) then
208      write(*,*)' *** Warning ***'
209      write(*,*)' nisurf = ',nisurf,' /= is_ter = ',is_ter
210      write(*,*)'or on doit commencer par les surfaces continentales'
211      abort_message='voir ci-dessus'
212      call abort_gcm(modname,abort_message,1)
213    endif
214    if (ocean /= 'slab  ' .and. ocean /= 'force ' .and. ocean /= 'couple') then
215      write(*,*)' *** Warning ***'
216      write(*,*)'Option couplage pour l''ocean = ', ocean
217      abort_message='option pour l''ocean non valable'
218      call abort_gcm(modname,abort_message,1)
219    endif
[105]220    if ( is_oce > is_sic ) then
221      write(*,*)' *** Warning ***'
222      write(*,*)' Pour des raisons de sequencement dans le code'
223      write(*,*)' l''ocean doit etre traite avant la banquise'
224      write(*,*)' or is_oce = ',is_oce, '> is_sic = ',is_sic
225      abort_message='voir ci-dessus'
226      call abort_gcm(modname,abort_message,1)
[112]227    endif
[262]228!    allocate(alb_neig_grid(klon), stat = error)
229!    if (error /= 0) then
230!      abort_message='Pb allocation alb_neig_grid'
231!      call abort_gcm(modname,abort_message,1)
232!    endif
[90]233  endif
234  first_call = .false.
[98]235 
[157]236! Initialisations diverses
237!
[235]238!!$  cal=0.; beta=1.; dif_grnd=0.; capsol=0.
239!!$  alb_new = 0.; z0_new = 0.; alb_neig = 0.0
240!!$! PB
241!!$  tsurf_new = 0.
[157]242
[235]243  cal = 999999. ; beta = 999999. ; dif_grnd = 999999. ; capsol = 999999.
244  alb_new = 999999. ; z0_new = 999999. ; alb_neig = 999999.
245  tsurf_new = 999999.
[281]246  alblw = 999999.
[90]247! Aiguillage vers les differents schemas de surface
248
249  if (nisurf == is_ter) then
250!
251! Surface "terre" appel a l'interface avec les sols continentaux
252!
253! allocation du run-off
[177]254    if (.not. allocated(coastalflow)) then
255      allocate(coastalflow(knon), stat = error)
256      if (error /= 0) then
257        abort_message='Pb allocation coastalflow'
258        call abort_gcm(modname,abort_message,1)
259      endif
260      allocate(riverflow(knon), stat = error)
261      if (error /= 0) then
262        abort_message='Pb allocation riverflow'
263        call abort_gcm(modname,abort_message,1)
264      endif
[90]265      allocate(run_off(knon), stat = error)
266      if (error /= 0) then
[275]267        abort_message='Pb allocation run_off'
[90]268        call abort_gcm(modname,abort_message,1)
269      endif
[177]270    else if (size(coastalflow) /= knon) then
[90]271      write(*,*)'Bizarre, le nombre de points continentaux'
[177]272      write(*,*)'a change entre deux appels. J''arrete ...'
273      abort_message='voir ci-dessus'
274      call abort_gcm(modname,abort_message,1)
[90]275    endif
[275]276    coastalflow = 0.
277    riverflow = 0.
[90]278!
[109]279! Calcul age de la neige
280!
[177]281!!$ PB ATTENTION changement ordre des appels
[258]282!!$    CALL albsno(klon,agesno,alb_neig_grid) 
[235]283
[98]284    if (.not. ok_veget) then
285!
286! calcul albedo: lecture albedo fichier CL puis ajout albedo neige
287!
[109]288       call interfsur_lim(itime, dtime, jour, &
289     & klon, nisurf, knon, knindex, debut,  &
[121]290     & alb_new, z0_new)
[236]291
[177]292! calcul snow et qsol, hydrol adapté
293!
[236]294       CALL calbeta(dtime, nisurf, knon, snow, qsol, beta, capsol, dif_grnd)
295
[177]296       IF (soil_model) THEN
[236]297           CALL soil(dtime, nisurf, knon,snow, tsurf, tsoil,soilcap, soilflux)
298           cal(1:knon) = RCPD / soilcap(1:knon)
299           radsol(1:knon) = radsol(1:knon)  + soilflux(1:knon)
[177]300       ELSE
301           cal = RCPD * capsol
302!!$      cal = capsol
303       ENDIF
304       CALL calcul_fluxs( klon, knon, nisurf, dtime, &
305     &   tsurf, p1lay, cal, beta, tq_cdrag, ps, &
306     &   precip_rain, precip_snow, snow, qsol,  &
307     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
308     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
309     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
310
[181]311       CALL fonte_neige( klon, knon, nisurf, dtime, &
312     &   tsurf, p1lay, cal, beta, tq_cdrag, ps, &
313     &   precip_rain, precip_snow, snow, qsol,  &
314     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
315     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
316     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
317
[236]318
[258]319     call albsno(klon,knon,dtime,agesno(:),alb_neig(:), precip_snow(:)) 
320     where (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
[281]321     zfra(1:knon) = max(0.0,min(1.0,snow/(snow+10.0)))
322     alb_new(1 : knon)  = alb_neig(1 : knon) *zfra(1:knon) + &
323    &                     alb_new(1 : knon)*(1.0-zfra(1:knon))
[258]324     z0_new = sqrt(z0_new**2+rugoro**2)
[281]325     alblw(1 : knon) = alb_new(1 : knon)
[258]326
[98]327    else
[258]328!!      CALL albsno(klon,agesno,alb_neig_grid) 
[98]329!
330!  appel a sechiba
331!
[233]332      call interfsol(itime, klon, dtime, date0, nisurf, knon, &
[177]333     &  knindex, rlon, rlat, cufi, cvfi, iim, jjm, pctsrf, &
[90]334     &  debut, lafin, ok_veget, &
[177]335     &  zlev,  u1_lay, v1_lay, temp_air, spechum, epot_air, ccanopy, &
[90]336     &  tq_cdrag, petAcoef, peqAcoef, petBcoef, peqBcoef, &
[177]337     &  precip_rain, precip_snow, sollwdown, swnet, swdown, &
338     &  tsurf, p1lay/100., ps, radsol, &
[90]339     &  evap, fluxsens, fluxlat, &             
[281]340     &  tsol_rad, tsurf_new, alb_new, alblw, &
341     &  emis_new, z0_new, dflux_l, dflux_s)
[233]342
343
344! ajout de la contribution du relief
345
346      z0_new = SQRT(z0_new**2+rugoro**2)
347
[98]348    endif   
[90]349!
[139]350! Remplissage des pourcentages de surface
351!
352    pctsrf_new(:,nisurf) = pctsrf(:,nisurf)
353
[90]354  else if (nisurf == is_oce) then
355
356    if (check) write(*,*)'ocean, nisurf = ',nisurf
[98]357
358
[90]359!
360! Surface "ocean" appel a l'interface avec l'ocean
361!
[101]362    if (ocean == 'couple') then
363      if (nexca == 0) then
364        abort_message='nexca = 0 dans interfoce_cpl'
365        call abort_gcm(modname,abort_message,1)
366      endif
367
[177]368      cumul = .false.
369
370      call interfoce(itime, dtime, cumul, &
[101]371      & klon, iim, jjm, nisurf, pctsrf, knon, knindex, rlon, rlat, &
[112]372      & ocean, npas, nexca, debut, lafin, &
[177]373      & swdown, sollw, precip_rain, precip_snow, evap, tsurf, &
374      & fluxlat, fluxsens, fder, albedo, taux, tauy, zmasq, &
[274]375      & tsurf_new, alb_new, pctsrf_new)
[101]376
[90]377!    else if (ocean == 'slab  ') then
378!      call interfoce(nisurf)
[109]379    else                              ! lecture conditions limites
380      call interfoce(itime, dtime, jour, &
381     &  klon, nisurf, knon, knindex, &
382     &  debut, &
383     &  tsurf_new, pctsrf_new)
384
[101]385    endif
[105]386
[112]387    tsurf_temp = tsurf_new
[98]388    cal = 0.
389    beta = 1.
390    dif_grnd = 0.
[258]391    alb_neig(:) = 0.
392    agesno(:) = 0.
[98]393
[147]394    call calcul_fluxs( klon, knon, nisurf, dtime, &
[105]395     &   tsurf_temp, p1lay, cal, beta, tq_cdrag, ps, &
[98]396     &   precip_rain, precip_snow, snow, qsol,  &
[90]397     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
398     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
[98]399     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
[235]400   
401    fder = fder + dflux_s + dflux_l
[177]402
[90]403!
[177]404! 2eme appel a interfoce pour le cumul des champs (en particulier
405! fluxsens et fluxlat calcules dans calcul_fluxs)
406!
407    if (ocean == 'couple') then
408
409      cumul = .true.
410
411      call interfoce(itime, dtime, cumul, &
412      & klon, iim, jjm, nisurf, pctsrf, knon, knindex, rlon, rlat, &
413      & ocean, npas, nexca, debut, lafin, &
414      & swdown, sollw, precip_rain, precip_snow, evap, tsurf, &
415      & fluxlat, fluxsens, fder, albedo, taux, tauy, zmasq, &
[274]416      & tsurf_new, alb_new, pctsrf_new)
[177]417
418!    else if (ocean == 'slab  ') then
419!      call interfoce(nisurf)
420
421    endif
422
423!
[98]424! calcul albedo
425!
426
[112]427    if ( minval(rmu0) == maxval(rmu0) .and. minval(rmu0) == -999.999 ) then
428      CALL alboc(FLOAT(jour),rlat,alb_eau)
429    else  ! cycle diurne
430      CALL alboc_cd(rmu0,alb_eau)
431    endif
432    DO ii =1, knon
433      alb_new(ii) = alb_eau(knindex(ii))
434    enddo
[157]435
[274]436    z0_new = sqrt(rugos**2 + rugoro**2)
[281]437    alblw(1:knon) = alb_new(1:knon)
438
[98]439!
[90]440  else if (nisurf == is_sic) then
441
442    if (check) write(*,*)'sea ice, nisurf = ',nisurf
443
444!
445! Surface "glace de mer" appel a l'interface avec l'ocean
446!
447!
[105]448    if (ocean == 'couple') then
[98]449
[177]450      cumul =.false.
451
452      call interfoce(itime, dtime, cumul, &
[105]453      & klon, iim, jjm, nisurf, pctsrf, knon, knindex, rlon, rlat, &
[112]454      & ocean, npas, nexca, debut, lafin, &
[177]455      & swdown, sollw, precip_rain, precip_snow, evap, tsurf, &
456      & fluxlat, fluxsens, fder, albedo, taux, tauy, zmasq, &
[274]457      & tsurf_new, alb_new, pctsrf_new)
[98]458
[105]459      tsurf_temp = tsurf_new
[177]460      cal = 0.
[105]461      dif_grnd = 0.
[140]462      beta = 1.0
[105]463
464!    else if (ocean == 'slab  ') then
465!      call interfoce(nisurf)
[274]466    ELSE
[235]467!                              ! lecture conditions limites
[274]468      CALL interfoce(itime, dtime, jour, &
[235]469             &  klon, nisurf, knon, knindex, &
470             &  debut, &
471             &  tsurf_new, pctsrf_new)
[105]472
[274]473      CALL calbeta(dtime, nisurf, knon, snow, qsol, beta, capsol, dif_grnd)
[235]474     
[274]475      IF (soil_model) THEN
476         CALL soil(dtime, nisurf, knon,snow, tsurf, tsoil,soilcap, soilflux)
477         cal(1:knon) = RCPD / soilcap(1:knon)
478         radsol(1:knon) = radsol(1:knon)  + soilflux(1:knon)
479         dif_grnd = 0.
480      ELSE
481         dif_grnd = 1.0 / tau_gl
482         cal = RCPD * calice
483         WHERE (snow > 0.0) cal = RCPD * calsno
[235]484      ENDIF
[274]485      tsurf_temp = tsurf
486      beta = 1.0
487    ENDIF
[105]488
[274]489    CALL calcul_fluxs( klon, knon, nisurf, dtime, &
[235]490         &   tsurf_temp, p1lay, cal, beta, tq_cdrag, ps, &
491         &   precip_rain, precip_snow, snow, qsol,  &
492         &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
493         &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
494         &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
[90]495
[274]496    IF (ocean /= 'couple') THEN
497      CALL fonte_neige( klon, knon, nisurf, dtime, &
[235]498             &   tsurf_temp, p1lay, cal, beta, tq_cdrag, ps, &
499             &   precip_rain, precip_snow, snow, qsol,  &
500             &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
501             &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
502             &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
[274]503
504!     calcul albedo
505
506      CALL albsno(klon,knon,dtime,agesno(:),alb_neig(:), precip_snow(:)) 
507      WHERE (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
[281]508      zfra(1:knon) = MAX(0.0,MIN(1.0,snow/(snow+10.0)))
509      alb_new(1 : knon) = alb_neig(1 : knon) *zfra(1:knon) + &
510     &                    0.6 * (1.0-zfra(1:knon))
[274]511!!      alb_new(1 : knon) = 0.6
512    ENDIF
513
514    fder = fder + dflux_s + dflux_l
515
[109]516!
[177]517! 2eme appel a interfoce pour le cumul et le passage des flux a l'ocean
518!
519    if (ocean == 'couple') then
520
521      cumul =.true.
522
523      call interfoce(itime, dtime, cumul, &
524      & klon, iim, jjm, nisurf, pctsrf, knon, knindex, rlon, rlat, &
525      & ocean, npas, nexca, debut, lafin, &
526      & swdown, sollw, precip_rain, precip_snow, evap, tsurf, &
527      & fluxlat, fluxsens, fder, albedo, taux, tauy, zmasq, &
[274]528      & tsurf_new, alb_new, pctsrf_new)
[177]529
530!    else if (ocean == 'slab  ') then
531!      call interfoce(nisurf)
532
533    endif
534
[258]535     
[281]536    z0_new = 0.001
537    z0_new = SQRT(z0_new**2+rugoro**2)
538    alblw(1:knon) = alb_new(1:knon)
[98]539
[90]540  else if (nisurf == is_lic) then
541
542    if (check) write(*,*)'glacier, nisurf = ',nisurf
543
544!
545! Surface "glacier continentaux" appel a l'interface avec le sol
546!
547!    call interfsol(nisurf)
[177]548    IF (soil_model) THEN
[235]549        CALL soil(dtime, nisurf, knon, snow, tsurf, tsoil,soilcap, soilflux)
550        cal(1:knon) = RCPD / soilcap(1:knon)
551        radsol(1:knon)  = radsol(1:knon) + soilflux(1:knon)
[177]552    ELSE
553        cal = RCPD * calice
554        WHERE (snow > 0.0) cal = RCPD * calsno
555    ENDIF
[98]556    beta = 1.0
557    dif_grnd = 0.0
558
[147]559    call calcul_fluxs( klon, knon, nisurf, dtime, &
[105]560     &   tsurf, p1lay, cal, beta, tq_cdrag, ps, &
[98]561     &   precip_rain, precip_snow, snow, qsol,  &
[90]562     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
563     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
[98]564     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
[90]565
[181]566    call fonte_neige( klon, knon, nisurf, dtime, &
567     &   tsurf, p1lay, cal, beta, tq_cdrag, ps, &
568     &   precip_rain, precip_snow, snow, qsol,  &
569     &   radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
570     &   petAcoef, peqAcoef, petBcoef, peqBcoef, &
571     &   tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
572
[109]573!
574! calcul albedo
575!
[258]576     CALL albsno(klon,knon,dtime,agesno(:),alb_neig(:), precip_snow(:)) 
577     WHERE (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
[281]578     zfra(1:knon) = MAX(0.0,MIN(1.0,snow/(snow+10.0)))
579     alb_new(1 : knon)  = alb_neig(1 : knon)*zfra(1:knon) + &
580    &                     0.6 * (1.0-zfra(1:knon))
[274]581!!     alb_new(1 : knon)  = 0.6
[139]582!
[157]583! Rugosite
584!
[171]585    z0_new = rugoro
[157]586!
[139]587! Remplissage des pourcentages de surface
588!
589    pctsrf_new(:,nisurf) = pctsrf(:,nisurf)
[109]590
[281]591    alblw(1:knon) = alb_new(1:knon)
[90]592  else
593    write(*,*)'Index surface = ',nisurf
594    abort_message = 'Index surface non valable'
595    call abort_gcm(modname,abort_message,1)
596  endif
597
598  END SUBROUTINE interfsurf_hq
599
600!
601!#########################################################################
602!
603  SUBROUTINE interfsurf_vent(nisurf, knon   &         
604  &                     )
605!
606! Cette routine sert d'aiguillage entre l'atmosphere et la surface en general
607! (sols continentaux, oceans, glaces) pour les tensions de vents.
608! En pratique l'interface se fait entre la couche limite du modele
609! atmospherique (clmain.F) et les routines de surface (sechiba, oasis, ...)
610!
611!
612! L.Fairhead 02/2000
613!
614! input:
615!   nisurf       index de la surface a traiter (1 = sol continental)
616!   knon         nombre de points de la surface a traiter
617
618! Parametres d'entree
619  integer, intent(IN) :: nisurf
620  integer, intent(IN) :: knon
621
622
623  return
624  END SUBROUTINE interfsurf_vent
625!
626!#########################################################################
627!
[205]628  SUBROUTINE interfsol(itime, klon, dtime, date0, nisurf, knon, &
[177]629     & knindex, rlon, rlat, cufi, cvfi, iim, jjm, pctsrf, &
[90]630     & debut, lafin, ok_veget, &
[177]631     & zlev,  u1_lay, v1_lay, temp_air, spechum, epot_air, ccanopy, &
[90]632     & tq_cdrag, petAcoef, peqAcoef, petBcoef, peqBcoef, &
633     & precip_rain, precip_snow, lwdown, swnet, swdown, &
[105]634     & tsurf, p1lay, ps, radsol, &
[90]635     & evap, fluxsens, fluxlat, &             
[281]636     & tsol_rad, tsurf_new, alb_new, alblw, &
637     & emis_new, z0_new, dflux_l, dflux_s)
[90]638
[177]639  USE intersurf
640
[90]641! Cette routine sert d'interface entre le modele atmospherique et le
642! modele de sol continental. Appel a sechiba
643!
644! L. Fairhead 02/2000
645!
646! input:
647!   itime        numero du pas de temps
648!   klon         nombre total de points de grille
649!   dtime        pas de temps de la physique (en s)
650!   nisurf       index de la surface a traiter (1 = sol continental)
651!   knon         nombre de points de la surface a traiter
652!   knindex      index des points de la surface a traiter
653!   rlon         longitudes de la grille entiere
654!   rlat         latitudes de la grille entiere
[177]655!   pctsrf       tableau des fractions de surface de chaque maille
[90]656!   debut        logical: 1er appel a la physique (lire les restart)
657!   lafin        logical: dernier appel a la physique (ecrire les restart)
658!   ok_veget     logical: appel ou non au schema de surface continental
659!                     (si false calcul simplifie des fluxs sur les continents)
[98]660!   zlev         hauteur de la premiere couche       
[90]661!   u1_lay       vitesse u 1ere couche
662!   v1_lay       vitesse v 1ere couche
663!   temp_air     temperature de l'air 1ere couche
664!   spechum      humidite specifique 1ere couche
[177]665!   epot_air     temp pot de l'air
[90]666!   ccanopy      concentration CO2 canopee
667!   tq_cdrag     cdrag
668!   petAcoef     coeff. A de la resolution de la CL pour t
669!   peqAcoef     coeff. A de la resolution de la CL pour q
670!   petBcoef     coeff. B de la resolution de la CL pour t
671!   peqBcoef     coeff. B de la resolution de la CL pour q
672!   precip_rain  precipitation liquide
673!   precip_snow  precipitation solide
[177]674!   lwdown       flux IR descendant a la surface
[90]675!   swnet        flux solaire net
676!   swdown       flux solaire entrant a la surface
677!   tsurf        temperature de surface
678!   p1lay        pression 1er niveau (milieu de couche)
679!   ps           pression au sol
680!   radsol       rayonnement net aus sol (LW + SW)
681!   
682!
683! input/output
684!   run_off      ruissellement total
685!
686! output:
687!   evap         evaporation totale
688!   fluxsens     flux de chaleur sensible
689!   fluxlat      flux de chaleur latente
690!   tsol_rad     
691!   tsurf_new    temperature au sol
692!   alb_new      albedo
693!   emis_new     emissivite
694!   z0_new       surface roughness
695
[98]696
[90]697! Parametres d'entree
698  integer, intent(IN) :: itime
699  integer, intent(IN) :: klon
700  real, intent(IN)    :: dtime
[205]701  real, intent(IN)    :: date0
[90]702  integer, intent(IN) :: nisurf
703  integer, intent(IN) :: knon
[177]704  integer, intent(IN) :: iim, jjm
[147]705  integer, dimension(klon), intent(IN) :: knindex
[90]706  logical, intent(IN) :: debut, lafin, ok_veget
[177]707  real, dimension(klon,nbsrf), intent(IN) :: pctsrf
[90]708  real, dimension(klon), intent(IN) :: rlon, rlat
[177]709  real, dimension(klon), intent(IN) :: cufi, cvfi
[147]710  real, dimension(klon), intent(IN) :: zlev
711  real, dimension(klon), intent(IN) :: u1_lay, v1_lay
712  real, dimension(klon), intent(IN) :: temp_air, spechum
[177]713  real, dimension(klon), intent(IN) :: epot_air, ccanopy
714  real, dimension(klon), intent(INOUT) :: tq_cdrag
715  real, dimension(klon), intent(IN) :: petAcoef, peqAcoef
[147]716  real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
717  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
718  real, dimension(klon), intent(IN) :: lwdown, swnet, swdown, ps
719  real, dimension(klon), intent(IN) :: tsurf, p1lay
720  real, dimension(klon), intent(IN) :: radsol
[90]721! Parametres de sortie
[147]722  real, dimension(klon), intent(OUT):: evap, fluxsens, fluxlat
[281]723  real, dimension(klon), intent(OUT):: tsol_rad, tsurf_new, alb_new, alblw
[147]724  real, dimension(klon), intent(OUT):: emis_new, z0_new
725  real, dimension(klon), intent(OUT):: dflux_s, dflux_l
[90]726
727! Local
728!
[281]729  integer              :: ii, ij, jj, igrid, ireal, i, index, iglob
[90]730  integer              :: error
731  character (len = 20) :: modname = 'interfsol'
732  character (len = 80) :: abort_message
[179]733  logical,save              :: check = .TRUE.
[147]734  real, dimension(klon) :: cal, beta, dif_grnd, capsol
[90]735! type de couplage dans sechiba
736!  character (len=10)   :: coupling = 'implicit'
737! drapeaux controlant les appels dans SECHIBA
738!  type(control_type), save   :: control_in
739! coordonnees geographiques
740  real, allocatable, dimension(:,:), save :: lalo
741! pts voisins
742  integer,allocatable, dimension(:,:), save :: neighbours
[177]743! fractions continents
744  real,allocatable, dimension(:), save :: contfrac
[90]745! resolution de la grille
746  real, allocatable, dimension (:,:), save :: resolution
[177]747! correspondance point n -> indices (i,j)
748  integer, allocatable, dimension(:,:), save :: correspond
749! offset pour calculer les point voisins
750  integer, dimension(8,3), save :: off_ini
751  integer, dimension(8), save :: offset
[90]752! Identifieurs des fichiers restart et histoire
753  integer, save          :: rest_id, hist_id
754  integer, save          :: rest_id_stom, hist_id_stom
[177]755!
756  real, allocatable, dimension (:,:), save :: lon_scat, lat_scat 
[90]757
[223]758  logical, save          :: lrestart_read = .true. , lrestart_write = .false.
[177]759
760  real, dimension(klon):: qsurf
[147]761  real, dimension(klon):: snow, qsol
[177]762  real, dimension(knon,2) :: albedo_out
763! Pb de nomenclature
764  real, dimension(klon) :: petA_orc, peqA_orc
765  real, dimension(klon) :: petB_orc, peqB_orc
[281]766! Pb de correspondances de grilles
767  integer, dimension(:), save, allocatable :: ig, jg
768  integer :: indi, indj
769  integer, dimension(klon) :: ktindex
770! Essai cdrag
771  real, dimension(klon) :: cdrag
[98]772
[90]773  if (check) write(*,*)'Entree ', modname
774  if (check) write(*,*)'ok_veget = ',ok_veget
775
[281]776  ktindex(:) = knindex(:) + iim - 1
777
[90]778! initialisation
[177]779  if (debut) then
[90]780
[281]781! Pb de correspondances de grilles
782   allocate(ig(klon))
783   allocate(jg(klon))
784   ig(1) = 1
785   jg(1) = 1
786   indi = 0
787   indj = 2
788   do igrid = 2, klon - 1
789     indi = indi + 1
790     if ( indi > iim) then
791       indi = 1
792       indj = indj + 1
793     endif
794     ig(igrid) = indi
795     jg(igrid) = indj
796   enddo
797   ig(klon) = 1
798   jg(klon) = jjm + 1
[177]799!
800!  Initialisation des offset   
801!
802! offset bord ouest
803   off_ini(1,1) = - iim  ; off_ini(2,1) = - iim + 1; off_ini(3,1) = 1
804   off_ini(4,1) = iim + 1; off_ini(5,1) = iim      ; off_ini(6,1) = 2 * iim - 1
805   off_ini(7,1) = iim -1 ; off_ini(8,1) = - 1
806! offset point normal
807   off_ini(1,2) = - iim  ; off_ini(2,2) = - iim + 1; off_ini(3,2) = 1
808   off_ini(4,2) = iim + 1; off_ini(5,2) = iim      ; off_ini(6,2) = iim - 1
809   off_ini(7,2) = -1     ; off_ini(8,2) = - iim - 1
810! offset bord   est
811   off_ini(1,3) = - iim; off_ini(2,3) = - 2 * iim + 1; off_ini(3,3) = - iim + 1
812   off_ini(4,3) =  1   ; off_ini(5,3) = iim          ; off_ini(6,3) = iim - 1
813   off_ini(7,3) = -1   ; off_ini(8,3) = - iim - 1
814!
815! Initialisation des correspondances point -> indices i,j
816!
817    if (( .not. allocated(correspond))) then
818      allocate(correspond(iim,jjm+1), stat = error)
819      if (error /= 0) then
820        abort_message='Pb allocation correspond'
821        call abort_gcm(modname,abort_message,1)
822      endif     
823    endif
824!
825! Attention aux poles
826!
[281]827!!$    do igrid = 1, knon
828!!$      index = ktindex(igrid)
829!!$      ij = index - int((index-1)/iim)*iim - 1
830!!$      jj = 2 + int((index-1)/iim)
831!!$      if (mod(index,iim) == 1 ) then
832!!$        jj = 1 + int((index-1)/iim)
833!!$        ij = iim
834!!$      endif
835!!$      correspond(ij,jj) = igrid
836!!$      write(50,*)'igrid, i, j =',igrid,ij,jj
837!!$    enddo
838! Pb de correspondances de grilles!
839!!$    do igrid = 1, knon
840!!$      index = ktindex(igrid)
841!!$      ij = ig(index)
842!!$      jj = jg(index)
843!!$      correspond(ij,jj) = igrid
844!!$      write(51,*)'igrid, i, j =',igrid,ij,jj
845!!$    enddo
[177]846    do igrid = 1, knon
[281]847      index = ktindex(igrid)
848          jj = int((index - 1)/iim) + 1
849          ij = index - (jj - 1) * iim
[177]850      correspond(ij,jj) = igrid
851    enddo
[281]852
853!!$    index = 0
854!!$    do jj = 1, jjm+1
855!!$      do ij = 1, iim
856!!$        index = index + 1
857!!$        correspond(ij,jj) = index
858!!$      enddo
859!!$    enddo
860
[177]861! Allouer et initialiser le tableau de coordonnees du sol
862!
863    if ((.not. allocated(lalo))) then
864      allocate(lalo(knon,2), stat = error)
865      if (error /= 0) then
866        abort_message='Pb allocation lalo'
867        call abort_gcm(modname,abort_message,1)
868      endif     
869    endif
870    if ((.not. allocated(lon_scat))) then
[201]871      allocate(lon_scat(iim,jjm+1), stat = error)
[177]872      if (error /= 0) then
873        abort_message='Pb allocation lon_scat'
874        call abort_gcm(modname,abort_message,1)
875      endif     
876    endif
877    if ((.not. allocated(lat_scat))) then
[201]878      allocate(lat_scat(iim,jjm+1), stat = error)
[177]879      if (error /= 0) then
880        abort_message='Pb allocation lat_scat'
881        call abort_gcm(modname,abort_message,1)
882      endif     
883    endif
884    lon_scat = 0.
885    lat_scat = 0.
886    do igrid = 1, knon
887      index = knindex(igrid)
888      lalo(igrid,2) = rlon(index)
889      lalo(igrid,1) = rlat(index)
890      ij = index - int((index-1)/iim)*iim - 1
891      jj = 2 + int((index-1)/iim)
892      if (mod(index,iim) == 1 ) then
893        jj = 1 + int((index-1)/iim)
894        ij = iim
895      endif
[281]896!      lon_scat(ij,jj) = rlon(index)
897!      lat_scat(ij,jj) = rlat(index)
[177]898    enddo
899    index = 1
900    do jj = 2, jjm
901      do ij = 1, iim
902        index = index + 1
903        lon_scat(ij,jj) = rlon(index)
904        lat_scat(ij,jj) = rlat(index)
905      enddo
906    enddo
907    lon_scat(:,1) = lon_scat(:,2)
908    lat_scat(:,1) = rlat(1)
[201]909    lon_scat(:,jjm+1) = lon_scat(:,2)
910    lat_scat(:,jjm+1) = rlat(klon)
[281]911! Pb de correspondances de grilles!
912!    do igrid = 1, knon
913!      index = ktindex(igrid)
914!      ij = ig(index)
915!      jj = jg(index)
916!      lon_scat(ij,jj) = rlon(index)
917!      lat_scat(ij,jj) = rlat(index)
918!    enddo
[90]919
[177]920!
921! Allouer et initialiser le tableau des voisins et des fraction de continents
922!
923    if ( (.not.allocated(neighbours))) THEN
924      allocate(neighbours(knon,8), stat = error)
925      if (error /= 0) then
926        abort_message='Pb allocation neighbours'
927        call abort_gcm(modname,abort_message,1)
928      endif
929    endif
[274]930    neighbours = -1.
[177]931    if (( .not. allocated(contfrac))) then
932      allocate(contfrac(knon), stat = error)
933      if (error /= 0) then
934        abort_message='Pb allocation contfrac'
935        call abort_gcm(modname,abort_message,1)
936      endif     
937    endif
[90]938
[177]939    do igrid = 1, knon
940      ireal = knindex(igrid)
941      contfrac(igrid) = pctsrf(ireal,is_ter)
[281]942    enddo
943
944    do igrid = 1, knon
945      iglob = ktindex(igrid)
946      if (mod(iglob, iim) == 1) then
[177]947        offset = off_ini(:,1)
[281]948      else if(mod(iglob, iim) == 0) then
[177]949        offset = off_ini(:,3)
950      else
951        offset = off_ini(:,2)
952      endif
953      do i = 1, 8
[281]954        index = iglob + offset(i)
955        ireal = (min(max(1, index - iim + 1), klon))
956!        if (index <= 1) index = 1
957!        if (index >= klon) index = klon
958        if (pctsrf(ireal, is_ter) > EPSFRA) then
959          jj = int((index - 1)/iim) + 1
960          ij = index - (jj - 1) * iim
961!!$          ij = index - int((index-1)/iim)*iim - 1
962!!$          jj = 2 + int((index-1)/iim)
963!!$          if (mod(index,iim) == 1 ) then
964!!$            jj = 1 + int((index-1)/iim)
965!!$            ij = iim
966!!$          endif
967!!$! Pb de correspondances de grilles!
968!!$      ij = ig(index)
969!!$      jj = jg(index)
970!!$!          write(*,*)'correspond',igrid, ireal,index,ij,jj
971!          if ( ij >= 1 .and. ij <= iim .and. jj >= 1 .and. jj <= jjm) then
[177]972!          write(*,*)'correspond',igrid, ireal,index,ij,jj
973            neighbours(igrid, i) = correspond(ij, jj)
[281]974!          endif
[177]975        endif
976      enddo
977    enddo
978
[281]979    write(*,*)'Neighbours = '
980
981    write(*,*)neighbours(1,8), neighbours(1,1),neighbours(1,2)
982    write(*,*)neighbours(1,7), ktindex(1), neighbours(1,3)
983    write(*,*)neighbours(1,6), neighbours(1,5),neighbours(1,4)
984
985    write(*,*)neighbours(250,8), neighbours(250,1),neighbours(250,2)
986    write(*,*)neighbours(250,7), ktindex(250), neighbours(250,3)
987    write(*,*)neighbours(250,6), neighbours(250,5),neighbours(250,4)
988
989 OPEN (unit=12, file="neighbours.9671")
990  DO i=1,knon
991     WRITE(12,*) '-----------------------------'
992     WRITE(12,'(I7,f8.5,   "    ",3I6)') knon, contfrac(i), &
993          & neighbours(i,8), neighbours(i,1), neighbours(i,2)
994     WRITE(12,'(f10.5,"         ",3I6)') lalo(i,2), neighbours(i,7), &
995          & ktindex(i), neighbours(i,3)
996     WRITE(12,'(f10.5,"         ",3I6)') lalo(i,1), neighbours(i,6), &
997          & neighbours(i,5), neighbours(i,3)
998  ENDDO
999  CLOSE(12)
1000
1001
[177]1002!
1003!  Allocation et calcul resolutions
1004    IF ( (.NOT.ALLOCATED(resolution))) THEN
1005      ALLOCATE(resolution(knon,2), stat = error)
1006      if (error /= 0) then
1007        abort_message='Pb allocation resolution'
1008        call abort_gcm(modname,abort_message,1)
1009      endif
1010    ENDIF
1011    do igrid = 1, knon
1012      ij = knindex(igrid)
1013      resolution(igrid,1) = cufi(ij)
1014      resolution(igrid,2) = cvfi(ij)
1015    enddo 
1016
1017  endif                          ! (fin debut)
1018
[90]1019!
1020! Appel a la routine sols continentaux
1021!
[223]1022  if (lafin) lrestart_write = .true.
1023  if (check) write(*,*)'lafin ',lafin,lrestart_write
[90]1024
[177]1025  petA_orc = petBcoef * dtime
1026  petB_orc = petAcoef
1027  peqA_orc = peqBcoef * dtime
1028  peqB_orc = peqAcoef
[90]1029
[281]1030  cdrag = 0.
1031  cdrag(1:knon) = tq_cdrag(1:knon)
1032
1033!  where(cdrag > 0.01)
1034!    cdrag = 0.01
1035!  endwhere
1036!  write(*,*)'Cdrag = ',minval(cdrag),maxval(cdrag)
1037
[201]1038!
1039! Init Orchidee
1040!
1041  if (debut) then
[281]1042    call intersurf_main (itime-1, iim, jjm+1, knon, ktindex, dtime, &
[177]1043     & lrestart_read, lrestart_write, lalo, &
1044     & contfrac, neighbours, resolution, date0, &
1045     & zlev,  u1_lay, v1_lay, spechum, temp_air, epot_air, ccanopy, &
[281]1046     & cdrag, petA_orc, peqA_orc, petB_orc, peqB_orc, &
[177]1047     & precip_rain, precip_snow, lwdown, swnet, swdown, p1lay, &
1048     & evap, fluxsens, fluxlat, coastalflow, riverflow, &
1049     & tsol_rad, tsurf_new, qsurf, albedo_out, emis_new, z0_new, &
1050     & lon_scat, lat_scat)
[201]1051  endif
[90]1052
[281]1053  call intersurf_main (itime, iim, jjm+1, knon, ktindex, dtime, &
[201]1054     & lrestart_read, lrestart_write, lalo, &
1055     & contfrac, neighbours, resolution, date0, &
1056     & zlev,  u1_lay, v1_lay, spechum, temp_air, epot_air, ccanopy, &
[281]1057     & cdrag, petA_orc, peqA_orc, petB_orc, peqB_orc, &
[201]1058     & precip_rain, precip_snow, lwdown, swnet, swdown, p1lay, &
1059     & evap, fluxsens, fluxlat, coastalflow, riverflow, &
1060     & tsol_rad, tsurf_new, qsurf, albedo_out, emis_new, z0_new, &
1061     & lon_scat, lat_scat)
1062
[281]1063!  alb_new(:) = (albedo_out(:,1) + albedo_out(:,2)) / 2.
1064  alb_new(1:knon) = albedo_out(1:knon,1)
1065  alblw(1:knon) = albedo_out(1:knon,2)
[177]1066
[275]1067! Convention orchidee: positif vers le haut
[223]1068  fluxsens = -1. * fluxsens
1069  fluxlat  = -1. * fluxlat
[281]1070!  evap     = -1. * evap
[223]1071
1072  if (debut) lrestart_read = .false.
1073
[90]1074  END SUBROUTINE interfsol
1075!
1076!#########################################################################
1077!
[177]1078  SUBROUTINE interfoce_cpl(itime, dtime, cumul, &
[98]1079      & klon, iim, jjm, nisurf, pctsrf, knon, knindex, rlon, rlat, &
[112]1080      & ocean, npas, nexca, debut, lafin, &
[98]1081      & swdown, lwdown, precip_rain, precip_snow, evap, tsurf, &
[177]1082      & fluxlat, fluxsens, fder, albsol, taux, tauy, zmasq, &
[274]1083      & tsurf_new, alb_new, pctsrf_new)
[90]1084
1085! Cette routine sert d'interface entre le modele atmospherique et un
[101]1086! coupleur avec un modele d'ocean 'complet' derriere
[90]1087!
[105]1088! Le modele de glace qu'il est prevu d'utiliser etant couple directement a
1089! l'ocean presentement, on va passer deux fois dans cette routine par pas de
1090! temps physique, une fois avec les points oceans et l'autre avec les points
1091! glace. A chaque pas de temps de couplage, la lecture des champs provenant
1092! du coupleur se fera "dans" l'ocean et l'ecriture des champs a envoyer
1093! au coupleur "dans" la glace. Il faut donc des tableaux de travail "tampons"
1094! dimensionnes sur toute la grille qui remplissent les champs sur les
1095! domaines ocean/glace quand il le faut. Il est aussi necessaire que l'index
1096! ocean soit traiter avant l'index glace (sinon tout intervertir)
1097!
1098!
[90]1099! L. Fairhead 02/2000
1100!
1101! input:
[98]1102!   itime        numero du pas de temps
1103!   iim, jjm     nbres de pts de grille
1104!   dtime        pas de tempsde la physique
1105!   klon         nombre total de points de grille
[90]1106!   nisurf       index de la surface a traiter (1 = sol continental)
[98]1107!   pctsrf       tableau des fractions de surface de chaque maille
1108!   knon         nombre de points de la surface a traiter
1109!   knindex      index des points de la surface a traiter
1110!   rlon         longitudes
1111!   rlat         latitudes
1112!   debut        logical: 1er appel a la physique
1113!   lafin        logical: dernier appel a la physique
[90]1114!   ocean        type d'ocean
[98]1115!   nexca        frequence de couplage
1116!   swdown       flux solaire entrant a la surface
[177]1117!   lwdown       flux IR net a la surface
[98]1118!   precip_rain  precipitation liquide
1119!   precip_snow  precipitation solide
1120!   evap         evaporation
1121!   tsurf        temperature de surface
1122!   fder         derivee dF/dT
1123!   albsol       albedo du sol (coherent avec swdown)
1124!   taux         tension de vent en x
1125!   tauy         tension de vent en y
1126!   nexca        frequence de couplage
[105]1127!   zmasq        masque terre/ocean
[90]1128!
[98]1129!
[90]1130! output:
[98]1131!   tsurf_new    temperature au sol
1132!   alb_new      albedo
1133!   pctsrf_new   nouvelle repartition des surfaces
1134!   alb_ice      albedo de la glace
[90]1135!
1136
[98]1137
[90]1138! Parametres d'entree
[98]1139  integer, intent(IN) :: itime
1140  integer, intent(IN) :: iim, jjm
1141  real, intent(IN) :: dtime
1142  integer, intent(IN) :: klon
[90]1143  integer, intent(IN) :: nisurf
[98]1144  integer, intent(IN) :: knon
1145  real, dimension(klon,nbsrf), intent(IN) :: pctsrf
[147]1146  integer, dimension(klon), intent(in) :: knindex
[98]1147  logical, intent(IN) :: debut, lafin
1148  real, dimension(klon), intent(IN) :: rlon, rlat
[90]1149  character (len = 6)  :: ocean
[147]1150  real, dimension(klon), intent(IN) :: lwdown, swdown
1151  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
1152  real, dimension(klon), intent(IN) :: tsurf, fder, albsol, taux, tauy
[140]1153  INTEGER              :: nexca, npas, kstep
[105]1154  real, dimension(klon), intent(IN) :: zmasq
[177]1155  real, dimension(klon), intent(IN) :: fluxlat, fluxsens
1156  logical, intent(IN)               :: cumul
[147]1157  real, dimension(klon), intent(INOUT) :: evap
[98]1158
[90]1159! Parametres de sortie
[274]1160  real, dimension(klon), intent(OUT):: tsurf_new, alb_new
[98]1161  real, dimension(klon,nbsrf), intent(OUT) :: pctsrf_new
[90]1162
1163! Variables locales
[140]1164  integer                    :: j, error, sum_error, ig, cpl_index,i
[98]1165  character (len = 20) :: modname = 'interfoce_cpl'
1166  character (len = 80) :: abort_message
[179]1167  logical,save              :: check = .true.
[98]1168! variables pour moyenner les variables de couplage
[105]1169  real, allocatable, dimension(:,:),save :: cpl_sols, cpl_nsol, cpl_rain
1170  real, allocatable, dimension(:,:),save :: cpl_snow, cpl_evap, cpl_tsol
1171  real, allocatable, dimension(:,:),save :: cpl_fder, cpl_albe, cpl_taux
1172  real, allocatable, dimension(:,:),save :: cpl_tauy, cpl_rriv, cpl_rcoa
1173! variables tampons avant le passage au coupleur
1174  real, allocatable, dimension(:,:,:),save :: tmp_sols, tmp_nsol, tmp_rain
1175  real, allocatable, dimension(:,:,:),save :: tmp_snow, tmp_evap, tmp_tsol
1176  real, allocatable, dimension(:,:,:),save :: tmp_fder, tmp_albe, tmp_taux
1177  real, allocatable, dimension(:,:,:),save :: tmp_tauy, tmp_rriv, tmp_rcoa
[98]1178! variables a passer au coupleur
[105]1179  real, dimension(iim, jjm+1) :: wri_sol_ice, wri_sol_sea, wri_nsol_ice
1180  real, dimension(iim, jjm+1) :: wri_nsol_sea, wri_fder_ice, wri_evap_ice
[177]1181  REAL, DIMENSION(iim, jjm+1) :: wri_evap_sea, wri_rcoa, wri_rriv
1182  REAL, DIMENSION(iim, jjm+1) :: wri_rain, wri_snow, wri_taux, wri_tauy
1183  REAL, DIMENSION(iim, jjm+1) :: wri_tauxx, wri_tauyy, wri_tauzz
1184  REAL, DIMENSION(iim, jjm+1) :: tmp_lon, tmp_lat
[98]1185! variables relues par le coupleur
[105]1186! read_sic = fraction de glace
1187! read_sit = temperature de glace
1188  real, allocatable, dimension(:,:),save :: read_sst, read_sic, read_sit
1189  real, allocatable, dimension(:,:),save :: read_alb_sic
[98]1190! variable tampon
[140]1191  real, dimension(klon)       :: tamp_sic
1192! sauvegarde des fractions de surface d'un pas de temps a l'autre apres
1193! l'avoir lu
1194  real, allocatable,dimension(:,:),save :: pctsrf_sav
[105]1195  real, dimension(iim, jjm+1, 2) :: tamp_srf
1196  integer, allocatable, dimension(:), save :: tamp_ind
1197  real, allocatable, dimension(:,:),save :: tamp_zmasq
1198  real, dimension(iim, jjm+1) :: deno
[137]1199  integer                     :: idtime
[179]1200  integer, allocatable,dimension(:),save :: unity
[131]1201!
1202  logical, save    :: first_appel = .true.
[179]1203  logical,save          :: print
1204!maf
1205! variables pour avoir une sortie IOIPSL des champs echanges
1206  CHARACTER*80,SAVE :: clintocplnam, clfromcplnam
1207  INTEGER, SAVE :: jf,nhoridct,nidct
1208  INTEGER, SAVE :: nhoridcs,nidcs
1209  INTEGER :: ndexct(iim*(jjm+1)),ndexcs(iim*(jjm+1))
1210  REAL :: zx_lon(iim,jjm+1), zx_lat(iim,jjm+1), zjulian
1211  include 'param_cou.h'
1212  include 'inc_cpl.h'
1213  include 'temps.h'
[98]1214!
[90]1215! Initialisation
[98]1216!
[131]1217  if (check) write(*,*)'Entree ',modname,'nisurf = ',nisurf
1218 
1219  if (first_appel) then
[140]1220    error = 0
1221    allocate(unity(klon), stat = error)
1222    if ( error  /=0) then
1223      abort_message='Pb allocation variable unity'
1224      call abort_gcm(modname,abort_message,1)
1225    endif
[143]1226    allocate(pctsrf_sav(klon,nbsrf), stat = error)
[140]1227    if ( error  /=0) then
1228      abort_message='Pb allocation variable pctsrf_sav'
1229      call abort_gcm(modname,abort_message,1)
1230    endif
[143]1231    pctsrf_sav = 0.
[140]1232
1233    do ig = 1, klon
1234      unity(ig) = ig
1235    enddo
[98]1236    sum_error = 0
[147]1237    allocate(cpl_sols(klon,2), stat = error); sum_error = sum_error + error
1238    allocate(cpl_nsol(klon,2), stat = error); sum_error = sum_error + error
1239    allocate(cpl_rain(klon,2), stat = error); sum_error = sum_error + error
1240    allocate(cpl_snow(klon,2), stat = error); sum_error = sum_error + error
1241    allocate(cpl_evap(klon,2), stat = error); sum_error = sum_error + error
1242    allocate(cpl_tsol(klon,2), stat = error); sum_error = sum_error + error
1243    allocate(cpl_fder(klon,2), stat = error); sum_error = sum_error + error
1244    allocate(cpl_albe(klon,2), stat = error); sum_error = sum_error + error
1245    allocate(cpl_taux(klon,2), stat = error); sum_error = sum_error + error
1246    allocate(cpl_tauy(klon,2), stat = error); sum_error = sum_error + error
1247    allocate(cpl_rcoa(klon,2), stat = error); sum_error = sum_error + error
1248    allocate(cpl_rriv(klon,2), stat = error); sum_error = sum_error + error
[105]1249    allocate(read_sst(iim, jjm+1), stat = error); sum_error = sum_error + error
1250    allocate(read_sic(iim, jjm+1), stat = error); sum_error = sum_error + error
1251    allocate(read_sit(iim, jjm+1), stat = error); sum_error = sum_error + error
1252    allocate(read_alb_sic(iim, jjm+1), stat = error); sum_error = sum_error + error
1253
[98]1254    if (sum_error /= 0) then
1255      abort_message='Pb allocation variables couplees'
1256      call abort_gcm(modname,abort_message,1)
1257    endif
[105]1258    cpl_sols = 0.; cpl_nsol = 0.; cpl_rain = 0.; cpl_snow = 0.
1259    cpl_evap = 0.; cpl_tsol = 0.; cpl_fder = 0.; cpl_albe = 0.
1260    cpl_taux = 0.; cpl_tauy = 0.; cpl_rriv = 0.; cpl_rcoa = 0.
1261
1262    sum_error = 0
1263    allocate(tamp_ind(klon), stat = error); sum_error = sum_error + error
1264    allocate(tamp_zmasq(iim, jjm+1), stat = error); sum_error = sum_error + error   
1265    do ig = 1, klon
1266      tamp_ind(ig) = ig
1267    enddo
1268    call gath2cpl(zmasq, tamp_zmasq, klon, klon, iim, jjm, tamp_ind)
[98]1269!
1270! initialisation couplage
1271!
[137]1272    idtime = int(dtime)
1273    call inicma(npas , nexca, idtime,(jjm+1)*iim)
[98]1274
[179]1275!
1276! initialisation sorties netcdf
1277!
1278    CALL ymds2ju(anne_ini, 1, 1, 0.0, zjulian)
1279    zjulian = zjulian + day_ini
1280    CALL gr_fi_ecrit(1,klon,iim,jjm+1,rlon,zx_lon)
1281    DO i = 1, iim
1282      zx_lon(i,1) = rlon(i+1)
1283      zx_lon(i,jjm+1) = rlon(i+1)
1284    ENDDO
1285    CALL gr_fi_ecrit(1,klon,iim,jjm+1,rlat,zx_lat)
1286    clintocplnam="cpl_atm_tauflx"
1287    CALL histbeg(clintocplnam, iim,zx_lon,jjm+1,zx_lat,1,iim,1,jjm+1, &
1288       & 0,zjulian,dtime,nhoridct,nidct)
1289! no vertical axis
1290    CALL histdef(nidct, 'tauxe','tauxe', &
1291         & "-",iim, jjm+1, nhoridct, 1, 1, 1, -99, 32, "inst", dtime,dtime)
1292    CALL histdef(nidct, 'tauyn','tauyn', &
1293         & "-",iim, jjm+1, nhoridct, 1, 1, 1, -99, 32, "inst", dtime,dtime)
1294    CALL histdef(nidct, 'tmp_lon','tmp_lon', &
1295         & "-",iim, jjm+1, nhoridct, 1, 1, 1, -99, 32, "inst", dtime,dtime)
1296    CALL histdef(nidct, 'tmp_lat','tmp_lat', &
1297         & "-",iim, jjm+1, nhoridct, 1, 1, 1, -99, 32, "inst", dtime,dtime)
1298    DO jf=1,jpflda2o1 + jpflda2o2
1299      CALL histdef(nidct, cl_writ(jf),cl_writ(jf), &
1300         & "-",iim, jjm+1, nhoridct, 1, 1, 1, -99, 32, "inst", dtime,dtime)
1301    END DO
1302    CALL histend(nidct)
1303    CALL histsync(nidct)
1304
1305    clfromcplnam="cpl_atm_sst"
1306    CALL histbeg(clfromcplnam, iim,zx_lon,jjm+1,zx_lat,1,iim,1,jjm+1, &
1307       & 0,zjulian,dtime,nhoridcs,nidcs)
1308! no vertical axis
1309    DO jf=1,jpfldo2a
1310      CALL histdef(nidcs, cl_read(jf),cl_read(jf), &
1311         & "-",iim, jjm+1, nhoridcs, 1, 1, 1, -99, 32, "inst", dtime,dtime)
1312    END DO
1313    CALL histend(nidcs)
1314    CALL histsync(nidcs)
1315
[131]1316    first_appel = .false.
1317  endif ! fin if (first_appel)
[98]1318
[157]1319! Initialisations
[90]1320
[112]1321! calcul des fluxs a passer
[90]1322
[140]1323  cpl_index = 1
1324  if (nisurf == is_sic) cpl_index = 2
[177]1325  if (cumul) then
[179]1326    if (check) write(*,*) modname, 'cumul des champs'
[177]1327    do ig = 1, knon
1328      cpl_sols(ig,cpl_index) = cpl_sols(ig,cpl_index) &
1329       &                          + swdown(ig)      / FLOAT(nexca)
1330      cpl_nsol(ig,cpl_index) = cpl_nsol(ig,cpl_index) &
1331       &                          + (lwdown(ig) + fluxlat(ig) +fluxsens(ig))&
1332       &                                / FLOAT(nexca)
1333      cpl_rain(ig,cpl_index) = cpl_rain(ig,cpl_index) &
1334       &                          + precip_rain(ig) / FLOAT(nexca)
1335      cpl_snow(ig,cpl_index) = cpl_snow(ig,cpl_index) &
1336       &                          + precip_snow(ig) / FLOAT(nexca)
1337      cpl_evap(ig,cpl_index) = cpl_evap(ig,cpl_index) &
1338       &                          + evap(ig)        / FLOAT(nexca)
1339      cpl_tsol(ig,cpl_index) = cpl_tsol(ig,cpl_index) &
1340       &                          + tsurf(ig)       / FLOAT(nexca)
1341      cpl_fder(ig,cpl_index) = cpl_fder(ig,cpl_index) &
1342       &                          + fder(ig)        / FLOAT(nexca)
1343      cpl_albe(ig,cpl_index) = cpl_albe(ig,cpl_index) &
1344       &                          + albsol(ig)      / FLOAT(nexca)
1345      cpl_taux(ig,cpl_index) = cpl_taux(ig,cpl_index) &
1346       &                          + taux(ig)        / FLOAT(nexca)
1347      cpl_tauy(ig,cpl_index) = cpl_tauy(ig,cpl_index) &
1348       &                          + tauy(ig)        / FLOAT(nexca)
1349      cpl_rriv(ig,cpl_index) = cpl_rriv(ig,cpl_index) &
[277]1350       &                          + riverflow(ig)   / FLOAT(nexca)/dtime
[177]1351      cpl_rcoa(ig,cpl_index) = cpl_rcoa(ig,cpl_index) &
[277]1352       &                          + coastalflow(ig) / FLOAT(nexca)/dtime
[177]1353    enddo
1354  endif
[98]1355
[138]1356  if (mod(itime, nexca) == 1) then
[98]1357!
[179]1358! Demande des champs au coupleur
[98]1359!
[105]1360! Si le domaine considere est l'ocean, on lit les champs venant du coupleur
1361!
[177]1362    if (nisurf == is_oce .and. .not. cumul) then
[147]1363      if (check) write(*,*)'rentree fromcpl, itime-1 = ',itime-1
[138]1364      call fromcpl(itime-1,(jjm+1)*iim,                                  &
[105]1365     &        read_sst, read_sic, read_sit, read_alb_sic)
[179]1366!
1367! sorties NETCDF des champs recus
1368!
1369      ndexcs(:)=0
1370      CALL histwrite(nidcs,cl_read(1),itime,read_sst,iim*(jjm+1),ndexcs)
1371      CALL histwrite(nidcs,cl_read(2),itime,read_sic,iim*(jjm+1),ndexcs)
[180]1372      CALL histwrite(nidcs,cl_read(3),itime,read_alb_sic,iim*(jjm+1),ndexcs)
1373      CALL histwrite(nidcs,cl_read(4),itime,read_sit,iim*(jjm+1),ndexcs)
[179]1374      CALL histsync(nidcs)
1375! pas utile      IF (npas-itime.LT.nexca )CALL histclo(nidcs)
1376
[105]1377      do j = 1, jjm + 1
1378        do ig = 1, iim
1379          if (abs(1. - read_sic(ig,j)) < 0.00001) then
1380            read_sst(ig,j) = RTT - 1.8
1381            read_sit(ig,j) = read_sit(ig,j) / read_sic(ig,j)
1382            read_alb_sic(ig,j) = read_alb_sic(ig,j) / read_sic(ig,j)
1383          else if (abs(read_sic(ig,j)) < 0.00001) then
1384            read_sst(ig,j) = read_sst(ig,j) / (1. - read_sic(ig,j))
1385            read_sit(ig,j) = read_sst(ig,j)
1386            read_alb_sic(ig,j) =  0.6
1387          else
1388            read_sst(ig,j) = read_sst(ig,j) / (1. - read_sic(ig,j))
1389            read_sit(ig,j) = read_sit(ig,j) / read_sic(ig,j)
1390            read_alb_sic(ig,j) = read_alb_sic(ig,j) / read_sic(ig,j)
1391          endif
1392        enddo
1393      enddo
[140]1394!
1395! transformer read_sic en pctsrf_sav
1396!
[157]1397      call cpl2gath(read_sic, tamp_sic , klon, klon,iim,jjm, unity)
1398      do ig = 1, klon
1399        IF (pctsrf(ig,is_oce) > epsfra .OR.            &
[140]1400     &             pctsrf(ig,is_sic) > epsfra) THEN
[143]1401          pctsrf_sav(ig,is_sic) = (pctsrf(ig,is_oce) + pctsrf(ig,is_sic)) &
1402     &                               * tamp_sic(ig)
1403          pctsrf_sav(ig,is_oce) = (pctsrf(ig,is_oce) + pctsrf(ig,is_sic)) &
1404     &                        - pctsrf_sav(ig,is_sic)
1405        endif
1406      enddo
[157]1407!
1408! Pour rattraper des erreurs d'arrondis
1409!
[179]1410      where (abs(pctsrf_sav(:,is_sic)) .le. 2.*epsilon(pctsrf_sav(1,is_sic)))
[157]1411        pctsrf_sav(:,is_sic) = 0.
1412        pctsrf_sav(:,is_oce) = pctsrf(:,is_oce) + pctsrf(:,is_sic)
1413      endwhere
[179]1414      where (abs(pctsrf_sav(:,is_oce)) .le. 2.*epsilon(pctsrf_sav(1,is_oce)))
[157]1415        pctsrf_sav(:,is_sic) = pctsrf(:,is_oce) + pctsrf(:,is_sic)
1416        pctsrf_sav(:,is_oce) = 0.
1417      endwhere
1418      if (minval(pctsrf_sav(:,is_oce)) < 0.) then
[143]1419        write(*,*)'Pb fraction ocean inferieure a 0'
[157]1420        write(*,*)'au point ',minloc(pctsrf_sav(:,is_oce))
1421        write(*,*)'valeur = ',minval(pctsrf_sav(:,is_oce))
[143]1422        abort_message = 'voir ci-dessus'
1423        call abort_gcm(modname,abort_message,1)
1424      endif
[157]1425      if (minval(pctsrf_sav(:,is_sic)) < 0.) then
[143]1426        write(*,*)'Pb fraction glace inferieure a 0'
[157]1427        write(*,*)'au point ',minloc(pctsrf_sav(:,is_sic))
1428        write(*,*)'valeur = ',minval(pctsrf_sav(:,is_sic))
[143]1429        abort_message = 'voir ci-dessus'
1430        call abort_gcm(modname,abort_message,1)
1431      endif
[105]1432    endif
[138]1433  endif                         ! fin mod(itime, nexca) == 1
1434
1435  if (mod(itime, nexca) == 0) then
[105]1436!
[138]1437! allocation memoire
[180]1438    if (nisurf == is_oce .and. (.not. cumul) ) then
[147]1439      sum_error = 0
1440      allocate(tmp_sols(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1441      allocate(tmp_nsol(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1442      allocate(tmp_rain(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1443      allocate(tmp_snow(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1444      allocate(tmp_evap(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1445      allocate(tmp_tsol(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1446      allocate(tmp_fder(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1447      allocate(tmp_albe(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1448      allocate(tmp_taux(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1449      allocate(tmp_tauy(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1450      allocate(tmp_rriv(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1451      allocate(tmp_rcoa(iim,jjm+1,2), stat=error); sum_error = sum_error + error
1452      if (sum_error /= 0) then
1453        abort_message='Pb allocation variables couplees pour l''ecriture'
1454        call abort_gcm(modname,abort_message,1)
1455      endif
[138]1456    endif
1457
1458!
1459! Mise sur la bonne grille des champs a passer au coupleur
1460!
[147]1461    cpl_index = 1
1462    if (nisurf == is_sic) cpl_index = 2
1463    call gath2cpl(cpl_sols(1,cpl_index), tmp_sols(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1464    call gath2cpl(cpl_nsol(1,cpl_index), tmp_nsol(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1465    call gath2cpl(cpl_rain(1,cpl_index), tmp_rain(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1466    call gath2cpl(cpl_snow(1,cpl_index), tmp_snow(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1467    call gath2cpl(cpl_evap(1,cpl_index), tmp_evap(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1468    call gath2cpl(cpl_tsol(1,cpl_index), tmp_tsol(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1469    call gath2cpl(cpl_fder(1,cpl_index), tmp_fder(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1470    call gath2cpl(cpl_albe(1,cpl_index), tmp_albe(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1471    call gath2cpl(cpl_taux(1,cpl_index), tmp_taux(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1472    call gath2cpl(cpl_tauy(1,cpl_index), tmp_tauy(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1473    call gath2cpl(cpl_rriv(1,cpl_index), tmp_rriv(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
1474    call gath2cpl(cpl_rcoa(1,cpl_index), tmp_rcoa(1,1,cpl_index), klon, knon,iim,jjm,                  knindex)
[138]1475
1476!
[105]1477! Si le domaine considere est la banquise, on envoie les champs au coupleur
1478!
[177]1479    if (nisurf == is_sic .and. cumul) then
[105]1480      wri_rain = 0.; wri_snow = 0.; wri_rcoa = 0.; wri_rriv = 0.
1481      wri_taux = 0.; wri_tauy = 0.
1482      call gath2cpl(pctsrf(1,is_oce), tamp_srf(1,1,1), klon, klon, iim, jjm, tamp_ind)
1483      call gath2cpl(pctsrf(1,is_sic), tamp_srf(1,1,2), klon, klon, iim, jjm, tamp_ind)
[98]1484
[105]1485      wri_sol_ice = tmp_sols(:,:,2)
1486      wri_sol_sea = tmp_sols(:,:,1)
1487      wri_nsol_ice = tmp_nsol(:,:,2)
1488      wri_nsol_sea = tmp_nsol(:,:,1)
1489      wri_fder_ice = tmp_fder(:,:,2)
1490      wri_evap_ice = tmp_evap(:,:,2)
1491      wri_evap_sea = tmp_evap(:,:,1)
1492      where (tamp_zmasq /= 1.)
1493        deno =  tamp_srf(:,:,1) + tamp_srf(:,:,2)
1494        wri_rain = tmp_rain(:,:,1) * tamp_srf(:,:,1) / deno +    &
1495      &            tmp_rain(:,:,2) * tamp_srf(:,:,2) / deno
1496        wri_snow = tmp_snow(:,:,1) * tamp_srf(:,:,1) / deno +    &
1497      &            tmp_snow(:,:,2) * tamp_srf(:,:,2) / deno
1498        wri_rriv = tmp_rriv(:,:,1) * tamp_srf(:,:,1) / deno +    &
1499      &            tmp_rriv(:,:,2) * tamp_srf(:,:,2) / deno
1500        wri_rcoa = tmp_rcoa(:,:,1) * tamp_srf(:,:,1) / deno +    &
1501      &            tmp_rcoa(:,:,2) * tamp_srf(:,:,2) / deno
1502        wri_taux = tmp_taux(:,:,1) * tamp_srf(:,:,1) / deno +    &
1503      &            tmp_taux(:,:,2) * tamp_srf(:,:,2) / deno
1504        wri_tauy = tmp_tauy(:,:,1) * tamp_srf(:,:,1) / deno +    &
1505      &            tmp_tauy(:,:,2) * tamp_srf(:,:,2) / deno
1506      endwhere
[177]1507!
1508! on passe les coordonnées de la grille
1509!
[179]1510
1511      CALL gr_fi_ecrit(1,klon,iim,jjm+1,rlon,tmp_lon)
1512      CALL gr_fi_ecrit(1,klon,iim,jjm+1,rlat,tmp_lat)
1513
[177]1514      DO i = 1, iim
1515        tmp_lon(i,1) = rlon(i+1)
1516        tmp_lon(i,jjm + 1) = rlon(i+1)
1517      ENDDO
1518!
[179]1519! sortie netcdf des champs pour le changement de repere
1520!
1521      ndexct(:)=0
1522      CALL histwrite(nidct,'tauxe',itime,wri_taux,iim*(jjm+1),ndexct)
1523      CALL histwrite(nidct,'tauyn',itime,wri_tauy,iim*(jjm+1),ndexct)
1524      CALL histwrite(nidct,'tmp_lon',itime,tmp_lon,iim*(jjm+1),ndexct)
1525      CALL histwrite(nidct,'tmp_lat',itime,tmp_lat,iim*(jjm+1),ndexct)
1526
1527!
[177]1528! calcul 3 coordonnées du vent
1529!
1530      CALL atm2geo (iim , jjm + 1, wri_taux, wri_tauy, tmp_lon, tmp_lat, &
1531         & wri_tauxx, wri_tauyy, wri_tauzz )
[179]1532!
1533! sortie netcdf des champs apres changement de repere et juste avant
1534! envoi au coupleur
1535!
1536      CALL histwrite(nidct,cl_writ(1),itime,wri_sol_ice,iim*(jjm+1),ndexct)
1537      CALL histwrite(nidct,cl_writ(2),itime,wri_sol_sea,iim*(jjm+1),ndexct)
1538      CALL histwrite(nidct,cl_writ(3),itime,wri_nsol_ice,iim*(jjm+1),ndexct)
1539      CALL histwrite(nidct,cl_writ(4),itime,wri_nsol_sea,iim*(jjm+1),ndexct)
1540      CALL histwrite(nidct,cl_writ(5),itime,wri_fder_ice,iim*(jjm+1),ndexct)
1541      CALL histwrite(nidct,cl_writ(6),itime,wri_evap_ice,iim*(jjm+1),ndexct)
1542      CALL histwrite(nidct,cl_writ(7),itime,wri_evap_sea,iim*(jjm+1),ndexct)
1543      CALL histwrite(nidct,cl_writ(8),itime,wri_rain,iim*(jjm+1),ndexct)
1544      CALL histwrite(nidct,cl_writ(9),itime,wri_snow,iim*(jjm+1),ndexct)
1545      CALL histwrite(nidct,cl_writ(10),itime,wri_rcoa,iim*(jjm+1),ndexct)
1546      CALL histwrite(nidct,cl_writ(11),itime,wri_rriv,iim*(jjm+1),ndexct)
1547      CALL histwrite(nidct,cl_writ(12),itime,wri_tauxx,iim*(jjm+1),ndexct)
1548      CALL histwrite(nidct,cl_writ(13),itime,wri_tauyy,iim*(jjm+1),ndexct)
1549      CALL histwrite(nidct,cl_writ(14),itime,wri_tauzz,iim*(jjm+1),ndexct)
1550      CALL histwrite(nidct,cl_writ(15),itime,wri_tauxx,iim*(jjm+1),ndexct)
1551      CALL histwrite(nidct,cl_writ(16),itime,wri_tauyy,iim*(jjm+1),ndexct)
1552      CALL histwrite(nidct,cl_writ(17),itime,wri_tauzz,iim*(jjm+1),ndexct)
1553      CALL histsync(nidct)
1554! pas utile      IF (lafin) CALL histclo(nidct)
[105]1555
1556      call intocpl(itime, (jjm+1)*iim, wri_sol_ice, wri_sol_sea, wri_nsol_ice,&
1557      & wri_nsol_sea, wri_fder_ice, wri_evap_ice, wri_evap_sea, wri_rain, &
[177]1558      & wri_snow, wri_rcoa, wri_rriv, wri_tauxx, wri_tauyy, wri_tauzz, &
1559      & wri_tauxx, wri_tauyy, wri_tauzz,lafin )
[105]1560      cpl_sols = 0.; cpl_nsol = 0.; cpl_rain = 0.; cpl_snow = 0.
1561      cpl_evap = 0.; cpl_tsol = 0.; cpl_fder = 0.; cpl_albe = 0.
1562      cpl_taux = 0.; cpl_tauy = 0.; cpl_rriv = 0.; cpl_rcoa = 0.
1563!
1564! deallocation memoire variables temporaires
1565!
1566      sum_error = 0
1567      deallocate(tmp_sols, stat=error); sum_error = sum_error + error
1568      deallocate(tmp_nsol, stat=error); sum_error = sum_error + error
1569      deallocate(tmp_rain, stat=error); sum_error = sum_error + error
1570      deallocate(tmp_snow, stat=error); sum_error = sum_error + error
1571      deallocate(tmp_evap, stat=error); sum_error = sum_error + error
1572      deallocate(tmp_fder, stat=error); sum_error = sum_error + error
1573      deallocate(tmp_tsol, stat=error); sum_error = sum_error + error
1574      deallocate(tmp_albe, stat=error); sum_error = sum_error + error
1575      deallocate(tmp_taux, stat=error); sum_error = sum_error + error
1576      deallocate(tmp_tauy, stat=error); sum_error = sum_error + error
1577      deallocate(tmp_rriv, stat=error); sum_error = sum_error + error
1578      deallocate(tmp_rcoa, stat=error); sum_error = sum_error + error
1579      if (sum_error /= 0) then
1580        abort_message='Pb deallocation variables couplees'
1581        call abort_gcm(modname,abort_message,1)
1582      endif
1583
1584    endif
1585
[138]1586  endif            ! fin (mod(itime, nexca) == 0)
[105]1587!
1588! on range les variables lues/sauvegardees dans les bonnes variables de sortie
1589!
1590  if (nisurf == is_oce) then
[98]1591    call cpl2gath(read_sst, tsurf_new, klon, knon,iim,jjm, knindex)
[105]1592  else if (nisurf == is_sic) then
[140]1593    call cpl2gath(read_sit, tsurf_new, klon, knon,iim,jjm, knindex)
1594    call cpl2gath(read_alb_sic, alb_new, klon, knon,iim,jjm, knindex)
[98]1595  endif
[140]1596  pctsrf_new(:,nisurf) = pctsrf_sav(:,nisurf)
[115]1597 
1598!  if (lafin) call quitcpl
[98]1599
[90]1600  END SUBROUTINE interfoce_cpl
1601!
1602!#########################################################################
1603!
[98]1604
[90]1605  SUBROUTINE interfoce_slab(nisurf)
1606
1607! Cette routine sert d'interface entre le modele atmospherique et un
1608! modele de 'slab' ocean
1609!
1610! L. Fairhead 02/2000
1611!
1612! input:
1613!   nisurf       index de la surface a traiter (1 = sol continental)
1614!
1615! output:
1616!
1617
1618! Parametres d'entree
1619  integer, intent(IN) :: nisurf
1620
1621  END SUBROUTINE interfoce_slab
1622!
1623!#########################################################################
1624!
1625  SUBROUTINE interfoce_lim(itime, dtime, jour, &
1626     & klon, nisurf, knon, knindex, &
1627     & debut,  &
[109]1628     & lmt_sst, pctsrf_new)
[90]1629
1630! Cette routine sert d'interface entre le modele atmospherique et un fichier
1631! de conditions aux limites
1632!
1633! L. Fairhead 02/2000
1634!
1635! input:
1636!   itime        numero du pas de temps courant
1637!   dtime        pas de temps de la physique (en s)
1638!   jour         jour a lire dans l'annee
1639!   nisurf       index de la surface a traiter (1 = sol continental)
1640!   knon         nombre de points dans le domaine a traiter
1641!   knindex      index des points de la surface a traiter
1642!   klon         taille de la grille
1643!   debut        logical: 1er appel a la physique (initialisation)
1644!
1645! output:
1646!   lmt_sst      SST lues dans le fichier de CL
1647!   pctsrf_new   sous-maille fractionnelle
1648!
1649
1650
1651! Parametres d'entree
1652  integer, intent(IN) :: itime
1653  real   , intent(IN) :: dtime
1654  integer, intent(IN) :: jour
1655  integer, intent(IN) :: nisurf
1656  integer, intent(IN) :: knon
1657  integer, intent(IN) :: klon
[147]1658  integer, dimension(klon), intent(in) :: knindex
[90]1659  logical, intent(IN) :: debut
1660
1661! Parametres de sortie
[147]1662  real, intent(out), dimension(klon) :: lmt_sst
[90]1663  real, intent(out), dimension(klon,nbsrf) :: pctsrf_new
1664
1665! Variables locales
1666  integer     :: ii
[112]1667  INTEGER,save :: lmt_pas     ! frequence de lecture des conditions limites
[90]1668                             ! (en pas de physique)
1669  logical,save :: deja_lu    ! pour indiquer que le jour a lire a deja
1670                             ! lu pour une surface precedente
1671  integer,save :: jour_lu
1672  integer      :: ierr
1673  character (len = 20) :: modname = 'interfoce_lim'
1674  character (len = 80) :: abort_message
[179]1675  character (len = 20),save :: fich ='limit.nc'
1676  logical, save     :: newlmt = .TRUE.
1677  logical, save     :: check = .true.
[90]1678! Champs lus dans le fichier de CL
[147]1679  real, allocatable , save, dimension(:) :: sst_lu, rug_lu, nat_lu
[90]1680  real, allocatable , save, dimension(:,:) :: pct_tmp
1681!
1682! quelques variables pour netcdf
1683!
1684#include "netcdf.inc"
1685  integer              :: nid, nvarid
1686  integer, dimension(2) :: start, epais
1687!
1688! Fin déclaration
1689!
1690   
[112]1691  if (debut .and. .not. allocated(sst_lu)) then
[90]1692    lmt_pas = nint(86400./dtime * 1.0) ! pour une lecture une fois par jour
1693    jour_lu = jour - 1
1694    allocate(sst_lu(klon))
1695    allocate(nat_lu(klon))
1696    allocate(pct_tmp(klon,nbsrf))
1697  endif
1698
1699  if ((jour - jour_lu) /= 0) deja_lu = .false.
1700 
[171]1701  if (check) write(*,*)modname,' :: jour, jour_lu, deja_lu', jour, jour_lu, deja_lu
[140]1702  if (check) write(*,*)modname,' :: itime, lmt_pas ', itime, lmt_pas,dtime
[90]1703
1704! Tester d'abord si c'est le moment de lire le fichier
1705  if (mod(itime-1, lmt_pas) == 0 .and. .not. deja_lu) then
1706!
1707! Ouverture du fichier
1708!
[112]1709    fich = trim(fich)
[90]1710    ierr = NF_OPEN (fich, NF_NOWRITE,nid)
1711    if (ierr.NE.NF_NOERR) then
1712      abort_message = 'Pb d''ouverture du fichier de conditions aux limites'
1713      call abort_gcm(modname,abort_message,1)
1714    endif
1715!
1716! La tranche de donnees a lire:
1717!
1718    start(1) = 1
1719    start(2) = jour + 1
1720    epais(1) = klon
1721    epais(2) = 1
1722!
1723    if (newlmt) then
1724!
1725! Fraction "ocean"
1726!
1727      ierr = NF_INQ_VARID(nid, 'FOCE', nvarid)
1728      if (ierr /= NF_NOERR) then
1729        abort_message = 'Le champ <FOCE> est absent'
1730        call abort_gcm(modname,abort_message,1)
1731      endif
1732#ifdef NC_DOUBLE
[112]1733      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais,pct_tmp(1,is_oce))
[90]1734#else
[112]1735      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais,pct_tmp(1,is_oce))
[90]1736#endif
1737      if (ierr /= NF_NOERR) then
1738        abort_message = 'Lecture echouee pour <FOCE>'
1739        call abort_gcm(modname,abort_message,1)
1740      endif
1741!
1742! Fraction "glace de mer"
1743!
1744      ierr = NF_INQ_VARID(nid, 'FSIC', nvarid)
1745      if (ierr /= NF_NOERR) then
1746        abort_message = 'Le champ <FSIC> est absent'
1747        call abort_gcm(modname,abort_message,1)
1748      endif
1749#ifdef NC_DOUBLE
[112]1750      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais,pct_tmp(1,is_sic))
[90]1751#else
[112]1752      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais,pct_tmp(1,is_sic))
[90]1753#endif
1754      if (ierr /= NF_NOERR) then
1755        abort_message = 'Lecture echouee pour <FSIC>'
1756        call abort_gcm(modname,abort_message,1)
1757      endif
1758!
1759! Fraction "terre"
1760!
1761      ierr = NF_INQ_VARID(nid, 'FTER', nvarid)
1762      if (ierr /= NF_NOERR) then
1763        abort_message = 'Le champ <FTER> est absent'
1764        call abort_gcm(modname,abort_message,1)
1765      endif
1766#ifdef NC_DOUBLE
[112]1767      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais,pct_tmp(1,is_ter))
[90]1768#else
[112]1769      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais,pct_tmp(1,is_ter))
[90]1770#endif
1771      if (ierr /= NF_NOERR) then
1772        abort_message = 'Lecture echouee pour <FTER>'
1773        call abort_gcm(modname,abort_message,1)
1774      endif
1775!
1776! Fraction "glacier terre"
1777!
1778      ierr = NF_INQ_VARID(nid, 'FLIC', nvarid)
1779      if (ierr /= NF_NOERR) then
1780        abort_message = 'Le champ <FLIC> est absent'
1781        call abort_gcm(modname,abort_message,1)
1782      endif
1783#ifdef NC_DOUBLE
[112]1784      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais,pct_tmp(1,is_lic))
[90]1785#else
[112]1786      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais,pct_tmp(1,is_lic))
[90]1787#endif
1788      if (ierr /= NF_NOERR) then
1789        abort_message = 'Lecture echouee pour <FLIC>'
1790        call abort_gcm(modname,abort_message,1)
1791      endif
1792!
1793    else  ! on en est toujours a rnatur
1794!
1795      ierr = NF_INQ_VARID(nid, 'NAT', nvarid)
1796      if (ierr /= NF_NOERR) then
1797        abort_message = 'Le champ <NAT> est absent'
1798        call abort_gcm(modname,abort_message,1)
1799      endif
1800#ifdef NC_DOUBLE
1801      ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais, nat_lu)
1802#else
1803      ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais, nat_lu)
1804#endif
1805      if (ierr /= NF_NOERR) then
1806        abort_message = 'Lecture echouee pour <NAT>'
1807        call abort_gcm(modname,abort_message,1)
1808      endif
1809!
1810! Remplissage des fractions de surface
1811! nat = 0, 1, 2, 3 pour ocean, terre, glacier, seaice
1812!
1813      pct_tmp = 0.0
1814      do ii = 1, klon
1815        pct_tmp(ii,nint(nat_lu(ii)) + 1) = 1.
1816      enddo
1817
1818!
1819!  On se retrouve avec ocean en 1 et terre en 2 alors qu'on veut le contraire
1820!
1821      pctsrf_new = pct_tmp
1822      pctsrf_new (:,2)= pct_tmp (:,1)
1823      pctsrf_new (:,1)= pct_tmp (:,2)
1824      pct_tmp = pctsrf_new
1825    endif ! fin test sur newlmt
1826!
1827! Lecture SST
1828!
1829    ierr = NF_INQ_VARID(nid, 'SST', nvarid)
1830    if (ierr /= NF_NOERR) then
1831      abort_message = 'Le champ <SST> est absent'
1832      call abort_gcm(modname,abort_message,1)
1833    endif
1834#ifdef NC_DOUBLE
1835    ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais, sst_lu)
1836#else
1837    ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais, sst_lu)
1838#endif
1839    if (ierr /= NF_NOERR) then
1840      abort_message = 'Lecture echouee pour <SST>'
1841      call abort_gcm(modname,abort_message,1)
1842    endif   
[109]1843
[90]1844!
[109]1845! Fin de lecture
1846!
1847    ierr = NF_CLOSE(nid)
1848    deja_lu = .true.
1849    jour_lu = jour
1850  endif
1851!
1852! Recopie des variables dans les champs de sortie
1853!
[235]1854  lmt_sst = 999999999.
[112]1855  do ii = 1, knon
1856    lmt_sst(ii) = sst_lu(knindex(ii))
1857  enddo
[109]1858
[171]1859  pctsrf_new(:,is_oce) = pct_tmp(:,is_oce)
1860  pctsrf_new(:,is_sic) = pct_tmp(:,is_sic)
1861
[109]1862  END SUBROUTINE interfoce_lim
1863
1864!
1865!#########################################################################
1866!
1867  SUBROUTINE interfsur_lim(itime, dtime, jour, &
1868     & klon, nisurf, knon, knindex, &
1869     & debut,  &
1870     & lmt_alb, lmt_rug)
1871
1872! Cette routine sert d'interface entre le modele atmospherique et un fichier
1873! de conditions aux limites
1874!
1875! L. Fairhead 02/2000
1876!
1877! input:
1878!   itime        numero du pas de temps courant
1879!   dtime        pas de temps de la physique (en s)
1880!   jour         jour a lire dans l'annee
1881!   nisurf       index de la surface a traiter (1 = sol continental)
1882!   knon         nombre de points dans le domaine a traiter
1883!   knindex      index des points de la surface a traiter
1884!   klon         taille de la grille
1885!   debut        logical: 1er appel a la physique (initialisation)
1886!
1887! output:
1888!   lmt_sst      SST lues dans le fichier de CL
1889!   lmt_alb      Albedo lu
1890!   lmt_rug      longueur de rugosité lue
1891!   pctsrf_new   sous-maille fractionnelle
1892!
1893
1894
1895! Parametres d'entree
1896  integer, intent(IN) :: itime
1897  real   , intent(IN) :: dtime
1898  integer, intent(IN) :: jour
1899  integer, intent(IN) :: nisurf
1900  integer, intent(IN) :: knon
1901  integer, intent(IN) :: klon
[147]1902  integer, dimension(klon), intent(in) :: knindex
[109]1903  logical, intent(IN) :: debut
1904
1905! Parametres de sortie
[147]1906  real, intent(out), dimension(klon) :: lmt_alb
1907  real, intent(out), dimension(klon) :: lmt_rug
[109]1908
1909! Variables locales
1910  integer     :: ii
[140]1911  integer,save :: lmt_pas     ! frequence de lecture des conditions limites
[109]1912                             ! (en pas de physique)
1913  logical,save :: deja_lu_sur! pour indiquer que le jour a lire a deja
1914                             ! lu pour une surface precedente
1915  integer,save :: jour_lu_sur
1916  integer      :: ierr
[121]1917  character (len = 20) :: modname = 'interfsur_lim'
[109]1918  character (len = 80) :: abort_message
[179]1919  character (len = 20),save :: fich ='limit.nc'
1920  logical,save     :: newlmt = .false.
1921  logical,save     :: check = .true.
[109]1922! Champs lus dans le fichier de CL
1923  real, allocatable , save, dimension(:) :: alb_lu, rug_lu
1924!
1925! quelques variables pour netcdf
1926!
1927#include "netcdf.inc"
[179]1928  integer ,save             :: nid, nvarid
1929  integer, dimension(2),save :: start, epais
[109]1930!
1931! Fin déclaration
1932!
1933   
1934  if (debut) then
1935    lmt_pas = nint(86400./dtime * 1.0) ! pour une lecture une fois par jour
1936    jour_lu_sur = jour - 1
1937    allocate(alb_lu(klon))
1938    allocate(rug_lu(klon))
1939  endif
1940
[112]1941  if ((jour - jour_lu_sur) /= 0) deja_lu_sur = .false.
[109]1942 
[112]1943  if (check) write(*,*)modname,':: jour_lu_sur, deja_lu_sur', jour_lu_sur, deja_lu_sur
[140]1944  if (check) write(*,*)modname,':: itime, lmt_pas', itime, lmt_pas
1945  call flush(6)
[109]1946
1947! Tester d'abord si c'est le moment de lire le fichier
1948  if (mod(itime-1, lmt_pas) == 0 .and. .not. deja_lu_sur) then
1949!
1950! Ouverture du fichier
1951!
[112]1952    fich = trim(fich)
[109]1953    ierr = NF_OPEN (fich, NF_NOWRITE,nid)
1954    if (ierr.NE.NF_NOERR) then
1955      abort_message = 'Pb d''ouverture du fichier de conditions aux limites'
1956      call abort_gcm(modname,abort_message,1)
1957    endif
1958!
1959! La tranche de donnees a lire:
[112]1960 
[109]1961    start(1) = 1
1962    start(2) = jour + 1
1963    epais(1) = klon
1964    epais(2) = 1
1965!
[90]1966! Lecture Albedo
1967!
1968    ierr = NF_INQ_VARID(nid, 'ALB', nvarid)
1969    if (ierr /= NF_NOERR) then
1970      abort_message = 'Le champ <ALB> est absent'
1971      call abort_gcm(modname,abort_message,1)
1972    endif
1973#ifdef NC_DOUBLE
1974    ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais, alb_lu)
1975#else
1976    ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais, alb_lu)
1977#endif
1978    if (ierr /= NF_NOERR) then
1979      abort_message = 'Lecture echouee pour <ALB>'
1980      call abort_gcm(modname,abort_message,1)
1981    endif
1982!
1983! Lecture rugosité
1984!
1985    ierr = NF_INQ_VARID(nid, 'RUG', nvarid)
1986    if (ierr /= NF_NOERR) then
1987      abort_message = 'Le champ <RUG> est absent'
1988      call abort_gcm(modname,abort_message,1)
1989    endif
1990#ifdef NC_DOUBLE
1991    ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,epais, rug_lu)
1992#else
1993    ierr = NF_GET_VARA_REAL(nid,nvarid,start,epais, rug_lu)
1994#endif
1995    if (ierr /= NF_NOERR) then
1996      abort_message = 'Lecture echouee pour <RUG>'
1997      call abort_gcm(modname,abort_message,1)
1998    endif
1999
2000!
2001! Fin de lecture
2002!
2003    ierr = NF_CLOSE(nid)
[109]2004    deja_lu_sur = .true.
2005    jour_lu_sur = jour
[90]2006  endif
2007!
2008! Recopie des variables dans les champs de sortie
2009!
[235]2010!!$  lmt_alb(:) = 0.0
2011!!$  lmt_rug(:) = 0.0
2012  lmt_alb(:) = 999999.
2013  lmt_rug(:) = 999999.
[112]2014  DO ii = 1, knon
2015    lmt_alb(ii) = alb_lu(knindex(ii))
2016    lmt_rug(ii) = rug_lu(knindex(ii))
2017  enddo
[90]2018
[109]2019  END SUBROUTINE interfsur_lim
[90]2020
2021!
2022!#########################################################################
2023!
2024
[147]2025  SUBROUTINE calcul_fluxs( klon, knon, nisurf, dtime, &
[90]2026     & tsurf, p1lay, cal, beta, coef1lay, ps, &
[98]2027     & precip_rain, precip_snow, snow, qsol, &
[90]2028     & radsol, dif_grnd, t1lay, q1lay, u1lay, v1lay, &
2029     & petAcoef, peqAcoef, petBcoef, peqBcoef, &
[98]2030     & tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
[90]2031
2032! Cette routine calcule les fluxs en h et q a l'interface et eventuellement
2033! une temperature de surface (au cas ou ok_veget = false)
2034!
2035! L. Fairhead 4/2000
2036!
2037! input:
2038!   knon         nombre de points a traiter
[98]2039!   nisurf       surface a traiter
[90]2040!   tsurf        temperature de surface
2041!   p1lay        pression 1er niveau (milieu de couche)
2042!   cal          capacite calorifique du sol
2043!   beta         evap reelle
2044!   coef1lay     coefficient d'echange
2045!   ps           pression au sol
[98]2046!   precip_rain  precipitations liquides
2047!   precip_snow  precipitations solides
2048!   snow         champs hauteur de neige
2049!   qsol         humidite du sol
2050!   runoff       runoff en cas de trop plein
[90]2051!   petAcoef     coeff. A de la resolution de la CL pour t
2052!   peqAcoef     coeff. A de la resolution de la CL pour q
2053!   petBcoef     coeff. B de la resolution de la CL pour t
2054!   peqBcoef     coeff. B de la resolution de la CL pour q
2055!   radsol       rayonnement net aus sol (LW + SW)
2056!   dif_grnd     coeff. diffusion vers le sol profond
2057!
2058! output:
2059!   tsurf_new    temperature au sol
2060!   fluxsens     flux de chaleur sensible
2061!   fluxlat      flux de chaleur latente
2062!   dflux_s      derivee du flux de chaleur sensible / Ts
2063!   dflux_l      derivee du flux de chaleur latente  / Ts
2064!
2065
2066#include "YOETHF.inc"
2067#include "FCTTRE.inc"
[258]2068#include "indicesol.inc"
[90]2069
2070! Parametres d'entree
[147]2071  integer, intent(IN) :: knon, nisurf, klon
[90]2072  real   , intent(IN) :: dtime
[147]2073  real, dimension(klon), intent(IN) :: petAcoef, peqAcoef
2074  real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
2075  real, dimension(klon), intent(IN) :: ps, q1lay
2076  real, dimension(klon), intent(IN) :: tsurf, p1lay, cal, beta, coef1lay
2077  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
2078  real, dimension(klon), intent(IN) :: radsol, dif_grnd
2079  real, dimension(klon), intent(IN) :: t1lay, u1lay, v1lay
2080  real, dimension(klon), intent(INOUT) :: snow, qsol
[90]2081
2082! Parametres sorties
[147]2083  real, dimension(klon), intent(OUT):: tsurf_new, evap, fluxsens, fluxlat
2084  real, dimension(klon), intent(OUT):: dflux_s, dflux_l
[90]2085
2086! Variables locales
2087  integer :: i
[147]2088  real, dimension(klon) :: zx_mh, zx_nh, zx_oh
2089  real, dimension(klon) :: zx_mq, zx_nq, zx_oq
2090  real, dimension(klon) :: zx_pkh, zx_dq_s_dt, zx_qsat, zx_coef
[157]2091  real, dimension(klon) :: zx_sl, zx_k1
[181]2092  real, dimension(klon) :: zx_q_0 , d_ts
[90]2093  real                  :: zdelta, zcvm5, zx_qs, zcor, zx_dq_s_dh
[98]2094  real                  :: bilan_f, fq_fonte
[177]2095  REAL                  :: subli, fsno
[90]2096  real, parameter :: t_grnd = 271.35, t_coup = 273.15
[177]2097!! PB temporaire en attendant mieux pour le modele de neige
2098  REAL, parameter :: chasno = 3.334E+05/(2.3867E+06*0.15)
2099!
[179]2100  logical, save         :: check = .true.
[90]2101  character (len = 20)  :: modname = 'calcul_fluxs'
[179]2102  logical, save         :: fonte_neige = .false.
2103  real, save            :: max_eau_sol = 150.0
[98]2104  character (len = 80) :: abort_message
[179]2105  logical,save         :: first = .true.,second=.false.
[90]2106
[140]2107  if (check) write(*,*)'Entree ', modname,' surface = ',nisurf
[98]2108
[275]2109  if (size(coastalflow) /= knon .AND. nisurf == is_ter) then
[98]2110    write(*,*)'Bizarre, le nombre de points continentaux'
2111    write(*,*)'a change entre deux appels. J''arrete ...'
2112    abort_message='Pb run_off'
2113    call abort_gcm(modname,abort_message,1)
2114  endif
2115!
2116! Traitement neige et humidite du sol
2117!
[258]2118!!$  WRITE(*,*)'test calcul_flux, surface ', nisurf
2119!!PB test
2120!!$    if (nisurf == is_oce) then
2121!!$      snow = 0.
2122!!$      qsol = max_eau_sol
2123!!$    else
2124!!$      where (precip_snow > 0.) snow = snow + (precip_snow * dtime)
2125!!$      where (snow > epsilon(snow)) snow = max(0.0, snow - (evap * dtime))
2126!!$!      snow = max(0.0, snow + (precip_snow - evap) * dtime)
2127!!$      where (precip_rain > 0.) qsol = qsol + (precip_rain - evap) * dtime
2128!!$    endif
[177]2129    IF (nisurf /= is_ter) qsol = max_eau_sol
[98]2130
2131
[90]2132!
2133! Initialisation
2134!
2135!
2136! zx_qs = qsat en kg/kg
2137!
2138  DO i = 1, knon
2139    zx_pkh(i) = (ps(i)/ps(i))**RKAPPA
2140  IF (thermcep) THEN
2141      zdelta=MAX(0.,SIGN(1.,rtt-tsurf(i)))
2142      zcvm5 = R5LES*RLVTT*(1.-zdelta) + R5IES*RLSTT*zdelta
2143      zcvm5 = zcvm5 / RCPD / (1.0+RVTMP2*q1lay(i))
2144      zx_qs= r2es * FOEEW(tsurf(i),zdelta)/ps(i)
2145      zx_qs=MIN(0.5,zx_qs)
2146      zcor=1./(1.-retv*zx_qs)
2147      zx_qs=zx_qs*zcor
2148      zx_dq_s_dh = FOEDE(tsurf(i),zdelta,zcvm5,zx_qs,zcor) &
2149     &                 /RLVTT / zx_pkh(i)
2150    ELSE
2151      IF (tsurf(i).LT.t_coup) THEN
2152        zx_qs = qsats(tsurf(i)) / ps(i)
2153        zx_dq_s_dh = dqsats(tsurf(i),zx_qs)/RLVTT &
2154     &                    / zx_pkh(i)
2155      ELSE
2156        zx_qs = qsatl(tsurf(i)) / ps(i)
2157        zx_dq_s_dh = dqsatl(tsurf(i),zx_qs)/RLVTT &
2158     &               / zx_pkh(i)
2159      ENDIF
2160    ENDIF
2161    zx_dq_s_dt(i) = RCPD * zx_pkh(i) * zx_dq_s_dh
2162    zx_qsat(i) = zx_qs
2163    zx_coef(i) = coef1lay(i) &
2164     & * (1.0+SQRT(u1lay(i)**2+v1lay(i)**2)) &
2165     & * p1lay(i)/(RD*t1lay(i))
[177]2166
[90]2167  ENDDO
2168
2169
2170! === Calcul de la temperature de surface ===
2171!
2172! zx_sl = chaleur latente d'evaporation ou de sublimation
2173!
2174  do i = 1, knon
2175    zx_sl(i) = RLVTT
2176    if (tsurf(i) .LT. RTT) zx_sl(i) = RLSTT
2177    zx_k1(i) = zx_coef(i)
2178  enddo
2179
2180
2181  do i = 1, knon
2182! Q
2183    zx_oq(i) = 1. - (beta(i) * zx_k1(i) * peqBcoef(i) * dtime)
2184    zx_mq(i) = beta(i) * zx_k1(i) * &
2185     &             (peqAcoef(i) - zx_qsat(i) &
2186     &                          + zx_dq_s_dt(i) * tsurf(i)) &
2187     &             / zx_oq(i)
2188    zx_nq(i) = beta(i) * zx_k1(i) * (-1. * zx_dq_s_dt(i)) &
2189     &                              / zx_oq(i)
2190
2191! H
2192    zx_oh(i) = 1. - (zx_k1(i) * petBcoef(i) * dtime)
2193    zx_mh(i) = zx_k1(i) * petAcoef(i) / zx_oh(i)
2194    zx_nh(i) = - (zx_k1(i) * RCPD * zx_pkh(i))/ zx_oh(i)
2195
2196! Tsurface
2197    tsurf_new(i) = (tsurf(i) + cal(i)/(RCPD * zx_pkh(i)) * dtime * &
2198     &             (radsol(i) + zx_mh(i) + zx_sl(i) * zx_mq(i)) &
2199     &                 + dif_grnd(i) * t_grnd * dtime)/ &
2200     &          ( 1. - dtime * cal(i)/(RCPD * zx_pkh(i)) * ( &
2201     &                       zx_nh(i) + zx_sl(i) * zx_nq(i)) & 
2202     &                     + dtime * dif_grnd(i))
[98]2203
2204!
2205! Y'a-t-il fonte de neige?
2206!
[181]2207!    fonte_neige = (nisurf /= is_oce) .AND. &
2208!     & (snow(i) > epsfra .OR. nisurf == is_sic .OR. nisurf == is_lic) &
2209!     & .AND. (tsurf_new(i) >= RTT)
2210!    if (fonte_neige) tsurf_new(i) = RTT 
[90]2211    d_ts(i) = tsurf_new(i) - tsurf(i)
[181]2212!    zx_h_ts(i) = tsurf_new(i) * RCPD * zx_pkh(i)
2213!    zx_q_0(i) = zx_qsat(i) + zx_dq_s_dt(i) * d_ts(i)
[90]2214!== flux_q est le flux de vapeur d'eau: kg/(m**2 s)  positive vers bas
2215!== flux_t est le flux de cpt (energie sensible): j/(m**2 s)
[98]2216    evap(i) = - zx_mq(i) - zx_nq(i) * tsurf_new(i)
2217    fluxlat(i) = - evap(i) * zx_sl(i)
[90]2218    fluxsens(i) = zx_mh(i) + zx_nh(i) * tsurf_new(i)
2219! Derives des flux dF/dTs (W m-2 K-1):
2220    dflux_s(i) = zx_nh(i)
2221    dflux_l(i) = (zx_sl(i) * zx_nq(i))
[177]2222
[98]2223!
2224! en cas de fonte de neige
2225!
[181]2226!    if (fonte_neige) then
2227!      bilan_f = radsol(i) + fluxsens(i) - (zx_sl(i) * evap (i)) - &
2228!     &          dif_grnd(i) * (tsurf_new(i) - t_grnd) - &
2229!     &          RCPD * (zx_pkh(i))/cal(i)/dtime * (tsurf_new(i) - tsurf(i))
2230!      bilan_f = max(0., bilan_f)
2231!      fq_fonte = bilan_f / zx_sl(i)
2232!      snow(i) = max(0., snow(i) - fq_fonte * dtime)
2233!      qsol(i) = qsol(i) + (fq_fonte * dtime)
2234!    endif
[258]2235!!$    if (nisurf == is_ter)  &
2236!!$     &  run_off(i) = run_off(i) + max(qsol(i) - max_eau_sol, 0.0)
2237!!$    qsol(i) = min(qsol(i), max_eau_sol)
[90]2238  ENDDO
2239
2240  END SUBROUTINE calcul_fluxs
2241!
2242!#########################################################################
2243!
[98]2244  SUBROUTINE gath2cpl(champ_in, champ_out, klon, knon, iim, jjm, knindex)
2245
2246! Cette routine ecrit un champ 'gathered' sur la grille 2D pour le passer
2247! au coupleur.
2248!
2249!
2250! input:         
2251!   champ_in     champ sur la grille gathere       
2252!   knon         nombre de points dans le domaine a traiter
2253!   knindex      index des points de la surface a traiter
2254!   klon         taille de la grille
2255!   iim,jjm      dimension de la grille 2D
2256!
2257! output:
2258!   champ_out    champ sur la grille 2D
2259!
2260! input
2261  integer                   :: klon, knon, iim, jjm
[147]2262  real, dimension(klon)     :: champ_in
2263  integer, dimension(klon)  :: knindex
[98]2264! output
2265  real, dimension(iim,jjm+1)  :: champ_out
2266! local
2267  integer                   :: i, ig, j
2268  real, dimension(klon)     :: tamp
2269
[105]2270  tamp = 0.
[98]2271  do i = 1, knon
2272    ig = knindex(i)
2273    tamp(ig) = champ_in(i)
2274  enddo   
[140]2275  ig = 1
2276  champ_out(:,1) = tamp(ig)
[98]2277  do j = 2, jjm
2278    do i = 1, iim
[140]2279      ig = ig + 1
2280      champ_out(i,j) = tamp(ig)
[98]2281    enddo
2282  enddo
[140]2283  ig = ig + 1
2284  champ_out(:,jjm+1) = tamp(ig)
[98]2285
2286  END SUBROUTINE gath2cpl
2287!
2288!#########################################################################
2289!
2290  SUBROUTINE cpl2gath(champ_in, champ_out, klon, knon, iim, jjm, knindex)
2291
2292! Cette routine ecrit un champ 'gathered' sur la grille 2D pour le passer
2293! au coupleur.
2294!
2295!
2296! input:         
2297!   champ_in     champ sur la grille gathere       
2298!   knon         nombre de points dans le domaine a traiter
2299!   knindex      index des points de la surface a traiter
2300!   klon         taille de la grille
2301!   iim,jjm      dimension de la grille 2D
2302!
2303! output:
2304!   champ_out    champ sur la grille 2D
2305!
2306! input
2307  integer                   :: klon, knon, iim, jjm
2308  real, dimension(iim,jjm+1)     :: champ_in
[147]2309  integer, dimension(klon)  :: knindex
[98]2310! output
[147]2311  real, dimension(klon)  :: champ_out
[98]2312! local
2313  integer                   :: i, ig, j
2314  real, dimension(klon)     :: tamp
[179]2315  logical ,save                  :: check = .false.
[98]2316
[140]2317  ig = 1
2318  tamp(ig) = champ_in(1,1)
[98]2319  do j = 2, jjm
2320    do i = 1, iim
[140]2321      ig = ig + 1
2322      tamp(ig) = champ_in(i,j)
[98]2323    enddo
2324  enddo
[140]2325  ig = ig + 1
2326  tamp(ig) = champ_in(1,jjm+1)
[98]2327
2328  do i = 1, knon
2329    ig = knindex(i)
2330    champ_out(i) = tamp(ig)
2331  enddo   
2332
2333  END SUBROUTINE cpl2gath
2334!
2335!#########################################################################
2336!
[258]2337  SUBROUTINE albsno(klon, knon,dtime,agesno,alb_neig_grid, precip_snow)
[109]2338  IMPLICIT none
[112]2339 
[258]2340  INTEGER :: klon, knon
[112]2341  INTEGER, PARAMETER :: nvm = 8
[258]2342  REAL   :: dtime
[112]2343  REAL, dimension(klon,nvm) :: veget
[258]2344  REAL, DIMENSION(klon) :: alb_neig_grid, agesno, precip_snow
[112]2345 
2346  INTEGER :: i, nv
2347 
2348  REAL, DIMENSION(nvm),SAVE :: init, decay
2349  REAL :: as
[109]2350  DATA init /0.55, 0.14, 0.18, 0.29, 0.15, 0.15, 0.14, 0./
2351  DATA decay/0.30, 0.67, 0.63, 0.45, 0.40, 0.14, 0.06, 1./
[112]2352 
[109]2353  veget = 0.
2354  veget(:,1) = 1.     ! desert partout
[258]2355  DO i = 1, knon
[112]2356    alb_neig_grid(i) = 0.0
[109]2357  ENDDO
2358  DO nv = 1, nvm
[258]2359    DO i = 1, knon
[109]2360      as = init(nv)+decay(nv)*EXP(-agesno(i)/5.)
[112]2361      alb_neig_grid(i) = alb_neig_grid(i) + veget(i,nv)*as
[109]2362    ENDDO
2363  ENDDO
[258]2364!
2365!! modilation en fonction de l'age de la neige
2366!
2367  DO i = 1, knon
2368    agesno(i)  = (agesno(i) + (1.-agesno(i)/50.)*dtime/86400.)&
2369            &             * EXP(-1.*MAX(0.0,precip_snow(i))*dtime/0.3)
2370    agesno(i) =  MAX(agesno(i),0.0)
2371  ENDDO
[112]2372 
[109]2373  END SUBROUTINE albsno
2374!
2375!#########################################################################
2376!
[181]2377
2378  SUBROUTINE fonte_neige( klon, knon, nisurf, dtime, &
2379     & tsurf, p1lay, cal, beta, coef1lay, ps, &
2380     & precip_rain, precip_snow, snow, qsol, &
2381     & radsol, dif_grnd, t1lay, q1lay, u1lay, v1lay, &
2382     & petAcoef, peqAcoef, petBcoef, peqBcoef, &
2383     & tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
2384
2385! Routine de traitement de la fonte de la neige dans le cas du traitement
2386! de sol simplifié
2387!
2388! LF 03/2001
2389! input:
2390!   knon         nombre de points a traiter
2391!   nisurf       surface a traiter
2392!   tsurf        temperature de surface
2393!   p1lay        pression 1er niveau (milieu de couche)
2394!   cal          capacite calorifique du sol
2395!   beta         evap reelle
2396!   coef1lay     coefficient d'echange
2397!   ps           pression au sol
2398!   precip_rain  precipitations liquides
2399!   precip_snow  precipitations solides
2400!   snow         champs hauteur de neige
2401!   qsol         humidite du sol
2402!   runoff       runoff en cas de trop plein
2403!   petAcoef     coeff. A de la resolution de la CL pour t
2404!   peqAcoef     coeff. A de la resolution de la CL pour q
2405!   petBcoef     coeff. B de la resolution de la CL pour t
2406!   peqBcoef     coeff. B de la resolution de la CL pour q
2407!   radsol       rayonnement net aus sol (LW + SW)
2408!   dif_grnd     coeff. diffusion vers le sol profond
2409!
2410! output:
2411!   tsurf_new    temperature au sol
2412!   fluxsens     flux de chaleur sensible
2413!   fluxlat      flux de chaleur latente
2414!   dflux_s      derivee du flux de chaleur sensible / Ts
2415!   dflux_l      derivee du flux de chaleur latente  / Ts
2416!
2417
2418#include "YOETHF.inc"
2419#include "FCTTRE.inc"
[258]2420#include "indicesol.inc"
[181]2421
2422! Parametres d'entree
2423  integer, intent(IN) :: knon, nisurf, klon
2424  real   , intent(IN) :: dtime
2425  real, dimension(klon), intent(IN) :: petAcoef, peqAcoef
2426  real, dimension(klon), intent(IN) :: petBcoef, peqBcoef
2427  real, dimension(klon), intent(IN) :: ps, q1lay
2428  real, dimension(klon), intent(IN) :: tsurf, p1lay, cal, beta, coef1lay
2429  real, dimension(klon), intent(IN) :: precip_rain, precip_snow
2430  real, dimension(klon), intent(IN) :: radsol, dif_grnd
2431  real, dimension(klon), intent(IN) :: t1lay, u1lay, v1lay
2432  real, dimension(klon), intent(INOUT) :: snow, qsol
2433
2434! Parametres sorties
2435  real, dimension(klon), intent(INOUT):: tsurf_new, evap, fluxsens, fluxlat
2436  real, dimension(klon), intent(INOUT):: dflux_s, dflux_l
2437
2438! Variables locales
2439  integer :: i
2440  real, dimension(klon) :: zx_mh, zx_nh, zx_oh
2441  real, dimension(klon) :: zx_mq, zx_nq, zx_oq
2442  real, dimension(klon) :: zx_pkh, zx_dq_s_dt, zx_qsat, zx_coef
2443  real, dimension(klon) :: zx_sl, zx_k1
2444  real, dimension(klon) :: zx_q_0 , d_ts
2445  real                  :: zdelta, zcvm5, zx_qs, zcor, zx_dq_s_dh
2446  real                  :: bilan_f, fq_fonte
2447  REAL                  :: subli, fsno
2448  real, parameter :: t_grnd = 271.35, t_coup = 273.15
2449!! PB temporaire en attendant mieux pour le modele de neige
2450  REAL, parameter :: chasno = 3.334E+05/(2.3867E+06*0.15)
2451!
2452  logical, save         :: check = .true.
2453  character (len = 20)  :: modname = 'fonte_neige'
2454  logical, save         :: neige_fond = .false.
2455  real, save            :: max_eau_sol = 150.0
2456  character (len = 80) :: abort_message
2457  logical,save         :: first = .true.,second=.false.
2458
2459  if (check) write(*,*)'Entree ', modname,' surface = ',nisurf
2460
2461! Initialisations
2462  DO i = 1, knon
2463    zx_pkh(i) = (ps(i)/ps(i))**RKAPPA
2464  IF (thermcep) THEN
2465      zdelta=MAX(0.,SIGN(1.,rtt-tsurf(i)))
2466      zcvm5 = R5LES*RLVTT*(1.-zdelta) + R5IES*RLSTT*zdelta
2467      zcvm5 = zcvm5 / RCPD / (1.0+RVTMP2*q1lay(i))
2468      zx_qs= r2es * FOEEW(tsurf(i),zdelta)/ps(i)
2469      zx_qs=MIN(0.5,zx_qs)
2470      zcor=1./(1.-retv*zx_qs)
2471      zx_qs=zx_qs*zcor
2472      zx_dq_s_dh = FOEDE(tsurf(i),zdelta,zcvm5,zx_qs,zcor) &
2473     &                 /RLVTT / zx_pkh(i)
2474    ELSE
2475      IF (tsurf(i).LT.t_coup) THEN
2476        zx_qs = qsats(tsurf(i)) / ps(i)
2477        zx_dq_s_dh = dqsats(tsurf(i),zx_qs)/RLVTT &
2478     &                    / zx_pkh(i)
2479      ELSE
2480        zx_qs = qsatl(tsurf(i)) / ps(i)
2481        zx_dq_s_dh = dqsatl(tsurf(i),zx_qs)/RLVTT &
2482     &               / zx_pkh(i)
2483      ENDIF
2484    ENDIF
2485    zx_dq_s_dt(i) = RCPD * zx_pkh(i) * zx_dq_s_dh
2486    zx_qsat(i) = zx_qs
2487    zx_coef(i) = coef1lay(i) &
2488     & * (1.0+SQRT(u1lay(i)**2+v1lay(i)**2)) &
2489     & * p1lay(i)/(RD*t1lay(i))
2490  ENDDO
[223]2491
2492
[181]2493! === Calcul de la temperature de surface ===
2494!
2495! zx_sl = chaleur latente d'evaporation ou de sublimation
2496!
2497  do i = 1, knon
2498    zx_sl(i) = RLVTT
2499    if (tsurf(i) .LT. RTT) zx_sl(i) = RLSTT
2500    zx_k1(i) = zx_coef(i)
2501  enddo
2502
2503
2504  do i = 1, knon
2505! Q
2506    zx_oq(i) = 1. - (beta(i) * zx_k1(i) * peqBcoef(i) * dtime)
2507    zx_mq(i) = beta(i) * zx_k1(i) * &
2508     &             (peqAcoef(i) - zx_qsat(i) &
2509     &                          + zx_dq_s_dt(i) * tsurf(i)) &
2510     &             / zx_oq(i)
2511    zx_nq(i) = beta(i) * zx_k1(i) * (-1. * zx_dq_s_dt(i)) &
2512     &                              / zx_oq(i)
2513
2514! H
2515    zx_oh(i) = 1. - (zx_k1(i) * petBcoef(i) * dtime)
2516    zx_mh(i) = zx_k1(i) * petAcoef(i) / zx_oh(i)
2517    zx_nh(i) = - (zx_k1(i) * RCPD * zx_pkh(i))/ zx_oh(i)
2518  enddo
2519
[258]2520
2521  WHERE (precip_snow > 0.) snow = snow + (precip_snow * dtime)
2522  WHERE (evap > 0 ) snow = MAX(0.0, snow - (evap * dtime))
2523  qsol = qsol + (precip_rain - evap) * dtime
[181]2524!
2525! Y'a-t-il fonte de neige?
2526!
2527  do i = 1, knon
2528    neige_fond = ((snow(i) > epsfra .OR. nisurf == is_sic .OR. nisurf == is_lic) &
2529     & .AND. tsurf_new(i) >= RTT)
2530    if (neige_fond) then
[258]2531      fq_fonte = MIN( MAX((tsurf_new(i)-RTT )/chasno,0.0),snow(i))
2532      snow(i) = max(0., snow(i) - fq_fonte)
2533      qsol(i) = qsol(i) + fq_fonte
2534      tsurf_new(i) = tsurf_new(i) - fq_fonte * chasno 
2535      IF (nisurf == is_sic .OR. nisurf == is_lic ) tsurf_new(i) = RTT -1.8
[181]2536      d_ts(i) = tsurf_new(i) - tsurf(i)
2537!      zx_h_ts(i) = tsurf_new(i) * RCPD * zx_pkh(i)
2538!      zx_q_0(i) = zx_qsat(i) + zx_dq_s_dt(i) * d_ts(i)
2539!== flux_q est le flux de vapeur d'eau: kg/(m**2 s)  positive vers bas
2540!== flux_t est le flux de cpt (energie sensible): j/(m**2 s)
[258]2541!!$      evap(i) = - zx_mq(i) - zx_nq(i) * tsurf_new(i)
2542!!$      fluxlat(i) = - evap(i) * zx_sl(i)
2543!!$      fluxsens(i) = zx_mh(i) + zx_nh(i) * tsurf_new(i)
[181]2544! Derives des flux dF/dTs (W m-2 K-1):
[258]2545!!$      dflux_s(i) = zx_nh(i)
2546!!$      dflux_l(i) = (zx_sl(i) * zx_nq(i))
2547!!$      bilan_f = radsol(i) + fluxsens(i) - (zx_sl(i) * evap (i)) - &
2548!!$     &          dif_grnd(i) * (tsurf_new(i) - t_grnd) - &
2549!!$     &          RCPD * (zx_pkh(i))/cal(i)/dtime * (tsurf_new(i) - tsurf(i))
2550!!$      bilan_f = max(0., bilan_f)
2551!!$      fq_fonte = bilan_f / zx_sl(i)
[181]2552    endif
[258]2553    IF (nisurf == is_ter)  &
2554       &  run_off(i) = run_off(i) + MAX(qsol(i) - max_eau_sol, 0.0)
2555    qsol(i) = MIN(qsol(i), max_eau_sol)
[181]2556  enddo
2557
2558  END SUBROUTINE fonte_neige
2559!
2560!#########################################################################
2561!
[90]2562  END MODULE interface_surf
Note: See TracBrowser for help on using the repository browser.