source: codes/icosagcm/devel/src/time/timeloop_gcm.f90

Last change on this file was 968, checked in by jisesh, 5 years ago

devel : nudge also surface pressure

File size: 16.1 KB
RevLine 
[12]1MODULE timeloop_gcm_mod
[714]2  USE profiling_mod
[151]3  USE icosa
[360]4  USE disvert_mod
5  USE trace
6  USE omp_para
[906]7  USE compute_diagnostics_mod, ONLY : compute_rhodz
[360]8  USE euler_scheme_mod
9  USE explicit_scheme_mod
10  USE hevi_scheme_mod
[732]11  USE caldyn_vars_mod
[350]12  IMPLICIT NONE
[133]13  PRIVATE
[12]14 
[186]15  INTEGER, PARAMETER :: itau_sync=10
[377]16  TYPE(t_message),SAVE :: req_ps0, req_mass0, req_theta_rhodz0, req_u0, req_q0, req_W0, req_geopot0
17  LOGICAL, SAVE :: positive_theta
[714]18  INTEGER :: itau_prof, id_timeloop, id_dyn, id_phys, id_dissip, id_adv, id_diags
[360]19  PUBLIC :: init_timeloop, timeloop
[151]20
[12]21CONTAINS
22 
[151]23  SUBROUTINE init_timeloop
[360]24    USE dissip_gcm_mod
25    USE observable_mod
26    USE caldyn_mod
27    USE etat0_mod
28    USE guided_mod
29    USE advect_tracer_mod
30    USE check_conserve_mod
31    USE output_field_mod
32    USE theta2theta_rhodz_mod
33    USE sponge_mod
[12]34
[360]35    CHARACTER(len=255) :: def
[413]36
[714]37    CALL register_id('timeloop',id_timeloop)
38    CALL register_id('dyn',id_dyn)
39    CALL register_id('dissip',id_dissip)
40    CALL register_id('phys',id_phys)
41    CALL register_id('adv',id_adv)
42    CALL register_id('diags',id_diags)
43
[413]44    CALL init_caldyn
[360]45   
[429]46!    IF (xios_output) itau_out=1
[360]47    IF (.NOT. enable_io) itau_out=HUGE(itau_out)
[377]48
[714]49    itau_prof=100
50    CALL getin('itau_profiling',itau_prof)
51
[377]52    positive_theta=.FALSE.
53    CALL getin('positive_theta',positive_theta)
54    IF(positive_theta .AND. nqtot<1) THEN
55       PRINT *, 'nqtot must be >0 if positive_theta is .TRUE.'
56       STOP
57    END IF
58
[376]59    def='ARK2.3'
[360]60    CALL getin('time_scheme',def)
61    SELECT CASE (TRIM(def))
62    CASE('euler')
63       scheme_family=explicit
64       scheme=euler
65       nb_stage=1
66    CASE ('runge_kutta')
67       scheme_family=explicit
68       scheme=rk4
69       nb_stage=4
70    CASE ('RK2.5')
71       scheme_family=explicit
72       scheme=rk25
73       nb_stage=5
74    CASE ('leapfrog_matsuno')
75       scheme_family=explicit
76       scheme=mlf
77       matsuno_period=5
78       CALL getin('matsuno_period',matsuno_period)
79       nb_stage=matsuno_period+1
[950]80    CASE('ARK1.1')
81       scheme_family=hevi
82       scheme=ark11
83       nb_stage=1
84       CALL set_coefs_ark11(dt)
[360]85    CASE('ARK2.3')
86       scheme_family=hevi
87       scheme=ark23
88       nb_stage=3
89       CALL set_coefs_ark23(dt)
90    CASE('ARK3.3')
91       scheme_family=hevi
92       scheme=ark33
93       nb_stage=3
94       CALL set_coefs_ark33(dt)
95    CASE ('none')
96       nb_stage=0
97    CASE default
[950]98       PRINT*,'Bad selector for variable scheme : <' // TRIM(def) // '>, ', &
99            'options are <euler>, <runge_kutta>, <leapfrog_matsuno>, <RK2.5>,<ARK2.3>, ,<ARK1.1>'
[360]100       STOP
101    END SELECT
102   
103    ! Time-independant orography
[159]104    CALL allocate_field(f_phis,field_t,type_real,name='phis')
[360]105    ! Model state at current time step
[159]106    CALL allocate_field(f_ps,field_t,type_real, name='ps')
107    CALL allocate_field(f_mass,field_t,type_real,llm,name='mass')
[360]108    CALL allocate_field(f_rhodz,field_t,type_real,llm,name='rhodz')
[387]109    CALL allocate_field(f_theta_rhodz,field_t,type_real,llm,nqdyn,name='theta_rhodz')
[159]110    CALL allocate_field(f_u,field_u,type_real,llm,name='u')
[366]111    CALL allocate_field(f_geopot,field_t,type_real,llm+1,name='geopot')
112    CALL allocate_field(f_W,field_t,type_real,llm+1,name='W')
[266]113    CALL allocate_field(f_q,field_t,type_real,llm,nqtot,'q')
[360]114    ! Mass fluxes
[159]115    CALL allocate_field(f_hflux,field_u,type_real,llm)    ! instantaneous mass fluxes
116    CALL allocate_field(f_hfluxt,field_u,type_real,llm)   ! mass "fluxes" accumulated in time
117    CALL allocate_field(f_wflux,field_t,type_real,llm+1)  ! vertical mass fluxes
[360]118    CALL allocate_field(f_wfluxt,field_t,type_real,llm+1,name='wfluxt')
119   
120    SELECT CASE(scheme_family)
121    CASE(explicit)
[909]122       IF(caldyn_conserv == conserv_gassmann) THEN
123          PRINT *, 'caldyn_conserv = energy_gassmann is not implemented for RK time schemes, use time_scheme=ARK2.3 .'
124          STOP
125       END IF
[360]126       ! Trends
[159]127       CALL allocate_field(f_dps,field_t,type_real,name='dps')
[360]128       CALL allocate_field(f_dmass,field_t,type_real,llm, name='dmass')
[387]129       CALL allocate_field(f_dtheta_rhodz,field_t,type_real,llm,nqdyn,name='dtheta_rhodz')
[360]130       CALL allocate_field(f_du,field_u,type_real,llm,name='du')
131       ! Model state at previous time step (RK/MLF)
[159]132       CALL allocate_field(f_psm1,field_t,type_real,name='psm1')
[162]133       CALL allocate_field(f_massm1,field_t,type_real,llm, name='massm1')
[387]134       CALL allocate_field(f_theta_rhodzm1,field_t,type_real,llm,nqdyn,name='theta_rhodzm1')
[360]135       CALL allocate_field(f_um1,field_u,type_real,llm,name='um1')
136    CASE(hevi)
137       ! Trends
138       CALL allocate_fields(nb_stage,f_dps_slow, field_t,type_real,name='dps_slow')
139       CALL allocate_fields(nb_stage,f_dmass_slow, field_t,type_real,llm, name='dmass_slow')
[387]140       CALL allocate_fields(nb_stage,f_dtheta_rhodz_slow, field_t,type_real,llm,nqdyn,name='dtheta_rhodz_fast')
[360]141       CALL allocate_fields(nb_stage,f_du_slow, field_u,type_real,llm,name='du_slow')
142       CALL allocate_fields(nb_stage,f_du_fast, field_u,type_real,llm,name='du_fast')
[366]143       CALL allocate_fields(nb_stage,f_dW_slow, field_t,type_real,llm+1,name='dW_slow')
144       CALL allocate_fields(nb_stage,f_dW_fast, field_t,type_real,llm+1,name='dW_fast')
145       CALL allocate_fields(nb_stage,f_dPhi_slow, field_t,type_real,llm+1,name='dPhi_slow')
146       CALL allocate_fields(nb_stage,f_dPhi_fast, field_t,type_real,llm+1,name='dPhi_fast')
[360]147       f_dps => f_dps_slow(:,1)
148       f_du => f_du_slow(:,1)
149       f_dtheta_rhodz => f_dtheta_rhodz_slow(:,1)
150    END SELECT
[151]151
[360]152    SELECT CASE(scheme)
153    CASE(mlf)
154       ! Model state 2 time steps ago (MLF)
155       CALL allocate_field(f_psm2,field_t,type_real)
156       CALL allocate_field(f_massm2,field_t,type_real,llm)
[387]157       CALL allocate_field(f_theta_rhodzm2,field_t,type_real,llm,nqdyn)
[360]158       CALL allocate_field(f_um2,field_u,type_real,llm)
[151]159    END SELECT
160
[295]161    CALL init_theta2theta_rhodz
[151]162    CALL init_dissip
[327]163    CALL init_sponge
[354]164    CALL init_observable
[151]165    CALL init_advect_tracer
166    CALL init_check_conserve
[186]167
[366]168    CALL etat0(f_ps,f_mass,f_phis,f_theta_rhodz,f_u, f_geopot,f_W, f_q)
[968]169   
170    CALL init_guided(f_u,f_theta_rhodz,f_ps)
[151]171
172    CALL transfert_request(f_phis,req_i0) 
173    CALL transfert_request(f_phis,req_i1) 
174
175    CALL init_message(f_ps,req_i0,req_ps0)
[162]176    CALL init_message(f_mass,req_i0,req_mass0)
[151]177    CALL init_message(f_theta_rhodz,req_i0,req_theta_rhodz0)
178    CALL init_message(f_u,req_e0_vect,req_u0)
179    CALL init_message(f_q,req_i0,req_q0)
[377]180    CALL init_message(f_geopot,req_i0,req_geopot0)
181    CALL init_message(f_W,req_i0,req_W0)
[151]182
183  END SUBROUTINE init_timeloop
[12]184 
[151]185  SUBROUTINE timeloop
[360]186    USE dissip_gcm_mod
187    USE sponge_mod
188    USE observable_mod
189    USE etat0_mod
190    USE guided_mod
191    USE caldyn_mod
192    USE advect_tracer_mod
[584]193    USE diagflux_mod
[360]194    USE physics_mod
195    USE mpipara
196    USE transfert_mod
197    USE check_conserve_mod
198    USE xios_mod
199    USE output_field_mod
200    USE write_etat0_mod
[528]201    USE restart_mod
[360]202    USE checksum_mod
203    USE explicit_scheme_mod
204    USE hevi_scheme_mod
205    REAL(rstd),POINTER :: rhodz(:,:), mass(:,:), ps(:)
[12]206
[592]207    REAL(rstd) :: adv_over_out ! ratio itau_adv/itau_out
208    INTEGER :: ind, it,i,j,l,n,  stage
209    LOGICAL :: fluxt_zero(ndomain) ! set to .TRUE. to start accumulating mass fluxes in time
[360]210    LOGICAL, PARAMETER :: check_rhodz=.FALSE.
211    INTEGER :: start_clock, stop_clock, rate_clock
[327]212    LOGICAL,SAVE :: first_physic=.TRUE.
[360]213    !$OMP THREADPRIVATE(first_physic)   
214
[295]215    CALL switch_omp_distrib_level
[350]216    CALL caldyn_BC(f_phis, f_geopot, f_wflux) ! set constant values in first/last interfaces
[132]217
[360]218    !$OMP BARRIER
219    DO ind=1,ndomain
220       IF (.NOT. assigned_domain(ind)) CYCLE
221       CALL swap_dimensions(ind)
222       CALL swap_geometry(ind)
223       rhodz=f_rhodz(ind); mass=f_mass(ind); ps=f_ps(ind)
224       IF(caldyn_eta==eta_mass) THEN
225          CALL compute_rhodz(.TRUE., ps, rhodz) ! save rhodz for transport scheme before dynamics update ps
226       ELSE
227          DO l=ll_begin,ll_end
228             rhodz(:,l)=mass(:,l)
229          ENDDO
230       END IF
231    END DO
232    !$OMP BARRIER
233    fluxt_zero=.TRUE.
[186]234
[387]235    IF(positive_theta) CALL copy_theta_to_q(f_theta_rhodz,f_rhodz,f_q)
[592]236    IF(diagflux_on) THEN
237       adv_over_out = itau_adv*(1./itau_out)
238    ELSE
239       adv_over_out = 0.
240    END IF
[377]241
[360]242    CALL check_conserve(f_ps,f_dps,f_u,f_theta_rhodz,f_phis,itau0) 
[326]243
[584]244    Call trace_on
[186]245
[413]246    IF (xios_output) THEN ! we must call update_calendar before any XIOS output
[473]247      IF (is_omp_master) CALL xios_update_calendar(1)
[413]248    END IF
[528]249   
[569]250!    IF (write_start) CALL write_etat0(itau0,f_ps, f_phis,f_theta_rhodz,f_u,f_q)
251    IF (write_start) CALL write_etat0(itau0,f_ps, f_phis,f_theta_rhodz,f_u,f_q, f_geopot, f_W)
[528]252   
[413]253    CALL write_output_fields_basic(.TRUE., f_phis, f_ps, f_mass, f_geopot, f_theta_rhodz, f_u, f_W, f_q)
254
[529]255    !$OMP MASTER
[714]256    CALL SYSTEM_CLOCK(start_clock, rate_clock)
[529]257    !$OMP END MASTER   
258
[360]259    DO it=itau0+1,itau0+itaumax
[364]260       IF (is_master) CALL print_iteration(it, itau0, itaumax, start_clock, rate_clock)
[413]261
[714]262       CALL enter_profile(id_timeloop)
263
[364]264       IF (xios_output) THEN
[473]265
266          IF(it>itau0+1 .AND. is_omp_master) CALL xios_update_calendar(it-itau0)
[364]267       ELSE
268          CALL update_time_counter(dt*it)
269       END IF
[295]270
[360]271       IF (it==itau0+1 .OR. MOD(it,itau_sync)==0) THEN
272          CALL send_message(f_ps,req_ps0)
273          CALL wait_message(req_ps0)
274          CALL send_message(f_mass,req_mass0)
275          CALL wait_message(req_mass0)
276          CALL send_message(f_theta_rhodz,req_theta_rhodz0) 
277          CALL wait_message(req_theta_rhodz0) 
278          CALL send_message(f_u,req_u0)
279          CALL wait_message(req_u0)
280          CALL send_message(f_q,req_q0) 
[377]281          CALL wait_message(req_q0)
282          IF(.NOT. hydrostatic) THEN
[499]283             CALL send_message(f_geopot,req_geopot0)
284             CALL wait_message(req_geopot0)
285             CALL send_message(f_W,req_W0)
286             CALL wait_message(req_W0)
[377]287          END IF
[167]288       ENDIF
[327]289
[360]290       CALL guided(it*dt,f_ps,f_theta_rhodz,f_u,f_q)
[326]291
[714]292       CALL enter_profile(id_dyn)
[360]293       SELECT CASE(scheme_family)
294       CASE(explicit)
295          CALL explicit_scheme(it, fluxt_zero)
296       CASE(hevi)
297          CALL HEVI_scheme(it, fluxt_zero)
298       END SELECT
[714]299       CALL exit_profile(id_dyn)
[594]300
[714]301       CALL enter_profile(id_dissip)
[360]302       IF (MOD(it,itau_dissip)==0) THEN
303         
304          IF(caldyn_eta==eta_mass) THEN
305             !ym flush ps
306             !$OMP BARRIER
307             DO ind=1,ndomain
308                IF (.NOT. assigned_domain(ind)) CYCLE
309                CALL swap_dimensions(ind)
310                CALL swap_geometry(ind)
311                mass=f_mass(ind); ps=f_ps(ind);
312                CALL compute_rhodz(.TRUE., ps, mass)
[162]313             END DO
[360]314          ENDIF
315         
[714]316          CALL enter_profile(id_diags)
[365]317          CALL check_conserve_detailed(it, AAM_dyn, &
318               f_ps,f_dps,f_u,f_theta_rhodz,f_phis)
[714]319          CALL exit_profile(id_diags)
[365]320       
[529]321          CALL dissip(f_ps,f_mass,f_phis,f_geopot,f_theta_rhodz,f_u, f_dtheta_rhodz,f_du)
[360]322         
323          CALL euler_scheme(.FALSE.)  ! update only u, theta
324          IF (iflag_sponge > 0) THEN
325             CALL sponge(f_u,f_du,f_theta_rhodz,f_dtheta_rhodz)
326             CALL euler_scheme(.FALSE.)  ! update only u, theta
[162]327          END IF
[365]328
[714]329          CALL enter_profile(id_diags)
[365]330          CALL check_conserve_detailed(it, AAM_dissip, &
331               f_ps,f_dps,f_u,f_theta_rhodz,f_phis)
[714]332          CALL exit_profile(id_diags)
[360]333       END IF
[714]334       CALL exit_profile(id_dissip)
[148]335       
[714]336       CALL enter_profile(id_adv)
[360]337       IF(MOD(it,itau_adv)==0) THEN
[592]338          CALL advect_tracer(f_hfluxt,f_wfluxt,f_u, f_q,f_rhodz, & ! update q and rhodz after RK step
339               adv_over_out, f_masst,f_qmasst,f_massfluxt, f_qfluxt)  ! accumulate mass and fluxes if diagflux_on
[594]340          fluxt_zero=.TRUE. ! restart accumulation of hfluxt and qfluxt at next call to explicit_scheme / HEVI_scheme
[595]341          ! At this point advect_tracer has obtained the halos of u and rhodz,
342          ! needed for correct computation of kinetic energy
[601]343          IF(diagflux_on) CALL diagflux_energy(adv_over_out, f_phis,f_rhodz,f_theta_rhodz,f_u, f_geopot,f_theta,f_buf_i, f_hfluxt)
[595]344
[594]345          IF (check_rhodz) THEN ! check that rhodz is consistent with ps
[360]346             DO ind=1,ndomain
347                IF (.NOT. assigned_domain(ind)) CYCLE
348                CALL swap_dimensions(ind)
349                CALL swap_geometry(ind)
350                rhodz=f_rhodz(ind); ps=f_ps(ind);
351                CALL compute_rhodz(.FALSE., ps, rhodz)   
352             END DO
353          ENDIF
[387]354          IF(positive_theta) CALL copy_q_to_theta(f_theta_rhodz,f_rhodz,f_q)
[159]355       END IF
[714]356       CALL exit_profile(id_adv)
[360]357       
[714]358       CALL enter_profile(id_diags)
[360]359       IF (MOD(it,itau_physics)==0) THEN
[365]360          CALL check_conserve_detailed(it, AAM_dyn, &
361            f_ps,f_dps,f_u,f_theta_rhodz,f_phis)
[714]362          CALL enter_profile(id_phys)
[741]363          CALL physics(it, f_phis, f_geopot, f_ps, f_theta_rhodz, f_u, f_wflux, f_q)
[714]364          CALL exit_profile(id_phys)
[365]365          CALL check_conserve_detailed(it, AAM_phys, &
366               f_ps,f_dps,f_u,f_theta_rhodz,f_phis)
[360]367          !$OMP MASTER
368          IF (first_physic) CALL SYSTEM_CLOCK(start_clock)
369          !$OMP END MASTER   
370          first_physic=.FALSE.
[159]371       END IF
[365]372
373       IF (MOD(it,itau_check_conserv)==0) THEN
374          CALL check_conserve_detailed(it, AAM_dyn, &
375               f_ps,f_dps,f_u,f_theta_rhodz,f_phis)
376          CALL check_conserve(f_ps,f_dps,f_u,f_theta_rhodz,f_phis,it) 
[413]377       ENDIF
[407]378
379       IF (mod(it,itau_out)==0 ) THEN
380          CALL transfert_request(f_u,req_e1_vect)
[413]381          CALL write_output_fields_basic(.FALSE.,f_phis, f_ps, f_mass, f_geopot, f_theta_rhodz, f_u, f_W, f_q)
[407]382       ENDIF
[714]383       CALL exit_profile(id_diags)
[407]384
[714]385       CALL exit_profile(id_timeloop)
[360]386    END DO
387   
[569]388!    CALL write_etat0(itau0+itaumax,f_ps, f_phis,f_theta_rhodz,f_u,f_q)
389    CALL write_etat0(itau0+itaumax,f_ps, f_phis,f_theta_rhodz,f_u,f_q, f_geopot, f_W) 
[360]390   
[365]391    CALL check_conserve_detailed(it, AAM_dyn, &
392         f_ps,f_dps,f_u,f_theta_rhodz,f_phis)
[360]393    CALL check_conserve(f_ps,f_dps,f_u,f_theta_rhodz,f_phis,it) 
394   
395    !$OMP MASTER
396    CALL SYSTEM_CLOCK(stop_clock)
397   
398    IF (mpi_rank==0) THEN
399       PRINT *,"Time elapsed : ",(stop_clock-start_clock)*1./rate_clock 
400    ENDIF
401    !$OMP END MASTER
402   
403    ! CONTAINS
404  END SUBROUTINE timeloop
[364]405
406  SUBROUTINE print_iteration(it,itau0,itaumax,start_clock,rate_clock)
407    INTEGER :: it, itau0, itaumax, start_clock, stop_clock, rate_clock, throughput
408    REAL :: per_step,total, elapsed
[365]409    WRITE(*,'(A,I7,A,F14.1)') "It No :",it,"   t :",dt*it
[364]410    IF(MOD(it,10)==0) THEN
411       CALL SYSTEM_CLOCK(stop_clock)
412       elapsed = (stop_clock-start_clock)*1./rate_clock
413       per_step = elapsed/(it-itau0)
414       throughput = dt/per_step
[609]415       total = per_step*itaumax
[364]416       WRITE(*,'(A,I5,A,F6.2,A,I6)') 'Time spent (s):',INT(elapsed), &
417            '  -- ms/step : ', 1000*per_step, &
418            '  -- Throughput :', throughput
419       WRITE(*,'(A,I5,A,I5)') 'Whole job (min) :', INT(total/60.), &
420            '  -- Completion in (min) : ', INT((total-elapsed)/60.)
421    END IF
[714]422    IF(MOD(it,itau_prof)==0) CALL print_profile
423
[364]424  END SUBROUTINE print_iteration
425
[387]426  SUBROUTINE copy_theta_to_q(f_theta_rhodz,f_rhodz,f_q)
[377]427    TYPE(t_field),POINTER :: f_theta_rhodz(:),f_rhodz(:), f_q(:)
[387]428    REAL(rstd), POINTER :: theta_rhodz(:,:,:), rhodz(:,:), q(:,:,:)
429    INTEGER :: ind, iq
[377]430    DO ind=1, ndomain
431       IF (.NOT. assigned_domain(ind)) CYCLE
432       CALL swap_dimensions(ind)
433       CALL swap_geometry(ind)
434       theta_rhodz=f_theta_rhodz(ind)
435       rhodz=f_rhodz(ind)
436       q=f_q(ind)
[387]437       DO iq=1, nqdyn
438          q(:,:,iq)  = theta_rhodz(:,:,iq)/rhodz(:,:)
439       END DO
[377]440    END DO
[387]441  END SUBROUTINE copy_theta_to_q
[377]442
[387]443  SUBROUTINE copy_q_to_theta(f_theta_rhodz,f_rhodz,f_q)
[377]444    TYPE(t_field),POINTER :: f_theta_rhodz(:),f_rhodz(:), f_q(:)
[387]445    REAL(rstd), POINTER :: theta_rhodz(:,:,:), rhodz(:,:), q(:,:,:)
446    INTEGER :: ind, iq
[377]447    DO ind=1, ndomain
448       IF (.NOT. assigned_domain(ind)) CYCLE
449       CALL swap_dimensions(ind)
450       CALL swap_geometry(ind)
451       theta_rhodz=f_theta_rhodz(ind)
452       rhodz=f_rhodz(ind)
453       q=f_q(ind)
[387]454       DO iq=1,nqdyn
455          theta_rhodz(:,:,iq) = rhodz(:,:)*q(:,:,iq)
456       END DO
[377]457    END DO
[387]458  END SUBROUTINE copy_q_to_theta
[377]459
[12]460END MODULE timeloop_gcm_mod
Note: See TracBrowser for help on using the repository browser.