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

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

Suppression d'ecriture de debogage
LF

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