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

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

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

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