source: trunk/LMDZ.GENERIC/libf/dyn3d/gcm.F @ 1007

Last change on this file since 1007 was 1006, checked in by emillour, 13 years ago

Generic GCM:

  • update the sponge layer: trun it into a module and (more important) compute the sponge quenching analytically rather than via Forward Euler approximation.

EM

File size: 18.7 KB
Line 
1      PROGRAM gcm
2
3      use sponge_mod,only: callsponge,mode_sponge,sponge
4      IMPLICIT NONE
5
6c      ......   Version  du 10/01/98    ..........
7
8c             avec  coordonnees  verticales hybrides
9c   avec nouveaux operat. dissipation * ( gradiv2,divgrad2,nxgraro2 )
10
11c=======================================================================
12c
13c   Auteur:  P. Le Van /L. Fairhead/F.Hourdin
14c   -------
15c
16c   Objet:
17c   ------
18c
19c   GCM LMD nouvelle grille
20c
21c=======================================================================
22c
23c  ... Dans inigeom , nouveaux calculs pour les elongations  cu , cv
24c      et possibilite d'appeler une fonction f(y)  a derivee tangente
25c      hyperbolique a la  place de la fonction a derivee sinusoidale.
26
27c  ... Possibilite de choisir le shema de Van-leer pour l'advection de
28c        q  , en faisant iadv = 3  dans   traceur  (29/04/97) .
29c
30c      Pour Van-Leer + Vapeur d'eau saturee, iadv(1)=4. (F.Codron,10/99)
31c
32c-----------------------------------------------------------------------
33c   Declarations:
34c   -------------
35
36#include "dimensions.h"
37#include "paramet.h"
38#include "comconst.h"
39#include "comdissnew.h"
40#include "comvert.h"
41#include "comgeom.h"
42#include "logic.h"
43#include "temps.h"
44#include "control.h"
45#include "ener.h"
46#include "netcdf.inc"
47#include "serre.h"
48#include "tracstoke.h"
49#include"advtrac.h"
50
51      INTEGER*4  iday ! jour julien
52      REAL       time ! Heure de la journee en fraction d''1 jour
53      REAL zdtvr
54
55c   variables dynamiques
56      REAL vcov(ip1jm,llm),ucov(ip1jmp1,llm) ! vents covariants
57      real, dimension(ip1jmp1,llm) :: teta   ! temperature potentielle
58      REAL q(ip1jmp1,llm,nqmx)               ! champs advectes
59      REAL ps(ip1jmp1)                       ! pression  au sol
60      REAL pext(ip1jmp1)                     ! pression  extensive
61      REAL p (ip1jmp1,llmp1  )               ! pression aux interfac.des couches
62      REAL pks(ip1jmp1)                      ! exner au  sol
63      REAL pk(ip1jmp1,llm)                   ! exner au milieu des couches
64      REAL pkf(ip1jmp1,llm)                  ! exner filt.au milieu des couches
65      REAL masse(ip1jmp1,llm)                ! masse d''air
66      REAL phis(ip1jmp1)                     ! geopotentiel au sol
67      REAL phi(ip1jmp1,llm)                  ! geopotentiel
68      REAL w(ip1jmp1,llm)                    ! vitesse verticale
69
70c variables dynamiques intermediaire pour le transport
71      REAL pbaru(ip1jmp1,llm),pbarv(ip1jm,llm) !flux de masse
72
73c   variables dynamiques au pas -1
74      REAL vcovm1(ip1jm,llm),ucovm1(ip1jmp1,llm)
75
76      REAL tetam1(ip1jmp1,llm),psm1(ip1jmp1)
77      REAL massem1(ip1jmp1,llm)
78
79c   tendances dynamiques
80      REAL dv(ip1jm,llm),du(ip1jmp1,llm)
81      REAL dteta(ip1jmp1,llm),dq(ip1jmp1,llm,nqmx),dp(ip1jmp1)
82
83c   tendances de la dissipation
84      REAL dvdis(ip1jm,llm),dudis(ip1jmp1,llm)
85      REAL dhdis(ip1jmp1,llm)
86
87c   tendances physiques
88      REAL dvfi(ip1jm,llm),dufi(ip1jmp1,llm)
89      REAL dhfi(ip1jmp1,llm),dqfi(ip1jmp1,llm,nqmx),dpfi(ip1jmp1)
90
91c   variables pour le fichier histoire
92      REAL dtav      ! intervalle de temps elementaire
93
94      REAL tppn(iim),tpps(iim),tpn,tps
95c
96!      INTEGER iadv(nqmx) ! indice schema de transport pour le traceur iq
97
98      INTEGER itau,itaufinp1,iav
99
100
101      EXTERNAL caldyn, traceur
102      EXTERNAL dissip,geopot,iniconst,inifilr
103      EXTERNAL integrd,SCOPY
104      EXTERNAL inigeom
105      EXTERNAL exner_hyb
106      EXTERNAL defrun_new, test_period
107      REAL  SSUM
108      REAL time_0 , finvmaold(ip1jmp1,llm)
109
110      LOGICAL lafin
111      INTEGER ij,iq,l,ierr,numvanle,iapp_tracvl
112
113      REAL rdayvrai,rdaym_ini,rday_ecri
114!      LOGICAL first
115      REAL beta(ip1jmp1,llm)
116
117      LOGICAL offline  ! Controle du stockage ds "fluxmass"
118      PARAMETER (offline=.false.)
119
120      character*20 modname
121      character*80 abort_message
122
123      LOGICAL tracer
124          data tracer/.true./
125      INTEGER nq
126
127C Calendrier
128      LOGICAL true_calendar
129      PARAMETER (true_calendar = .false.)
130
131! flag to set/remove calls to groupeun
132      logical callgroupeun
133      parameter (callgroupeun = .false.)
134
135!     added by RDW for tests without dynamics
136      logical calldyn
137      parameter (calldyn = .true.)
138
139!     added by RW for test
140!      real pmean,airetot
141
142!     added by FF for dissipation / energy conservation tests
143      logical dissip_conservative
144      parameter (dissip_conservative = .false.)
145      REAL ecin(ip1jmp1,llm),ecin0(ip1jmp1,llm)
146!     d (theta)/ d t (pot. temperature) due to the creation
147!     of thermal energy by dissipation
148      REAL dtetaecdt(ip1jmp1,llm)
149      REAL vcont(ip1jm,llm),ucont(ip1jmp1,llm)
150      REAL vnat(ip1jm,llm),unat(ip1jmp1,llm)
151
152
153c-----------------------------------------------------------------------
154c   Initialisations:
155c   ----------------
156
157      modname = 'gcm'
158      lafin    = .FALSE.
159
160c-----------------------------------------------------------------------
161c  Initialize tracers using iniadvtrac (Ehouarn, oct 2008)
162      CALL iniadvtrac(nq,numvanle)
163
164
165      CALL dynetat0("start.nc",nqmx,vcov,ucov,
166     .              teta,q,masse,ps,phis, time_0)
167
168      CALL defrun_new( 99, .TRUE. )
169
170c  on recalcule eventuellement le pas de temps
171
172      IF(MOD(day_step,iperiod).NE.0)
173     * STOP'Il faut choisir un nb de pas par jour multiple de iperiod'
174
175      IF(MOD(day_step,iphysiq).NE.0)
176     * STOP'Il faut choisir un nb de pas par jour multiple de iphysiq'
177
178      zdtvr    = daysec/FLOAT(day_step)
179
180        IF(dtvr.NE.zdtvr) THEN
181         PRINT*,'WARNING!!! changement de pas de temps',dtvr,'>',zdtvr
182        ENDIF
183
184c  nombre d'etats dans les fichiers demarrage et histoire
185
186      dtvr = zdtvr
187      CALL iniconst
188      CALL inigeom
189      CALL inifilr
190
191c
192c   ......    P.Le Van    ( modif  le 29/04/97 )   ......... 
193c
194
195      CALL inidissip ( lstardis, nitergdiv, nitergrot, niterh   ,
196     *                tetagdiv, tetagrot , tetatemp              )
197c
198
199      CALL pression ( ip1jmp1, ap, bp, ps, p       )
200
201      call dump2d(iip1,jjp1,ps,'PRESSION SURFACE')
202      CALL exner_hyb( ip1jmp1, ps, p,beta, pks, pk, pkf )
203
204
205c  numero de stockage pour les fichiers de redemarrage:
206
207c-----------------------------------------------------------------------
208c   temps de depart et de fin:
209c   --------------------------
210
211      itau = 0
212      iday = day_ini+itau/day_step
213      time = FLOAT(itau-(iday-day_ini)*day_step)/day_step+time_0
214
215
216         IF(time.GT.1.) THEN
217          time = time-1.
218          iday = iday+1
219         ENDIF
220      itaufin   = nday*day_step
221c ********************************
222c      itaufin = 120   ! temporaire !!
223c ********************************
224      itaufinp1 = itaufin +1
225
226      day_end = day_ini + nday
227      PRINT 300, itau,itaufin,day_ini,day_end
228 300  FORMAT('1'/,15x,'run du pas',i7,2x,'au pas',i7,2x, 
229     . 'c''est a dire du jour',i7,3x,'au jour',i7//)
230
231      CALL dynredem0("restart.nc",day_end,anne_ini,phis,nqmx)
232
233      ecripar = .TRUE.
234
235      dtav = iperiod*dtvr/daysec
236
237
238c   Quelques initialisations pour les traceurs
239      call initial0(ijp1llm*nqmx,dq)
240c     istdyn=day_step/4     ! stockage toutes les 6h=1jour/4
241c     istphy=istdyn/iphysiq
242
243      write(*,*) "gcm: callgroupeun set to:",callgroupeun
244c-----------------------------------------------------------------------
245c   Debut de l'integration temporelle:
246c   ----------------------------------
247
248   1  CONTINUE
249c
250      IF( MOD( itau, 10* day_step ).EQ.0 )  THEN
251        CALL test_period ( ucov,vcov,teta,q,p,phis )
252        PRINT *,' ----   Test_period apres continue   OK ! -----', itau
253      ENDIF
254
255      if (callgroupeun) then
256        call groupeun(jjp1,llm,ucov,.true.)
257        call groupeun(jjm,llm,vcov,.true.)
258        call groupeun(jjp1,llm,teta,.true.)
259        call groupeun(jjp1,llm,masse,.true.)
260        call groupeun(jjp1,1,ps,.false.)
261      endif
262
263      CALL SCOPY( ijmllm ,vcov , 1, vcovm1 , 1 )
264      CALL SCOPY( ijp1llm,ucov , 1, ucovm1 , 1 )
265      CALL SCOPY( ijp1llm,teta , 1, tetam1 , 1 )
266      CALL SCOPY( ijp1llm,masse, 1, massem1, 1 )
267      CALL SCOPY( ip1jmp1, ps  , 1,   psm1 , 1 )
268
269      forward = .TRUE.
270      leapf   = .FALSE.
271      dt      =  dtvr
272
273c   ...    P.Le Van .26/04/94  ....
274
275      CALL SCOPY   ( ijp1llm,   masse, 1, finvmaold,     1 )
276      CALL filtreg ( finvmaold ,jjp1, llm, -2,2, .TRUE., 1 )
277
278
279   2  CONTINUE
280
281c-----------------------------------------------------------------------
282
283c   date:
284c   -----
285
286!      write(*,*) 'GCM: itau=',itau
287
288c   gestion des appels de la physique et des dissipations:
289c   ------------------------------------------------------
290c
291c   ...    P.Le Van  ( 6/02/95 )  ....
292
293      apphys = .FALSE.
294      statcl = .FALSE.
295      conser = .FALSE.
296      apdiss = .FALSE.
297
298      IF( purmats ) THEN
299         IF( MOD(itau,iconser) .EQ.0.AND.  forward    ) conser = .TRUE.
300         IF( MOD(itau,idissip ).EQ.0.AND..NOT.forward ) apdiss = .TRUE.
301         IF( MOD(itau,iphysiq ).EQ.0.AND..NOT.forward
302     $                              .AND.   physic    ) apphys = .TRUE.
303      ELSE
304         IF( MOD(itau   ,iconser) .EQ. 0              ) conser = .TRUE.
305         IF( MOD(itau+1,idissip)  .EQ. 0              ) apdiss = .TRUE.
306         IF( MOD(itau+1,iphysiq).EQ.0. AND. physic    ) apphys = .TRUE.
307      END IF
308
309c-----------------------------------------------------------------------
310c   calcul des tendances dynamiques:
311c   --------------------------------
312
313      CALL geopot  ( ip1jmp1, teta  , pk , pks,  phis  , phi   )
314
315      if(calldyn)then
316         CALL caldyn
317     $        ( itau,ucov,vcov,teta,ps,masse,pk,pkf,phis ,
318     $        phi,conser,du,dv,dteta,dp,w,pbaru,pbarv,time+iday-day_ini)
319      endif
320
321c-----------------------------------------------------------------------
322c   calcul des tendances advection des traceurs (dont l'humidite)
323c   -------------------------------------------------------------
324
325
326
327      if (tracer) then
328       IF( forward. OR . leapf )  THEN
329
330        DO iq = 1, nqmx
331c
332         IF ( iadv(iq).EQ.1.OR.iadv(iq).EQ.2 )  THEN
333            CALL traceur( iq,iadv,q,teta,pk,w, pbaru, pbarv, dq )
334
335         ELSE IF( iq.EQ. nqmx )   THEN
336c
337            iapp_tracvl = 5
338c
339cccc     iapp_tracvl est la frequence en pas du groupement des flux
340cccc      de masse pour  Van-Leer dans la routine  tracvl  .
341c
342
343            CALL vanleer(numvanle,iapp_tracvl,nqmx,q,pbaru,pbarv,
344     *                      p, masse, dq,  iadv(1), teta, pk     )
345
346c
347c                   ...  Modif  F.Codron  ....
348c
349         ENDIF
350c
351        ENDDO
352C
353c        IF (offline) THEN
354C maf stokage du flux de masse pour traceurs OFF-LINE
355
356c           CALL fluxstokenc(pbaru,pbarv,masse,teta,phi,phis,
357c    .   time_step, itau)
358
359c        ENDIF
360c
361      ENDIF
362          END IF   ! tracer
363
364
365c-----------------------------------------------------------------------
366c   integrations dynamique et traceurs:
367c   ----------------------------------
368
369          if(calldyn)then
370             CALL integrd(2,vcovm1,ucovm1,tetam1,psm1,massem1,
371     $            dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps,masse,phis,
372     $            finvmaold)
373          else
374             print*,'Currently no dynamics in this GCM...'
375          endif
376
377
378
379
380
381c .P.Le Van (26/04/94  ajout de  finvpold dans l'appel d'integrd)
382c
383c-----------------------------------------------------------------------
384c   calcul des tendances physiques:
385c   -------------------------------
386c    ########   P.Le Van ( Modif le  6/02/95 )   ###########
387c
388       IF( purmats )  THEN
389          IF( itau.EQ.itaufin.AND..NOT.forward ) lafin = .TRUE.
390       ELSE
391          IF( itau+1. EQ. itaufin )              lafin = .TRUE.
392       ENDIF
393c
394c
395       IF( apphys )  THEN
396c
397c     .......   Ajout   P.Le Van ( 17/04/96 )   ...........
398c
399
400         CALL pression (  ip1jmp1, ap, bp, ps,  p      )
401         CALL exner_hyb(  ip1jmp1, ps, p,beta,pks, pk, pkf )
402
403           rdaym_ini  = itau * dtvr / daysec
404           rdayvrai   = rdaym_ini  + day_ini
405
406           IF ( ecritphy.LT.1. )  THEN
407             rday_ecri = rdaym_ini
408           ELSE
409             rday_ecri = INT(rdaym_ini)+INT(day_ini)
410           ENDIF
411c
412
413
414
415        CALL calfis( nqmx, lafin ,rdayvrai,rday_ecri,time  ,
416     $                 ucov,vcov,teta,q,masse,ps,p,pk,phis,phi ,
417     $     du,dv,dteta,dq,w, dufi,dvfi,dhfi,dqfi,dpfi,tracer)
418
419
420c      ajout des tendances physiques:
421c      ------------------------------
422!        if(1.eq.2)then
423          CALL addfi( nqmx, dtphys, leapf, forward   ,
424     $                  ucov, vcov, teta , q   ,ps , masse,
425     $                 dufi, dvfi, dhfi , dqfi ,dpfi  )
426!       else
427!          print*,'Currently no physics in this GCM...'
428!       endif
429c
430       ENDIF
431
432       CALL pression ( ip1jmp1, ap, bp, ps, p                  )
433
434       CALL exner_hyb( ip1jmp1, ps, p,beta, pks, pk, pkf )
435c   ----------------------------------------------------------
436
437c
438c
439c   dissipation horizontale et verticale  des petites echelles:
440c   ----------------------------------------------------------
441
442      IF(apdiss) THEN
443
444c        Sponge layer
445c        ~~~~~~~~~~~~
446
447         IF (callsponge) THEN
448           pext(1:ip1jmp1)=ps(1:ip1jmp1)*aire(1:ip1jmp1)
449           CALL sponge(ucov,vcov,teta,pext,dtdiss,mode_sponge)
450         ENDIF
451
452c        Dissipation horizontale
453c        ~~~~~~~~~~~~~~~~~~~~~~~
454
455
456         if(dissip_conservative) then
457!     calculate kinetic energy before dissipation
458            call covcont(llm,ucov,vcov,ucont,vcont)
459            call enercin(vcov,ucov,vcont,ucont,ecin0)
460         end if
461
462         CALL dissip(vcov,ucov,teta,p,dvdis,dudis,dhdis)
463
464         ucov(:,:)=ucov(:,:)+dudis(:,:)
465         vcov(:,:)=vcov(:,:)+dvdis(:,:)
466
467
468         if (dissip_conservative) then
469C           On rajoute la tendance due a la transform. Ec -> E therm. cree
470C           lors de la dissipation
471            call covcont(llm,ucov,vcov,ucont,vcont)
472            call enercin(vcov,ucov,vcont,ucont,ecin)
473            dtetaecdt(:,:) = (ecin0(:,:)-ecin(:,:))/ pk(:,:)
474            dhdis(:,:)     = dhdis(:,:) + dtetaecdt(:,:)
475         endif
476
477         teta(:,:)=teta(:,:)+dhdis(:,:)
478
479
480c    .......        P. Le Van (  ajout  le 17/04/96  )   ...........
481c   ...      Calcul de la valeur moyenne, unique de h aux poles  .....
482c
483
484        DO l  =  1, llm
485          DO ij =  1,iim
486           tppn(ij)  = aire(  ij    ) * teta(  ij    ,l)
487           tpps(ij)  = aire(ij+ip1jm) * teta(ij+ip1jm,l)
488          ENDDO
489
490           tpn  = SSUM(iim,tppn,1)/apoln
491           tps  = SSUM(iim,tpps,1)/apols
492
493          DO ij = 1, iip1
494           teta(  ij    ,l) = tpn
495           teta(ij+ip1jm,l) = tps
496          ENDDO
497        ENDDO
498
499        DO ij =  1,iim
500          tppn(ij)  = aire(  ij    ) * ps (  ij    )
501          tpps(ij)  = aire(ij+ip1jm) * ps (ij+ip1jm)
502        ENDDO
503          tpn  = SSUM(iim,tppn,1)/apoln
504
505          tps  = SSUM(iim,tpps,1)/apols
506
507        DO ij = 1, iip1
508          ps(  ij    ) = tpn
509          ps(ij+ip1jm) = tps
510        ENDDO
511
512
513
514
515
516
517
518      END IF
519       
520c   ********************************************************************
521c   ********************************************************************
522c   .... fin de l'integration dynamique  et physique pour le pas itau ..
523c   ********************************************************************
524c   ********************************************************************
525
526c   preparation du pas d'integration suivant  ......
527
528      IF ( .NOT.purmats ) THEN
529c       ........................................................
530c       ..............  schema matsuno + leapfrog  ..............
531c       ........................................................
532
533            IF(forward. OR. leapf) THEN
534              itau= itau + 1
535              iday= day_ini+itau/day_step
536              time= FLOAT(itau-(iday-day_ini)*day_step)/day_step+time_0
537                IF(time.GT.1.) THEN
538                  time = time-1.
539                  iday = iday+1
540                ENDIF
541            ENDIF
542
543
544            IF( itau. EQ. itaufinp1 ) then 
545              abort_message = 'Simulation finished'
546              call abort_gcm(modname,abort_message,0)
547            ENDIF
548c-----------------------------------------------------------------------
549c   ecriture du fichier histoire moyenne:
550c   -------------------------------------
551
552c           IF(MOD(itau,iperiod).EQ.0 .OR. itau.EQ.itaufin) THEN
553c              IF(itau.EQ.itaufin) THEN
554c                 iav=1
555c              ELSE
556c                 iav=0
557c              ENDIF
558c              CALL writedynav(histaveid, nqmx, itau,vcov ,
559c    ,                          ucov,teta,pk,phi,q,masse,ps,phis)
560c           ENDIF
561
562c-----------------------------------------------------------------------
563
564
565            IF(itau.EQ.itaufin) THEN
566
567
568       PRINT *,' Appel test_period avant redem ', itau
569       CALL test_period ( ucov,vcov,teta,q,p,phis )
570       CALL dynredem1("restart.nc",0.0,
571     .                     vcov,ucov,teta,q,nqmx,masse,ps)
572
573              CLOSE(99)
574            ENDIF
575
576c-----------------------------------------------------------------------
577c   gestion de l'integration temporelle:
578c   ------------------------------------
579
580            IF( MOD(itau,iperiod).EQ.0 )    THEN
581                    GO TO 1
582            ELSE IF ( MOD(itau-1,iperiod). EQ. 0 ) THEN
583
584                   IF( forward )  THEN
585c      fin du pas forward et debut du pas backward
586
587                      forward = .FALSE.
588                        leapf = .FALSE.
589                           GO TO 2
590
591                   ELSE
592c      fin du pas backward et debut du premier pas leapfrog
593
594                        leapf =  .TRUE.
595                        dt  =  2.*dtvr
596                        GO TO 2
597                   END IF
598            ELSE
599
600c      ......   pas leapfrog  .....
601
602                 leapf = .TRUE.
603                 dt  = 2.*dtvr
604                 GO TO 2
605            END IF
606
607      ELSE
608
609c       ........................................................
610c       ..............       schema  matsuno        ...............
611c       ........................................................
612            IF( forward )  THEN
613
614             itau =  itau + 1
615             iday = day_ini+itau/day_step
616             time = FLOAT(itau-(iday-day_ini)*day_step)/day_step+time_0
617
618                  IF(time.GT.1.) THEN
619                   time = time-1.
620                   iday = iday+1
621                  ENDIF
622
623               forward =  .FALSE.
624               IF( itau. EQ. itaufinp1 ) then 
625                 abort_message = 'Simulation finished'
626                 call abort_gcm(modname,abort_message,0)
627               ENDIF
628               GO TO 2
629
630            ELSE
631
632            IF(MOD(itau,iperiod).EQ.0 .OR. itau.EQ.itaufin) THEN
633               IF(itau.EQ.itaufin) THEN
634                  iav=1
635               ELSE
636                  iav=0
637               ENDIF
638c              CALL writedynav(histaveid, nqmx, itau,vcov ,
639c    ,                          ucov,teta,pk,phi,q,masse,ps,phis)
640
641            ENDIF
642
643
644                 IF(itau.EQ.itaufin)
645     . CALL dynredem1("restart.nc",0.0,
646     .                     vcov,ucov,teta,q,nqmx,masse,ps)
647
648                 forward = .TRUE.
649                 GO TO  1
650
651
652            ENDIF
653
654      END IF
655
656      STOP
657      END
Note: See TracBrowser for help on using the repository browser.