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

Last change on this file since 457 was 457, checked in by lmdzadmin, 21 years ago

Correction bug tsurf_new=RTT - 1.8 apres fonte et passage routine soil
Correction bug tsurf_new=RTT sic & lic
IM/JLD/LF

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