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

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

Rajout interfoce_cpl. LF

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