source: LMDZ6/branches/Portage_acc/libf/dyn3d/driver.F90 @ 4151

Last change on this file since 4151 was 4151, checked in by Ehouarn Millour, 2 years ago

Add a "driver" main program for OpenACC testing of the physics.
"driver" compiles just like gcm, reads in start* files and calls (and updates) physics in a time marching loop.
EM

File size: 15.4 KB
Line 
1PROGRAM driver
2
3  USE IOIPSL, ONLY: getin, ymds2ju, ioconf_calendar
4  USE mod_const_mpi, ONLY: COMM_LMDZ
5  USE control_mod, ONLY: planet_type, config_inca, offline
6  USE control_mod, ONLY: nday, day_step, iphysiq, dayref, anneeref
7  USE infotrac, ONLY: type_trac, nqtot, infotrac_init
8  USE temps_mod, ONLY: calend,start_time,annee_ref,day_ref
9  USE temps_mod, ONLY: itau_dyn,itau_phy,day_ini,jD_ref,jH_ref,day_end,year_len
10  USE comconst_mod, ONLY: cpp, kappa, daysec, dtphys, dtvr, g, r, rad
11  USE comconst_mod, ONLY: daylen, year_day, pi, omeg
12  USE logic_mod, ONLY: iflag_phys
13  USE comvert_mod, ONLY: preff, pa
14  USE inigeomphy_mod, ONLY: inigeomphy
15  USE iniphysiq_mod, ONLY: iniphysiq
16
17  IMPLICIT NONE
18
19  include "dimensions.h"
20  include "paramet.h"
21  include "comgeom.h"
22
23!  INTEGER :: step_per_day = 24 ! # of physics steps per day
24
25  INTEGER :: ngrid ! # of grid points on physics grid = 2+(jjm-1)*iim-1/jjm
26
27!  REAL, PARAMETER :: unjours=86400.,    & ! solar day in seconds
28!       &             radius=6.4e6,      & ! planetary radius
29!       &             g=9.8,             & ! gravity
30!       &             cpp=1004.,         & ! Cp
31!       &             kappa=296.945007/cpp ! R/Cp
32!  REAL :: timestep !=unjours/step_per_day ! physics time step (s)
33
34!  REAL :: psurf=1e5, ptop=1e4, Temp=250. ! initial values of surface pressure, temperature
35
36  ! dynamics (to load data from start.nc)
37  REAL,ALLOCATABLE :: ucov(:,:) ! covariant zonal wind
38  REAL,ALLOCATABLE :: vcov(:,:) ! covariant meridional wind
39  REAL,ALLOCATABLE :: teta(:,:) ! potential temperature
40  REAL,ALLOCATABLE :: q(:,:,:) ! tracers
41  REAL,ALLOCATABLE :: masse(:,:) ! air mass
42  REAL,ALLOCATABLE :: ps(:) ! surface pressure
43  REAL,ALLOCATABLE :: phis(:) ! surface geopotential
44  REAL :: time_0
45 
46  ! physics
47  REAL,ALLOCATABLE :: pplev(:,:)  ! pressure at interfaces
48  REAL,ALLOCATABLE :: pplay(:,:) ! pressure at full levels
49  REAL,ALLOCATABLE :: pphi(:,:) ! geopotential at full levels
50  REAL,ALLOCATABLE :: pphis(:) ! surface geopotential
51  REAL,ALLOCATABLE :: pt(:,:) ! temperature at full levels
52  REAL,ALLOCATABLE :: pu(:,:) ! zonal wind at full levels
53  REAL,ALLOCATABLE :: pv(:,:) ! meridional wind at full levels
54  REAL,ALLOCATABLE :: pq(:,:,:)! tracers
55  REAL,ALLOCATABLE :: pr(:,:) ! vorticity
56
57  !$acc data create(pplev, pplay, pphi, pphis, pt, pu, pv, pq, pr)
58
59! 0. Preliminary stuff: read in parameters from run.def
60  call conf_gcm( 99, .TRUE.)
61!  call conf_planete
62 
63  daysec=86400. ! day length(s)
64  daylen=daysec
65  year_day=360 ! # days per year
66  rad=6.4e6 ! planet radius (m)
67  g=9.81 ! gravity
68  cpp=1004. ! Cp
69  r=287.05967 ! R
70  kappa=287.05967/cpp ! R/Cp
71  preff=101325.0
72  pa=preff/2.
73  pi=2.*asin(1.)
74  omeg=2.*pi/daysec*(1./daylen+1./year_day)
75 
76!  nday = 1 ! simulation lenght (days)
77!  CALL getin("nday",nday)
78  WRITE(*,*)"driver: nday=",nday
79 
80!  CALL getin("day_step",day_step)
81  WRITE(*,*)"driver: day_step=",day_step
82  dtphys=daysec/(day_step/iphysiq) ! physics time step (s)
83  dtvr=daysec/day_step
84  WRITE(*,*)"driver: timestep= dtphys=",dtphys
85 
86 
87 
88! 1. Initialize setup (geometry, physics)
89! 1.0. Parameters
90  planet_type="earth"
91  COMM_LMDZ=1
92  iflag_phys=1
93 
94
95! 1.1. Tracers-related
96  type_trac="lmdz"
97  config_inca="none"
98  offline=.false.
99 
100  call infotrac_init
101 
102  ! 1.2. Geometry
103
104!  CALL init_latlon(lat, lon)
105!  WRITE(*,*)"driver: LAT = " , minval(lat), maxval(lat)
106!  WRITE(*,*)"driver: LON = " , minval(lon), maxval(lon)
107  ! initialize dyn constants and geometry
108  CALL iniconst
109  CALL inigeom
110
111  ! 1.3. Initial conditions
112  ! dynamics
113  ALLOCATE(ucov(ip1jmp1,llm))
114  ALLOCATE(vcov(ip1jm,llm))
115  ALLOCATE(teta(ip1jmp1,llm))
116  ALLOCATE(q(ip1jmp1,llm,nqtot))
117  ALLOCATE(masse(ip1jmp1,llm))
118  ALLOCATE(ps(ip1jmp1))
119  ALLOCATE(phis(ip1jmp1))
120 
121  CALL dynetat0("start.nc",vcov,ucov,teta,q,masse,ps,phis,time_0)
122 
123
124  ! 1.3. Calendar
125!  annee_ref=2000
126!  dayref=1
127  if (calend == 'earth_360d' ) then
128    call ioconf_calendar('360d')
129  else
130    write(*,*) "potential calendar problem with IOIPSL!!"
131  endif
132  year_len=360
133
134!  annee_ref = anneeref
135!  day_ref = dayref
136!  day_ini = dayref
137  itau_dyn = 0
138  itau_phy = 0
139
140  ! Calendar
141!  call ymds2ju(annee_ref, mois, day_ref, heure, jD_ref)
142  call ymds2ju(annee_ref, 1, day_ref, 0., jD_ref)
143  jH_ref = jD_ref - int(jD_ref)
144  jD_ref = int(jD_ref)
145!  call ioconf_startdate(INT(jD_ref), jH_ref)
146 
147
148  day_end = day_ini + nday
149
150  ! 1.4. Initialize physics
151  ngrid=2+(jjm-1)*iim-1/jjm
152  write(*,*) "driver: ngrid=",ngrid
153  CALL iniphysiq(iim,jjm,llm, &
154          ngrid,comm_lmdz, &
155          daysec,day_ini,dtphys, &
156          rlatu,rlatv,rlonu,rlonv,aire,cu,cv,rad,g,r,cpp, &
157          iflag_phys)
158
159 
160! 2. Initialize fields on physics grid
161
162  ALLOCATE(pplev(ngrid,llm+1)) ! pressure at interfaces
163  ALLOCATE(pplay(ngrid,llm)) ! pressure at full levels
164  ALLOCATE(pphi(ngrid,llm)) ! geopotential at full levels
165  ALLOCATE(pphis(ngrid)) ! surface geopotential
166  ALLOCATE(pt(ngrid,llm)) ! temperature (K) at full levels
167  ALLOCATE(pu(ngrid,llm)) ! zonal wind (m/s) at full levels
168  ALLOCATE(pr(ngrid,llm)) ! relative vorticity
169  ALLOCATE(pv(ngrid,llm)) ! meridional wind at full levels
170  ALLOCATE(pq(ngrid,llm,nqtot)) ! tracers
171
172  CALL init_temperature_pressure_geopot(ps,masse,teta,phis, &
173                                        ngrid,pplev,pplay,pphi,pphis,pt)
174  CALL init_winds_tracers(ucov,vcov,q,nqtot, &
175                          ngrid,pu,pv,pr,pq)
176
177! 3. Temporal loop 
178
179  CALL timeloop(ngrid,llm,nqtot,nday,day_step/iphysiq,dtphys,&
180                pplev,pplay,pphi,pphis,&
181                pu,pv,pr,pt,pq)
182
183  !$acc end data
184
185  write(*,*)"driver: Everything is cool :-)"
186
187CONTAINS
188
189!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
190
191   SUBROUTINE timeloop(ngrid,llm,nqtot,nday,calls_per_day,dtphys,&
192                pplev,pplay,pphi,pphis,&
193                pu,pv,pr,pt,pq)
194
195   USE comvert_mod, ONLY: presnivs
196   USE physiq_mod, ONLY: physiq
197   USE comconst_mod, ONLY: r
198   IMPLICIT NONE
199
200   INTEGER,INTENT(IN) :: ngrid ! # number of atmospheric columns
201   INTEGER,INTENT(IN) :: llm ! # number of vertical levels
202   INTEGER,INTENT(IN) :: nqtot ! # of tracers
203   INTEGER,INTENT(IN) :: nday ! # of days to run
204   INTEGER,INTENT(IN) :: calls_per_day ! # number of calls to physics per day
205   REAL,INTENT(IN) :: dtphys ! physics time step (s)
206   REAL,INTENT(INOUT) :: pplev(ngrid,llm+1) ! pressure at interfaces
207   REAL,INTENT(INOUT) :: pplay(ngrid,llm) ! pressure at mid-layer
208   REAL,INTENT(INOUT) :: pphi(ngrid,llm) ! geopotential at mid-layer
209   REAL,INTENT(INOUT) :: pphis(ngrid) ! surface geopotential
210   REAL,INTENT(INOUT) :: pu(ngrid,llm) ! zonal wind (m/s)
211   REAL,INTENT(INOUT) :: pv(ngrid,llm) ! meridional wind (m/s)
212   REAL,INTENT(INOUT) :: pr(ngrid,llm) ! relative vorticity
213   REAL,INTENT(INOUT) :: pt(ngrid,llm) ! temperature (K)
214   REAL,INTENT(INOUT) :: pq(ngrid,llm,nqtot) ! tracers
215   
216   LOGICAL,SAVE :: firstcall=.true.
217   LOGICAL,SAVE :: lastcall=.false.
218   REAL :: JD_cur ! Julian day
219   REAL :: JH_cur ! Julian hour (fraction of day)
220   ! tendencies from the physics
221   REAL :: pdu(ngrid,llm)
222   REAL :: pdv(ngrid,llm)
223   REAL :: pdt(ngrid,llm)
224   REAL :: pdq(ngrid,llm,nqtot)
225   REAL :: pdps(ngrid)
226   !$acc data create(pdu,pdv,pdt,pdq,pdps)
227   
228   INTEGER :: iday,istep
229   INTEGER :: ig,l
230   REAL :: rho,gdz
231
232   REAL :: flxw(ngrid,llm) ! vertical mass flux ! set to zero here.
233   REAL :: phi_top(ngrid)
234   !$acc data create(phi_top,flxw)
235   
236   flxw(1:ngrid,1:llm)=0.
237   
238   DO iday=1,nday
239     JD_cur=iday
240     DO istep = 0, calls_per_day-1
241       JH_cur=istep/calls_per_day
242       if ((iday==nday).and.(istep==calls_per_day-1)) lastcall=.true.
243       CALL physiq(ngrid,llm,firstcall,lastcall,dtphys, &
244                   pplev,pplay,pphi,pphis, &
245                   presnivs, &
246                   pu,pv,pr,pt,pq,flxw, &
247                   pdu,pdv,pdt,pdq,pdps)
248       firstcall=.false.
249       
250       ! add increments sent back from physics:
251       !$acc kernels default(present)
252       pt(:,:)=pt(:,:)+dtphys*pdt(:,:)
253       pu(:,:)=pu(:,:)+dtphys*pdu(:,:)
254       pv(:,:)=pv(:,:)+dtphys*pdv(:,:)
255       pq(:,:,:)=pq(:,:,:)+dtphys*pdq(:,:,:)
256       !$acc end kernels
257       
258       ! Recomputation of relative geopotential:
259       phi_top(:)=0
260       !$acc loop private(rho, gdz)
261       do l=1,llm
262         do ig=1,ngrid
263           ! rho=p/RT
264           rho=r*pplay(ig,l)/pt(ig,l)
265           gdz=(pplev(ig,l)-pplev(ig,l+1))/rho ! layer thickness * g
266           pphi(ig,l)=phi_top(ig)+0.5*gdz ! geopotential at mid-layer
267           phi_top(ig)=phi_top(ig)+gdz ! geopotential at layer top
268         enddo
269       enddo
270       !$acc end kernels
271       
272     ENDDO ! of DO istep = 0, day_step-1
273   ENDDO ! of DO iday=0,nday-1
274   
275   END SUBROUTINE timeloop
276
277
278!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
279
280   SUBROUTINE init_winds_tracers(ucov,vcov,q,nqtot, &
281                                 ngrid,pu,pv,pr,pq)
282
283    USE comconst_mod, ONLY: pi
284   
285    IMPLICIT NONE
286
287    include "dimensions.h"
288    include "paramet.h"
289    include "comgeom2.h"
290
291     REAL,INTENT(IN) :: ucov(iip1,jjp1,llm) ! covariant meridional velocity
292     REAL,INTENT(IN) :: vcov(iip1,jjm,llm) ! covariant zonal wind
293     REAL,INTENT(IN) :: q(iip1,jjp1,llm,nqtot) ! tracers
294     INTEGER,INTENT(IN) :: nqtot ! # of tracers
295     INTEGER,INTENT(IN) :: ngrid ! # of physics columns
296     REAL,INTENT(OUT) :: pu(ngrid,llm) ! zonal wind speed on physics grid
297     REAL,INTENT(OUT) :: pv(ngrid,llm) ! meridional wind speed on physics grid
298     REAL,INTENT(OUT) :: pr(ngrid,llm) ! vorticity on physics grid
299     REAL,INTENT(OUT) :: pq(ngrid,llm,nqtot) ! tracers on physics grid
300     
301     INTEGER :: i,j,l,iq,ig0
302     REAL :: rot(iim,jjm,llm) ! rot, on dynamics grid
303     REAL :: z1(iim),zsin(iim),zcos(iim)
304     REAL,EXTERNAL :: ssum
305     
306     ! 1. Compute zonal wind on physics grid
307     do l=1,llm
308       do j=2,jjm
309         ig0=1+(j-2)*iim
310         pu(ig0+1,l)=0.5*(ucov(iim,j,l)/cu(iim,j) + ucov(1,j,l)/cu(1,j))
311         do i=2,iim
312           pu(ig0+i,l)=0.5*(ucov(i-1,j,l)/cu(i-1,j) + ucov(i,j,l)/cu(i,j))
313         enddo
314       enddo ! of do j=2,jjm
315     enddo ! of do l=1,llm
316     
317     ! North pole: u = 1/pi * Integral[v * cos(long) * d long]
318     do l=1,llm
319       z1(1)=(rlonu(1)-rlonu(iim)+2.*pi)*vcov(1,1,l)/cv(1,1)
320       do i=2,iim
321         z1(i)=(rlonu(i)-rlonu(i-1))*vcov(i,1,l)/cv(i,1)
322       enddo
323       zcos(1:iim)=cos(rlonv(1:iim))*z1(1:iim)
324       pu(1,l)=ssum(iim,zcos,1)/pi
325     enddo ! of l=1,llm
326     
327     ! South pole: u = 1/pi * Integral[v * cos(long) * d long]
328     do l=1,llm
329       z1(1)=(rlonu(1)-rlonu(iim)+2.*pi)*vcov(1,jjm,l)/cv(1,jjm)
330       do i=2,iim
331         z1(i)=(rlonu(i)-rlonu(i-1))*vcov(i,jjm,l)/cv(i,jjm)
332       enddo
333       zcos(1:iim)=cos(rlonv(1:iim))*z1(1:iim)
334       pu(ngrid,l)=ssum(iim,zcos,1)/pi     
335     enddo ! of do l=1,llm
336     
337     
338     ! 2. Compute meridional wind on physics grid
339     do l=1,llm
340       do j=2,jjm
341         ig0=1+(j-2)*iim
342         do i=1,iim
343           pv(ig0+i,l)=0.5*(vcov(i,j-1,l)/cv(i,j-1) + vcov(i,j,l)/cv(i,j))
344         enddo
345       enddo ! of do j=2,jjm
346     enddo ! of do l=1,llm
347     
348     ! North pole: v = 1/pi * Integral[v * sin(long) * d long ]
349     do l=1,llm
350       z1(1)=(rlonu(1)-rlonu(iim)+2.*pi)*vcov(1,1,l)/cv(1,1)
351       do i=2,iim
352         z1(i)=(rlonu(i)-rlonu(i-1))*vcov(i,1,l)/cv(i,1)
353       enddo
354       zsin(1:iim)=sin(rlonv(1:iim))*z1(1:iim)
355       pv(1,l)=ssum(iim,zsin,1)/pi
356     enddo ! of l=1,llm
357     
358     ! South pole: v = 1/pi * Integral[v * sin(long) * d long ]
359     do l=1,llm
360       z1(1)=(rlonu(1)-rlonu(iim)+2.*pi)*vcov(1,jjm,l)/cv(1,jjm)
361       do i=2,iim
362         z1(i)=(rlonu(i)-rlonu(i-1))*vcov(i,jjm,l)/cv(i,jjm)
363       enddo
364       zsin(1:iim)=sin(rlonv(1:iim))*z1(1:iim)
365       pv(ngrid,l)=ssum(iim,zsin,1)/pi
366     enddo  ! of do l=1,llm
367     
368     
369     ! 3. Compute vorticity, first on dynamics grid
370     do l=1,llm
371       do i=1,iim
372         do j=1,jjm
373           rot(i,j,l)=(vcov(i+1,j,l)-vcov(i,j,l) + ucov(i,j+1,l)-ucov(i,j,l)) / &
374                      ((cu(i,j)+cu(i,j+1))*(cv(i+1,j)+cv(i,j))*4)
375         enddo
376       enddo ! of do i=1,iim
377     enddo  ! of do l=1,llm
378     
379     ! compute vorticity, on physics grid
380     do l=1,llm
381       ! North Pole:
382       pr(1,l)=0.
383       do j=2,jjm
384         ig0=1+(j-2)*iim
385         pr(ig0+1,l)=0.25*(rot(iim,j-1,l)+rot(iim,j,l)+ &
386                           rot(1,j-1,l)+rot(1,j,l))
387         do i=2,iim
388           pr(ig0+i,l)=0.25*(rot(i-1,j-1,l)+rot(i-1,j,l)+ &
389                             rot(i,j-1,l)+rot(i,j,l))
390         enddo
391       enddo ! of do j=2,jjm
392       ! South pole
393       pr(ngrid,l)=0.
394     enddo ! of do l=1,llm
395     
396     ! 4. Tracers, copy them over to the physics grid
397     do iq=1,nqtot
398       CALL gr_dyn_fi(llm,iip1,jjp1,ngrid,q(1,1,1,iq),pq(1,1,iq))
399     enddo
400     
401  END SUBROUTINE init_winds_tracers
402
403!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
404
405  SUBROUTINE init_temperature_pressure_geopot(ps,masse,teta,phis, &
406                                              ngrid,pplev,pplay,pphi,pphis,pt)
407
408    USE comvert_mod, ONLY: ap,bp
409    USE exner_hyb_m, ONLY: exner_hyb
410    USE comconst_mod, ONLY: cpp
411    USE geopot_mod, ONLY: geopot
412
413    IMPLICIT NONE
414
415    include "dimensions.h"
416    include "paramet.h"
417
418    REAL,INTENT(IN) :: ps(ip1jmp1)   ! surface pressure (Pa) on dyn grid
419    REAL,INTENT(IN) :: masse(ip1jmp1,llm) ! air mass on dyn. grid
420    REAL,INTENT(IN) :: teta(ip1jmp1,llm) ! potential temperature on dyn grid
421    REAL,INTENT(IN) :: phis(ip1jmp1)   ! surface geopotential on dyn grid
422    INTEGER,INTENT(IN) :: ngrid ! # of physics columns
423    REAL,INTENT(OUT) :: pplev(ngrid,llm+1) ! pressure at interfaces
424    REAL,INTENT(OUT) :: pplay(ngrid, llm) ! pressure at mid-layer
425    REAL,INTENT(OUT) :: pphi(ngrid, llm) ! geopotential phi=gz at mid-layer
426    REAL,INTENT(OUT) :: pphis(ngrid) ! surface geopotential
427    REAL,INTENT(OUT) :: pt(ngrid, llm) ! temperature at mid-layer
428
429    REAL :: p(ip1jmp1,llmp1) ! interlayer pressure on dynamics grid
430    REAL :: pks(ip1jmp1) ! Exner at the surface
431    REAL :: pk(ip1jmp1,llm) ! Exner at mid-layer
432    REAL :: phi(ip1jmp1,llm) ! Geopotential on dynamics grid
433   
434    REAL :: ppk(ngrid,llm) ! Exner at mid-layer on physics grid
435    REAL :: pteta(ngrid,llm) ! potential temperature on physics grid
436   
437    INTEGER :: ig,l
438
439    ! 1. Compute necessary intermediate variables on dynamics grid
440    ! Compute pressure on dynamics grid
441    CALL pression(ip1jmp1,ap,bp,ps,p)
442    ! Compute Exner on dynamics grid
443    CALL exner_hyb(ip1jmp1,ps,p,pks,pk)
444    ! Compute geopotential on dynamics grid
445    CALL geopot(ip1jmp1,teta,pk,pks,phis,phi)
446   
447    ! 2. Output fields, on physics grid
448   
449    ! Copy over p() to pplev()
450    CALL gr_dyn_fi(llm+1,iip1,jjp1,ngrid,p,pplev)
451   
452    ! Compute pplay() based on ab(),bp() and pplev(:,1) (surface pressure)
453    do ig=1,ngrid
454      pplay(ig,1:llm)=0.5*(ap(1:llm)+bp(1:llm)*pplev(ig,1)+&
455                           ap(2:llm+1)+bp(2:llm+1)*pplev(ig,1))
456    enddo
457   
458    ! Copy surface geopotential phis() to pphis()
459    CALL gr_dyn_fi(1,iip1,jjp1,ngrid,phis,pphis)
460   
461    ! Copy geopotential phi() to pphi()
462    CALL gr_dyn_fi(llm,iip1,jjp1,ngrid,phi,pphi)
463    ! and make pphi relative to surface
464    do l=1,llm
465      pphi(1:ngrid,l)=pphi(1:ngrid,l)-pphis(1:ngrid)
466    enddo
467   
468    ! Compute temperature from teta, on physics grid
469    CALL gr_dyn_fi(llm,iip1,jjp1,ngrid,pk,ppk)
470    CALL gr_dyn_fi(llm,iip1,jjp1,ngrid,teta,pteta)
471    do l=1,llm
472      pt(1:ngrid,l)=pteta(1:ngrid,l)*ppk(1:ngrid,l)/cpp
473    enddo
474   
475
476  END SUBROUTINE init_temperature_pressure_geopot
477
478END PROGRAM driver
Note: See TracBrowser for help on using the repository browser.