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

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

Passage des dimensions de la grille a inicma
LF

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