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

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

Divers bugs corriges pour le couplage
LF

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