source: codes/icosagcm/trunk/src/timeloop_gcm.f90 @ 139

Last change on this file since 139 was 139, checked in by dubos, 11 years ago

caldyn_adv is back

File size: 14.7 KB
RevLine 
[12]1MODULE timeloop_gcm_mod
[133]2
3  PRIVATE
[12]4 
[133]5  PUBLIC :: timeloop
6
7  INTEGER, PARAMETER :: euler=1, rk4=2, mlf=3
8
[12]9CONTAINS
10 
11  SUBROUTINE timeloop
[19]12  USE icosa
[15]13  USE dissip_gcm_mod
[17]14  USE caldyn_mod
[12]15  USE etat0_mod
[17]16  USE guided_mod
17  USE advect_tracer_mod
[81]18  USE physics_mod
[131]19  USE mpipara
[17]20 
[12]21  IMPLICIT NONE
22  TYPE(t_field),POINTER :: f_phis(:)
[129]23!  TYPE(t_field),POINTER :: f_theta(:)
[17]24  TYPE(t_field),POINTER :: f_q(:)
[132]25  TYPE(t_field),POINTER :: f_dtheta(:), f_rhodz(:)
[12]26  TYPE(t_field),POINTER :: f_ps(:),f_psm1(:), f_psm2(:)
27  TYPE(t_field),POINTER :: f_u(:),f_um1(:),f_um2(:)
28  TYPE(t_field),POINTER :: f_theta_rhodz(:),f_theta_rhodzm1(:),f_theta_rhodzm2(:)
29  TYPE(t_field),POINTER :: f_dps(:),f_dpsm1(:), f_dpsm2(:)
30  TYPE(t_field),POINTER :: f_du(:),f_dum1(:),f_dum2(:)
31  TYPE(t_field),POINTER :: f_dtheta_rhodz(:),f_dtheta_rhodzm1(:),f_dtheta_rhodzm2(:)
[133]32  TYPE(t_field),POINTER :: f_hflux(:), f_wflux(:), f_hfluxt(:), f_wfluxt(:)
[12]33
34  REAL(rstd),POINTER :: phis(:)
[17]35  REAL(rstd),POINTER :: q(:,:,:)
[12]36  REAL(rstd),POINTER :: ps(:) ,psm1(:), psm2(:)
37  REAL(rstd),POINTER :: u(:,:) , um1(:,:), um2(:,:)
[133]38  REAL(rstd),POINTER :: rhodz(:,:), theta_rhodz(:,:) , theta_rhodzm1(:,:), theta_rhodzm2(:,:)
[12]39  REAL(rstd),POINTER :: dps(:), dpsm1(:), dpsm2(:)
40  REAL(rstd),POINTER :: du(:,:), dum1(:,:), dum2(:,:)
41  REAL(rstd),POINTER :: dtheta_rhodz(:,:),dtheta_rhodzm1(:,:),dtheta_rhodzm2(:,:)
[133]42  REAL(rstd),POINTER :: hflux(:,:),wflux(:,:),hfluxt(:,:),wfluxt(:,:)
[50]43
[98]44!  REAL(rstd) :: dt, run_length
[12]45  INTEGER :: ind
[133]46  INTEGER :: it,i,j,n, nb_stage, stage, matsuno_period, scheme
47  CHARACTER(len=255) :: scheme_name
[138]48  LOGICAL :: fluxt_zero(ndomain) ! set to .TRUE. to start accumulating fluxes in time
[98]49!  INTEGER :: itaumax
50!  REAL(rstd) ::write_period
51!  INTEGER    :: itau_out
[63]52 
[98]53!  dt=90.
54!  CALL getin('dt',dt)
[32]55 
[98]56!  itaumax=100
57!  CALL getin('itaumax',itaumax)
[17]58
[98]59!  run_length=dt*itaumax
60!  CALL getin('run_length',run_length)
61!  itaumax=run_length/dt
62!  PRINT *,'itaumax=',itaumax
63!  dt=dt/scale_factor
[45]64
[129]65! Trends
66  CALL allocate_field(f_dps,field_t,type_real)
67  CALL allocate_field(f_du,field_u,type_real,llm)
68  CALL allocate_field(f_dtheta_rhodz,field_t,type_real,llm)
69! Model state at current time step (RK/MLF/Euler)
70  CALL allocate_field(f_phis,field_t,type_real)
71  CALL allocate_field(f_ps,field_t,type_real)
72  CALL allocate_field(f_u,field_u,type_real,llm)
73  CALL allocate_field(f_theta_rhodz,field_t,type_real,llm)
74! Model state at previous time step (RK/MLF)
75  CALL allocate_field(f_psm1,field_t,type_real)
76  CALL allocate_field(f_um1,field_u,type_real,llm)
77  CALL allocate_field(f_theta_rhodzm1,field_t,type_real,llm)
78! Tracers
79  CALL allocate_field(f_q,field_t,type_real,llm,nqtot)
[132]80  CALL allocate_field(f_rhodz,field_t,type_real,llm)
[134]81! Mass fluxes
[133]82  CALL allocate_field(f_hflux,field_u,type_real,llm)    ! instantaneous mass fluxes
83  CALL allocate_field(f_wflux,field_t,type_real,llm+1)  ! computed by caldyn
84  CALL allocate_field(f_hfluxt,field_u,type_real,llm)   ! mass "fluxes" accumulated in time
85  CALL allocate_field(f_wfluxt,field_t,type_real,llm+1)
[129]86
[133]87  scheme_name='runge_kutta'
88  CALL getin('scheme',scheme_name)
[129]89
[133]90  SELECT CASE (TRIM(scheme_name))
[129]91  CASE('euler')
[133]92     scheme=euler
[129]93     nb_stage=1
94  CASE ('runge_kutta')
[133]95     scheme=rk4
[129]96     nb_stage=4
97  CASE ('leapfrog_matsuno')
[133]98     scheme=mlf
[129]99     matsuno_period=5
100     CALL getin('matsuno_period',matsuno_period)
101     nb_stage=matsuno_period+1
102     ! Model state 2 time steps ago (MLF)
103     CALL allocate_field(f_psm2,field_t,type_real)
104     CALL allocate_field(f_theta_rhodzm2,field_t,type_real,llm)
105     CALL allocate_field(f_um2,field_u,type_real,llm)
106  CASE default
[133]107     PRINT*,'Bad selector for variable scheme : <', TRIM(scheme_name),             &
[129]108          ' > options are <euler>, <runge_kutta>, <leapfrog_matsuno>'
109     STOP
110  END SELECT
[12]111 
[98]112!  write_period=0
113!  CALL getin('write_period',write_period)
114!  write_period=write_period/scale_factor
115!  itau_out=FLOOR(.5+write_period/dt)
116!  PRINT *, 'Output frequency (scaled) set to ',write_period, ' : itau_out = ',itau_out
[63]117 
[129]118! Trends at previous time steps needed only by Adams-Bashforth
119!  CALL allocate_field(f_dpsm1,field_t,type_real)
120!  CALL allocate_field(f_dpsm2,field_t,type_real)
121!  CALL allocate_field(f_dum1,field_u,type_real,llm)
122!  CALL allocate_field(f_dum2,field_u,type_real,llm)
123!  CALL allocate_field(f_dtheta_rhodzm1,field_t,type_real,llm)
124!  CALL allocate_field(f_dtheta_rhodzm2,field_t,type_real,llm)
[12]125
[129]126!  CALL allocate_field(f_theta,field_t,type_real,llm)
127!  CALL allocate_field(f_dtheta,field_t,type_real,llm)
[12]128
[98]129  CALL init_dissip
130  CALL init_caldyn
131  CALL init_guided
132  CALL init_advect_tracer
133  CALL init_physics
[12]134 
[17]135  CALL etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
[97]136  CALL writefield("phis",f_phis,once=.TRUE.)
[81]137  CALL transfert_request(f_q,req_i1) 
[50]138
[133]139  DO ind=1,ndomain
140     CALL swap_dimensions(ind)
141     CALL swap_geometry(ind)
142     rhodz=f_rhodz(ind); ps=f_ps(ind)
[138]143     CALL compute_rhodz(.TRUE., ps,rhodz) ! save rhodz for transport scheme before dynamics update ps
[133]144  END DO
[138]145  fluxt_zero=.TRUE.
[132]146
[138]147  ! check that rhodz is consistent with ps
148  CALL transfert_request(f_rhodz,req_i1)
149  CALL transfert_request(f_ps,req_i1)
150  DO ind=1,ndomain
151     CALL swap_dimensions(ind)
152     CALL swap_geometry(ind)
153     rhodz=f_rhodz(ind); ps=f_ps(ind)
154     CALL compute_rhodz(.FALSE., ps, rhodz)   
155  END DO
156 
[12]157  DO it=0,itaumax
[81]158
[131]159    IF (is_mpi_root) PRINT *,"It No :",It,"   t :",dt*It
[63]160    IF (mod(it,itau_out)==0 ) THEN
161      CALL writefield("q",f_q)
[81]162      CALL update_time_counter(dt*it)
[63]163    ENDIF
164   
[139]165    CALL guided(it*dt,f_ps,f_theta_rhodz,f_u,f_q)
[129]166
167    DO stage=1,nb_stage
168       CALL caldyn((stage==1) .AND. (MOD(it,itau_out)==0), &
[132]169            f_phis,f_ps,f_theta_rhodz,f_u, f_q, &
[134]170            f_hflux, f_wflux, f_dps, f_dtheta_rhodz, f_du)
[133]171       SELECT CASE (scheme)
172       CASE(euler)
173          CALL euler_scheme(.TRUE.)
174       CASE (rk4)
[129]175          CALL rk_scheme(stage)
[133]176       CASE (mlf)
[129]177          CALL  leapfrog_matsuno_scheme(stage)
178         
179          !      CASE ('leapfrog')
180          !        CALL leapfrog_scheme
181          !
182          !      CASE ('adam_bashforth')
183          !        CALL dissip(f_u,f_du,f_ps,f_phis, f_theta_rhodz,f_dtheta_rhodz)
184          !        CALL adam_bashforth_scheme
[133]185       CASE DEFAULT
[129]186          STOP
187       END SELECT
188    END DO
[130]189
[131]190    CALL dissip(f_u,f_du,f_ps,f_phis, f_theta_rhodz,f_dtheta_rhodz)
191    CALL euler_scheme(.FALSE.)
[130]192
[133]193    IF(MOD(it+1,itau_adv)==0) THEN
[138]194       CALL transfert_request(f_wfluxt,req_i1) ! FIXME
195!       CALL transfert_request(f_hfluxt,req_e1) ! FIXME
196
[135]197       CALL advect_tracer(f_hfluxt,f_wfluxt,f_u, f_q,f_rhodz)  ! update q and rhodz after RK step
[134]198       fluxt_zero=.TRUE.
[138]199
200       ! FIXME : check that rhodz is consistent with ps
201       CALL transfert_request(f_rhodz,req_i1)
202       CALL transfert_request(f_ps,req_i1)
203       CALL transfert_request(f_dps,req_i1) ! FIXME
204       CALL transfert_request(f_wflux,req_i1) ! FIXME
205       DO ind=1,ndomain
206          CALL swap_dimensions(ind)
207          CALL swap_geometry(ind)
208          rhodz=f_rhodz(ind); ps=f_ps(ind); dps=f_dps(ind); 
209          wflux=f_wflux(ind); wfluxt=f_wfluxt(ind)
210          CALL compute_rhodz(.FALSE., ps, rhodz)   
211       END DO
212
[133]213    END IF
214
[124]215!    CALL physics(it,f_phis, f_ps, f_theta_rhodz, f_u, f_q)
[129]216    ENDDO
217 
[12]218  CONTAINS
219
[130]220    SUBROUTINE Euler_scheme(with_dps)
[12]221    IMPLICIT NONE
[130]222    LOGICAL :: with_dps
223    INTEGER :: ind
224    DO ind=1,ndomain
[138]225       CALL swap_dimensions(ind)
226       CALL swap_geometry(ind)
[130]227       IF(with_dps) THEN
228          ps=f_ps(ind) ; dps=f_dps(ind) ; 
229          ps(:)=ps(:)+dt*dps(:)
[133]230          hflux=f_hflux(ind);     hfluxt=f_hfluxt(ind)
[138]231          wflux=f_wflux(ind);     wfluxt=f_wfluxt(ind)
232          CALL accumulate_fluxes(hflux,wflux,hfluxt,wfluxt,dt,fluxt_zero(ind))
[130]233       END IF
234       u=f_u(ind) ; theta_rhodz=f_theta_rhodz(ind)
235       du=f_du(ind) ; dtheta_rhodz=f_dtheta_rhodz(ind)
236       u(:,:)=u(:,:)+dt*du(:,:)
237       theta_rhodz(:,:)=theta_rhodz(:,:)+dt*dtheta_rhodz(:,:)
238    ENDDO
[133]239
[12]240    END SUBROUTINE Euler_scheme
[120]241
[129]242    SUBROUTINE RK_scheme(stage)
[120]243      IMPLICIT NONE
244      INTEGER :: ind, stage
[129]245      REAL(rstd), DIMENSION(4), PARAMETER :: coef = (/ .25, 1./3., .5, 1. /)
[120]246      REAL(rstd) :: tau
247
248      tau = dt*coef(stage)
[129]249     
[120]250      DO ind=1,ndomain
[138]251         CALL swap_dimensions(ind)
252         CALL swap_geometry(ind)
[120]253         ps=f_ps(ind)   ; u=f_u(ind)   ; theta_rhodz=f_theta_rhodz(ind)
254         psm1=f_psm1(ind) ; um1=f_um1(ind) ; theta_rhodzm1=f_theta_rhodzm1(ind)
255         dps=f_dps(ind) ; du=f_du(ind) ; dtheta_rhodz=f_dtheta_rhodz(ind)
[129]256         
257         IF (stage==1) THEN ! first stage : save model state in XXm1
[120]258            psm1(:)=ps(:) ; um1(:,:)=u(:,:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:)
259         END IF
[129]260         ! updates are of the form x1 := x0 + tau*f(x1)
[120]261         ps(:)=psm1(:)+tau*dps(:)
262         u(:,:)=um1(:,:)+tau*du(:,:)
263         theta_rhodz(:,:)=theta_rhodzm1(:,:)+tau*dtheta_rhodz(:,:)
[133]264         IF(stage==nb_stage) THEN ! accumulate mass fluxes at last stage
265            hflux=f_hflux(ind);     hfluxt=f_hfluxt(ind)
[138]266            wflux=f_wflux(ind);     wfluxt=f_wfluxt(ind)
267            CALL accumulate_fluxes(hflux,wflux, hfluxt,wfluxt, dt,fluxt_zero(ind))
[133]268         END IF
[120]269      END DO
270    END SUBROUTINE RK_scheme
271
[12]272    SUBROUTINE leapfrog_scheme
273    IMPLICIT NONE
274      INTEGER :: ind
275
276      DO ind=1,ndomain
[138]277        CALL swap_dimensions(ind)
278        CALL swap_geometry(ind)
[12]279        ps=f_ps(ind)   ; u=f_u(ind)   ; theta_rhodz=f_theta_rhodz(ind)
280        psm1=f_psm1(ind) ; um1=f_um1(ind) ; theta_rhodzm1=f_theta_rhodzm1(ind)
281        psm2=f_psm2(ind) ; um2=f_um2(ind) ; theta_rhodzm2=f_theta_rhodzm2(ind)
282        dps=f_dps(ind) ; du=f_du(ind) ; dtheta_rhodz=f_dtheta_rhodz(ind)
283
284        IF (it==0) THEN
285          psm2(:)=ps(:) ; theta_rhodzm2(:,:)=theta_rhodz(:,:) ; um2(:,:)=u(:,:) 
286
287          ps(:)=ps(:)+dt*dps(:)
288          u(:,:)=u(:,:)+dt*du(:,:)
289          theta_rhodz(:,:)=theta_rhodz(:,:)+dt*dtheta_rhodz(:,:)
290
291          psm1(:)=ps(:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:) ; um1(:,:)=u(:,:) 
292        ELSE
293       
294          ps(:)=psm2(:)+2*dt*dps(:)
295          u(:,:)=um2(:,:)+2*dt*du(:,:)
296          theta_rhodz(:,:)=theta_rhodzm2(:,:)+2*dt*dtheta_rhodz(:,:)
297
298          psm2(:)=psm1(:) ; theta_rhodzm2(:,:)=theta_rhodzm1(:,:) ; um2(:,:)=um1(:,:) 
299          psm1(:)=ps(:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:) ; um1(:,:)=u(:,:) 
300        ENDIF
301         
302      ENDDO
303    END SUBROUTINE leapfrog_scheme 
304 
[129]305    SUBROUTINE leapfrog_matsuno_scheme(stage)
[12]306    IMPLICIT NONE
[129]307    INTEGER :: ind, stage
308    REAL :: tau
309    tau = dt/nb_stage
[12]310      DO ind=1,ndomain
[138]311        CALL swap_dimensions(ind)
312        CALL swap_geometry(ind)
313
[12]314        ps=f_ps(ind)   ; u=f_u(ind)   ; theta_rhodz=f_theta_rhodz(ind)
315        psm1=f_psm1(ind) ; um1=f_um1(ind) ; theta_rhodzm1=f_theta_rhodzm1(ind)
316        psm2=f_psm2(ind) ; um2=f_um2(ind) ; theta_rhodzm2=f_theta_rhodzm2(ind)
317        dps=f_dps(ind) ; du=f_du(ind) ; dtheta_rhodz=f_dtheta_rhodz(ind)
318
319       
[129]320!        IF (MOD(it,matsuno_period+1)==0) THEN
321        IF (stage==1) THEN
[12]322          psm1(:)=ps(:) ; um1(:,:)=u(:,:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:)
[129]323          ps(:)=psm1(:)+tau*dps(:)
324          u(:,:)=um1(:,:)+tau*du(:,:)
325          theta_rhodz(:,:)=theta_rhodzm1(:,:)+tau*dtheta_rhodz(:,:)
[12]326
[129]327!        ELSE IF (MOD(it,matsuno_period+1)==1) THEN
328        ELSE IF (stage==2) THEN
[12]329
[129]330          ps(:)=psm1(:)+tau*dps(:)
331          u(:,:)=um1(:,:)+tau*du(:,:)
332          theta_rhodz(:,:)=theta_rhodzm1(:,:)+tau*dtheta_rhodz(:,:)
[12]333
334          psm2(:)=psm1(:) ; theta_rhodzm2(:,:)=theta_rhodzm1(:,:) ; um2(:,:)=um1(:,:) 
335          psm1(:)=ps(:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:) ; um1(:,:)=u(:,:) 
336
337        ELSE
338
[129]339          ps(:)=psm2(:)+2*tau*dps(:)
340          u(:,:)=um2(:,:)+2*tau*du(:,:)
341          theta_rhodz(:,:)=theta_rhodzm2(:,:)+2*tau*dtheta_rhodz(:,:)
[12]342
343          psm2(:)=psm1(:) ; theta_rhodzm2(:,:)=theta_rhodzm1(:,:) ; um2(:,:)=um1(:,:) 
344          psm1(:)=ps(:) ; theta_rhodzm1(:,:)=theta_rhodz(:,:) ; um1(:,:)=u(:,:) 
345
346        ENDIF
347     
348      ENDDO
349     
350    END SUBROUTINE leapfrog_matsuno_scheme 
351         
352    SUBROUTINE adam_bashforth_scheme
353    IMPLICIT NONE
354      INTEGER :: ind
355
356      DO ind=1,ndomain
[138]357        CALL swap_dimensions(ind)
358        CALL swap_geometry(ind)
[12]359        ps=f_ps(ind)   ; u=f_u(ind)   ; theta_rhodz=f_theta_rhodz(ind)
360        dps=f_dps(ind) ; du=f_du(ind) ; dtheta_rhodz=f_dtheta_rhodz(ind)
361        dpsm1=f_dpsm1(ind) ; dum1=f_dum1(ind) ; dtheta_rhodzm1=f_dtheta_rhodzm1(ind)
362        dpsm2=f_dpsm2(ind) ; dum2=f_dum2(ind) ; dtheta_rhodzm2=f_dtheta_rhodzm2(ind)
363
364        IF (it==0) THEN
365          dpsm1(:)=dps(:) ; dum1(:,:)=du(:,:) ; dtheta_rhodzm1(:,:)=dtheta_rhodz(:,:)
366          dpsm2(:)=dpsm1(:) ; dum2(:,:)=dum1(:,:) ; dtheta_rhodzm2(:,:)=dtheta_rhodzm1(:,:)
367        ENDIF
368             
369        ps(:)=ps(:)+dt*(23*dps(:)-16*dpsm1(:)+5*dpsm2(:))/12
370        u(:,:)=u(:,:)+dt*(23*du(:,:)-16*dum1(:,:)+5*dum2(:,:))/12
371        theta_rhodz(:,:)=theta_rhodz(:,:)+dt*(23*dtheta_rhodz(:,:)-16*dtheta_rhodzm1(:,:)+5*dtheta_rhodzm2(:,:))/12
372
373        dpsm2(:)=dpsm1(:) ; dum2(:,:)=dum1(:,:) ; dtheta_rhodzm2(:,:)=dtheta_rhodzm1(:,:)
374        dpsm1(:)=dps(:) ; dum1(:,:)=du(:,:) ; dtheta_rhodzm1(:,:)=dtheta_rhodz(:,:)
375
[50]376      ENDDO     
[12]377     
378    END SUBROUTINE adam_bashforth_scheme
379
[50]380  END SUBROUTINE timeloop   
[133]381
[138]382  SUBROUTINE compute_rhodz(comp, ps, rhodz)
[133]383    USE icosa
384    USE disvert_mod
[138]385    LOGICAL, INTENT(IN) :: comp ! .TRUE. to compute, .FALSE. to check
[133]386    REAL(rstd), INTENT(IN) :: ps(iim*jjm)
387    REAL(rstd), INTENT(OUT) :: rhodz(iim*jjm,llm)
[138]388    REAL(rstd) :: m, err
389    INTEGER :: l,i,j,ij,dd
390    err=0.
391    IF(comp) THEN
392       dd=1
393    ELSE
394!       dd=-1
395       dd=0
396    END IF
397
[133]398    DO l = 1, llm
[138]399       DO j=jj_begin-dd,jj_end+dd
400          DO i=ii_begin-dd,ii_end+dd
[133]401             ij=(j-1)*iim+i
[138]402             m = ( ap(l) - ap(l+1) + (bp(l)-bp(l+1))*ps(ij) )/g 
403             IF(comp) THEN
404                rhodz(ij,l) = m
405             ELSE
406                err = MAX(err,abs(m-rhodz(ij,l)))
407             END IF
[133]408          ENDDO
409       ENDDO
410    ENDDO
[138]411
412    IF(.NOT. comp) THEN
413       IF(err>1e-10) THEN
414          PRINT *, 'Discrepancy between ps and rhodz detected', err
415          STOP
416       ELSE
417!          PRINT *, 'No discrepancy between ps and rhodz detected'
418       END IF
419    END IF
420
[133]421  END SUBROUTINE compute_rhodz
422
[138]423  SUBROUTINE accumulate_fluxes(hflux,wflux, hfluxt,wfluxt, tau,fluxt_zero)
[133]424    USE icosa
425    REAL(rstd), INTENT(IN)    :: hflux(3*iim*jjm,llm), wflux(iim*jjm,llm+1)
426    REAL(rstd), INTENT(INOUT) :: hfluxt(3*iim*jjm,llm), wfluxt(iim*jjm,llm+1)
427    REAL(rstd), INTENT(IN) :: tau
[134]428    LOGICAL, INTENT(INOUT) :: fluxt_zero
429    IF(fluxt_zero) THEN
[138]430!       PRINT *, 'Accumulating fluxes (first)'
[134]431       fluxt_zero=.FALSE.
432       hfluxt = tau*hflux
433       wfluxt = tau*wflux
434    ELSE
[138]435!       PRINT *, 'Accumulating fluxes (next)'
[134]436       hfluxt = hfluxt + tau*hflux
437       wfluxt = wfluxt + tau*wflux
438    END IF
[133]439  END SUBROUTINE accumulate_fluxes
[12]440 
441END MODULE timeloop_gcm_mod
Note: See TracBrowser for help on using the repository browser.