source: trunk/LMDZ.MARS/libf/phymars/wstats_mod.F90 @ 3225

Last change on this file since 3225 was 2997, checked in by emillour, 19 months ago

Mars PCM:
Some adaptations to enable running the 1D model with XIOS.
Note that this requires compiling with "-io xios -parallel mpi"
but the model should then be run using a single core, i.e. without mpirun
EM

File size: 27.6 KB
RevLine 
[2559]1module wstats_mod
2
3! module containing parameters and routines to generate the "stats.nc" file
4! which will contain a mean statistical day of variables extracted at set
5! times of day every day of the simulation, and the standard deviations thereof
6
7implicit none
8
9logical,save :: callstats ! global flag to trigger generating a stats.nc
10                          ! file or not. Initialized in conf_gcm()
11!$OMP THREADPRIVATE(callstats)
12
13integer,save :: istats ! calculate stats every istats physics timestep,
14                       ! starting at first call. Initialized by inistats()
15!$OMP THREADPRIVATE(istats)
16
17integer,parameter :: istime=12 ! number of time steps per sol to store
18
19integer,save :: count(istime) ! count tab to know the variable record
[2573]20!$OMP THREADPRIVATE(count)
[2559]21
22contains
23
[38]24subroutine wstats(ngrid,nom,titre,unite,dim,px)
25
[2559]26! Main routine to call to trigger writing a given field to the "stats.nc" file
27
[1130]28use mod_phys_lmdz_para, only : is_mpi_root, is_master, gather, klon_mpi_begin
[1528]29use mod_grid_phy_lmdz, only : klon_glo, Grid1Dto2D_glo, &
[2563]30                              nbp_lon, nbp_lat, nbp_lev, &
31                              grid_type, unstructured
[38]32implicit none
33
[1528]34include "netcdf.inc"
[38]35
36integer,intent(in) :: ngrid
37character (len=*),intent(in) :: nom,titre,unite
38integer,intent(in) :: dim
[1528]39real,intent(in) :: px(ngrid,nbp_lev)
[1532]40real,allocatable,save :: mean3d(:,:,:),sd3d(:,:,:),dx3(:,:,:)
41real,allocatable,save :: mean2d(:,:),sd2d(:,:),dx2(:,:)
[38]42character (len=50) :: namebis
43character (len=50), save :: firstvar
[2616]44!$OMP THREADPRIVATE(mean3d,sd3d,dx3,mean2d,sd2d,dx2,firstvar)
[1130]45integer :: ierr,varid,nbdim,nid
[38]46integer :: meanid,sdid
[1130]47integer, dimension(4)  :: id,start,sizes
[38]48logical, save :: firstcall=.TRUE.
[1130]49integer,save :: indx
[38]50integer, save :: step=0
[1532]51!$OMP THREADPRIVATE(firstcall,indx,step)
[2563]52integer :: l,i,j,ig0,n
[38]53
[2563]54! Added to read an optional stats.def file to select outputs
55logical,save :: stats_def ! .true. if there is a stats.def file
56integer,save :: n_name_def ! number of fields to output in stats.nc
57! NB: stats_def and n_name_def do not need be threadprivate
58integer,parameter :: n_name_def_max=199 ! max number of fields to output
59character(len=120),save :: name_def(n_name_def_max)
60logical :: getout ! to trigger an early exit if variable not in output list
61
[2616]62!$OMP THREADPRIVATE(stats_def,n_name_def,name_def)
63
[1130]64! Added to work in parallel mode
65#ifdef CPP_PARA
[1528]66real px3_glop(klon_glo,nbp_lev) ! to store a 3D data set on global physics grid
67real px3_glo(nbp_lon,nbp_lat,nbp_lev) ! to store a global 3D data set on global lonxlat grid
[1130]68real px2_glop(klon_glo) ! to store a 2D data set on global physics grid
[1528]69real px2_glo(nbp_lon,nbp_lat) ! to store a 2D data set on global lonxlat grid
[1130]70real px2(ngrid)
[1528]71real px3(ngrid,nbp_lev)
[1130]72#else
73! When not running in parallel mode:
[1528]74real px3_glop(ngrid,nbp_lev) ! to store a 3D data set on global physics grid
75real px3_glo(nbp_lon,nbp_lat,nbp_lev) ! to store a global 3D data set on global lonxlat grid
[1130]76real px2_glop(ngrid) ! to store a 2D data set on global physics grid
[1528]77real px2_glo(nbp_lon,nbp_lat) ! to store a 2D data set on global lonxlat grid
[1130]78#endif
79
[2563]80! 0. Preliminary stuff
81if (callstats.eqv..false.) then
82  ! exit because creating/writing stats.nc not requested by user
83  return
84endif
85
86if (grid_type==unstructured) then
87  ! exit because non-structured grid case is not handled
88  return
89endif
90
[1130]91! 1. Initialization (creation of stats.nc file)
[38]92if (firstcall) then
93   firstcall=.false.
[2563]94
95!$OMP MASTER
96  ! open stats.def definition file if there is one
97  open(99,file="stats.def",status='old',form='formatted',&
98       iostat=ierr)
99  if (ierr.eq.0) then
100    stats_def=.true. ! yes there is a stats.def file
101    write(*,*) "*****************"
102    write(*,*) "Reading stats.def"
103    write(*,*) "*****************"
104    do n=1,n_name_def_max
105      read(99,fmt='(a)',end=88) name_def(n)
106      write(*,*) 'Output in stats: ', trim(name_def(n))
107    enddo
10888  continue
109    ! check there is no overflow
110    if (n.ge.n_name_def_max) then
111      write(*,*) "n_name_def_max too small in wstats:",n
112      call abort_physic("wstats","n_name_def_max too small",1)
113    endif
114    n_name_def=n-1
115    close(99)
116  else
117    stats_def=.false. ! no stats.def file; output all fields sent to wstats
118  endif ! of if (ierr.eq.0)
119!$OMP END MASTER
120!$OMP BARRIER
121
[1130]122   firstvar=trim((nom))
[38]123   call inistats(ierr)
[1532]124   if (klon_glo>1) then ! general case, 3D GCM
125     allocate(mean3d(nbp_lon+1,nbp_lat,nbp_lev))
126     allocate(sd3d(nbp_lon+1,nbp_lat,nbp_lev))
127     allocate(dx3(nbp_lon+1,nbp_lat,nbp_lev))
128     allocate(mean2d(nbp_lon+1,nbp_lat))
129     allocate(sd2d(nbp_lon+1,nbp_lat))
130     allocate(dx2(nbp_lon+1,nbp_lat))
131   else ! 1D model
132     allocate(mean3d(1,1,nbp_lev))
133     allocate(sd3d(1,1,nbp_lev))
134     allocate(dx3(1,1,nbp_lev))
135     allocate(mean2d(1,1))
136     allocate(sd2d(1,1))
137     allocate(dx2(1,1))
138   endif
[2563]139endif ! of if (firstcall)
[38]140
[1130]141if (firstvar==nom) then ! If we're back to the first variable, increment time counter
[38]142      step = step + 1
143endif
144
145if (mod(step,istats).ne.0) then
[1130]146  ! if its not time to write to file, exit
[38]147   RETURN
148endif
149
[2563]150! Exit if there is a stats.def file and the variable is not in the list
151if (stats_def) then
152  getout=.true.
153  do n=1,n_name_def
154    ! look for the variable's name in the list
155    if (trim(name_def(n)).eq.nom) then
156      getout=.false.
157      ! found it, no need to scan the rest of the list exit loop
158      exit
159    endif
160  enddo
161  if (getout) then
162    ! variable not in the list so exit routine now
163    return
164  endif
165endif ! of if (stats_def)
166
[1130]167! collect fields on a global physics grid
168#ifdef CPP_PARA
169 if (dim.eq.3) then
[1528]170  px3(1:ngrid,1:nbp_lev)=px(1:ngrid,1:nbp_lev)
[1130]171  ! Gather fieds on a "global" (without redundant longitude) array
172  call Gather(px3,px3_glop)
173!$OMP MASTER
174  if (is_mpi_root) then
175    call Grid1Dto2D_glo(px3_glop,px3_glo)
[2997]176    if (klon_glo>1) then ! general case (unless in 1D)
[1130]177    ! copy dx3_glo() to dx3(:) and add redundant longitude
[1528]178    dx3(1:nbp_lon,:,:)=px3_glo(1:nbp_lon,:,:)
179    dx3(nbp_lon+1,:,:)=dx3(1,:,:)
[2997]180    endif
[1130]181  endif
182!$OMP END MASTER
183!$OMP BARRIER
184 else ! dim.eq.2
185  ! Gather fieds on a "global" (without redundant longitude) array
186  px2(:)=px(:,1)
187  call Gather(px2,px2_glop)
188!$OMP MASTER
[2997]189  if (is_mpi_root) then
190    call Grid1Dto2D_glo(px2_glop,px2_glo)
191    if (klon_glo>1) then ! general case (unless in 1D)
192      ! copy px2_glo() to dx2(:) and add redundant longitude
193      dx2(1:nbp_lon,:)=px2_glo(1:nbp_lon,:)
194      dx2(nbp_lon+1,:)=dx2(1,:)
195    endif
196  endif
[1130]197!$OMP END MASTER
198!$OMP BARRIER
199 endif
200#else
201  if (dim.eq.3) then
[1528]202    px3_glop(:,1:nbp_lev)=px(:,1:nbp_lev)
[1130]203!  Passage variable physique -->  variable dynamique
[1528]204    DO l=1,nbp_lev
205      DO i=1,nbp_lon
[1130]206         px3_glo(i,1,l)=px(1,l)
[1528]207         px3_glo(i,nbp_lat,l)=px(ngrid,l)
[1130]208      ENDDO
[1528]209      DO j=2,nbp_lat-1
210         ig0= 1+(j-2)*nbp_lon
211         DO i=1,nbp_lon
[1130]212            px3_glo(i,j,l)=px(ig0+i,l)
213         ENDDO
214      ENDDO
215    ENDDO
216  else ! dim.eq.2
217    px2_glop(:)=px(:,1)
218!    Passage variable physique -->  physique dynamique
[1528]219   DO i=1,nbp_lon
[1130]220     px2_glo(i,1)=px(1,1)
[1528]221     px2_glo(i,nbp_lat)=px(ngrid,1)
[1130]222   ENDDO
[1528]223   DO j=2,nbp_lat-1
224     ig0= 1+(j-2)*nbp_lon
225     DO i=1,nbp_lon
[1130]226        px2_glo(i,j)=px(ig0+i,1)
227     ENDDO
228   ENDDO
229  endif
230#endif
231
232! 2. Write field to file
233
234if (is_master) then
235! only master needs do this
236
[38]237ierr = NF_OPEN("stats.nc",NF_WRITE,nid)
238
239namebis=trim(nom)
[1130]240
241! test: check if that variable already exists in file
[38]242ierr= NF_INQ_VARID(nid,namebis,meanid)
243
244if (ierr.ne.NF_NOERR) then
[1130]245  ! variable not in file, create/define it
[38]246   if (firstvar==nom) then
[1130]247      indx=1
248      count(:)=0
[38]249   endif
250
251
252!declaration de la variable
253
254! choix du nom des coordonnees
255   ierr= NF_INQ_DIMID(nid,"longitude",id(1))
256   ierr= NF_INQ_DIMID(nid,"latitude",id(2))
257   if (dim.eq.3) then
258      ierr= NF_INQ_DIMID(nid,"altitude",id(3))
259      ierr= NF_INQ_DIMID(nid,"Time",id(4))
260      nbdim=4
261   else if (dim==2) then
262      ierr= NF_INQ_DIMID(nid,"Time",id(3))
263      nbdim=3
264   endif
265
266   write (*,*) "====================="
[2311]267   write (*,*) "STATS: creating ",nom
[38]268   namebis=trim(nom)
[1560]269   call def_var_stats(nid,namebis,titre,unite,nbdim,id,meanid,ierr)
[1130]270   if (dim.eq.3) then
271     call inivar(nid,meanid,size(px3_glop,1),dim,indx,px3_glop,ierr)
272   else ! dim.eq.2
273     call inivar(nid,meanid,size(px2_glop,1),dim,indx,px2_glop,ierr)
274   endif
[38]275   namebis=trim(nom)//"_sd"
[1560]276   call def_var_stats(nid,namebis,trim(titre)//" total standard deviation over the season",unite,nbdim,id,sdid,ierr)
[1130]277   if (dim.eq.3) then
278     call inivar(nid,sdid,size(px3_glop,1),dim,indx,px3_glop,ierr)
279   else ! dim.eq.2
280     call inivar(nid,sdid,size(px2_glop,1),dim,indx,px2_glop,ierr)
281   endif
[38]282
283   ierr= NF_CLOSE(nid)
284   return
285
286else
[1130]287   ! variable found in file
[38]288   namebis=trim(nom)//"_sd"
289   ierr= NF_INQ_VARID(nid,namebis,sdid)
290
291endif
292
293if (firstvar==nom) then
[1130]294   count(indx)=count(int(indx))+1
295   indx=indx+1
296   if (indx>istime) then
297      indx=1
[38]298   endif
299endif
300
[1130]301if (count(indx)==0) then
302   ! very first time we write the variable to file
[38]303   if (dim.eq.3) then
[1130]304      start=(/1,1,1,indx/)
[1532]305      if (klon_glo>1) then !general case
306        sizes=(/nbp_lon+1,nbp_lat,nbp_lev,1/)
307      else
308        sizes=(/1,1,nbp_lev,1/)
309      endif
[1130]310      mean3d(:,:,:)=0
311      sd3d(:,:,:)=0
[38]312   else if (dim.eq.2) then
[1130]313      start=(/1,1,indx,0/)
[1532]314      if (klon_glo>1) then !general case
[1689]315        sizes=(/nbp_lon+1,nbp_lat,1,0/)
[1532]316      else
317        sizes=(/1,1,1,0/)
318      endif
[1130]319      mean2d(:,:)=0
320      sd2d(:,:)=0
[38]321   endif
322else
[1130]323   ! load values from file
[38]324   if (dim.eq.3) then
[1130]325      start=(/1,1,1,indx/)
[1532]326      if (klon_glo>1) then !general case
327        sizes=(/nbp_lon+1,nbp_lat,nbp_lev,1/)
328      else ! 1D model case
329        sizes=(/1,1,nbp_lev,1/)
330      endif
[38]331#ifdef NC_DOUBLE
[1130]332      ierr = NF_GET_VARA_DOUBLE(nid,meanid,start,sizes,mean3d)
333      ierr = NF_GET_VARA_DOUBLE(nid,sdid,start,sizes,sd3d)
[38]334#else
[1130]335      ierr = NF_GET_VARA_REAL(nid,meanid,start,sizes,mean3d)
336      ierr = NF_GET_VARA_REAL(nid,sdid,start,sizes,sd3d)
[38]337#endif
338      if (ierr.ne.NF_NOERR) then
[1532]339         write (*,*) "wstats error reading :",trim(nom)
[38]340         write (*,*) NF_STRERROR(ierr)
[2311]341         call abort_physic("wstats","Failed reading "//trim(nom),1)
[38]342      endif
343
344   else if (dim.eq.2) then
[1130]345      start=(/1,1,indx,0/)
[1532]346      if (klon_glo>1) then ! general case
347        sizes=(/nbp_lon+1,nbp_lat,1,0/)
348      else
349        sizes=(/1,1,1,0/)
350      endif
[38]351#ifdef NC_DOUBLE
[1130]352      ierr = NF_GET_VARA_DOUBLE(nid,meanid,start,sizes,mean2d)
353      ierr = NF_GET_VARA_DOUBLE(nid,sdid,start,sizes,sd2d)
[38]354#else
[1130]355      ierr = NF_GET_VARA_REAL(nid,meanid,start,sizes,mean2d)
356      ierr = NF_GET_VARA_REAL(nid,sdid,start,sizes,sd2d)
[38]357#endif
358      if (ierr.ne.NF_NOERR) then
[1532]359         write (*,*) "wstats error reading :",trim(nom)
[38]360         write (*,*) NF_STRERROR(ierr)
[2311]361         call abort_physic("wstats","Failed reading "//trim(nom),1)
[38]362      endif
363   endif
[1130]364endif ! of if (count(indx)==0)
[38]365
[1130]366
367! 2.1. Build dx* (data on lon-lat grid, with redundant longitude)
368
[38]369if (dim.eq.3) then
[1528]370  dx3(1:nbp_lon,:,:)=px3_glo(:,:,:)
[1532]371  IF (klon_glo>1) THEN ! in 3D, add redundant longitude point
372    dx3(nbp_lon+1,:,:)=dx3(1,:,:)
373  ENDIF
[1130]374else ! dim.eq.2
[1528]375  dx2(1:nbp_lon,:)=px2_glo(:,:)
[1532]376  IF (klon_glo>1) THEN ! in 3D, add redundant longitude point
377    dx2(nbp_lon+1,:)=dx2(1,:)
378  ENDIF
[1130]379endif
[38]380
381
[1130]382! 2.2. Add current values to previously stored sums
[38]383
[1130]384if (dim.eq.3) then
[38]385
[1130]386   mean3d(:,:,:)=mean3d(:,:,:)+dx3(:,:,:)
387   sd3d(:,:,:)=sd3d(:,:,:)+dx3(:,:,:)**2
388
[38]389#ifdef NC_DOUBLE
[1130]390   ierr = NF_PUT_VARA_DOUBLE(nid,meanid,start,sizes,mean3d)
391   ierr = NF_PUT_VARA_DOUBLE(nid,sdid,start,sizes,sd3d)
[38]392#else
[1130]393   ierr = NF_PUT_VARA_REAL(nid,meanid,start,sizes,mean3d)
394   ierr = NF_PUT_VARA_REAL(nid,sdid,start,sizes,sd3d)
[38]395#endif
[1532]396  if (ierr.ne.NF_NOERR) then
397     write (*,*) "wstats error writing :",trim(nom)
398     write (*,*) NF_STRERROR(ierr)
[2311]399     call abort_physic("wstats","Failed writing "//trim(nom),1)
[1532]400  endif
[38]401
402else if (dim.eq.2) then
403
404   mean2d(:,:)= mean2d(:,:)+dx2(:,:)
[1130]405   sd2d(:,:)=sd2d(:,:)+dx2(:,:)**2
[38]406
407#ifdef NC_DOUBLE
[1130]408   ierr = NF_PUT_VARA_DOUBLE(nid,meanid,start,sizes,mean2d)
409   ierr = NF_PUT_VARA_DOUBLE(nid,sdid,start,sizes,sd2d)
[38]410#else
[1130]411   ierr = NF_PUT_VARA_REAL(nid,meanid,start,sizes,mean2d)
412   ierr = NF_PUT_VARA_REAL(nid,sdid,start,sizes,sd2d)
[38]413#endif
[1532]414  if (ierr.ne.NF_NOERR) then
415     write (*,*) "wstats error writing :",trim(nom)
416     write(*,*) "start:",start
417     write(*,*) "sizes:",sizes
418     write(*,*) "mean2d:",mean2d
419     write(*,*) "sd2d:",sd2d
420     write (*,*) NF_STRERROR(ierr)
[2311]421     call abort_physic("wstats","Failed writing "//trim(nom),1)
[1532]422  endif
[38]423
[1130]424endif ! of if (dim.eq.3) elseif (dim.eq.2)
[38]425
[1130]426  ierr= NF_CLOSE(nid)
427endif ! of if (is_master)
[38]428
429end subroutine wstats
430
[2559]431!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
432
433subroutine inistats(ierr)
434
435! routine to initialize the stats file (i.e. create file, write
436! time independent coordinates, etc.)
437
438use mod_phys_lmdz_para, only : is_master
439USE vertical_layers_mod, ONLY: ap,bp,aps,bps,preff,pseudoalt,presnivs
440USE nrtype, ONLY: pi
441USE time_phylmdz_mod, ONLY: daysec,dtphys
442USE regular_lonlat_mod, ONLY: lon_reg, lat_reg
443USE mod_grid_phy_lmdz, ONLY: nbp_lon, nbp_lat, nbp_lev
444implicit none
445
446include "netcdf.inc"
447
448integer,intent(out) :: ierr
449
450integer :: nid
451integer :: l,nsteppd
452real, dimension(nbp_lev) ::  sig_s
453real,allocatable :: lon_reg_ext(:) ! extended longitudes
454integer :: idim_lat,idim_lon,idim_llm,idim_llmp1,idim_time
455real, dimension(istime) :: lt
456integer :: nvarid
457
458
459IF (nbp_lon*nbp_lat==1) THEN
460  ! 1D model
461  ALLOCATE(lon_reg_ext(1))
462ELSE
463  ! 3D model
464  ALLOCATE(lon_reg_ext(nbp_lon+1))
465ENDIF
466
467write (*,*)
468write (*,*) '                        || STATS ||'
469write (*,*)
470write (*,*) 'daysec',daysec
471write (*,*) 'dtphys',dtphys
472nsteppd=nint(daysec/dtphys)
473write (*,*) 'nsteppd=',nsteppd
474
475if (abs(float(nsteppd)-daysec/dtphys).gt.1.e-8*daysec) then
476  call abort_physic("inistats",'1 sol .ne. n physics steps',1)
477endif
478
479if(mod(nsteppd,istime).ne.0) then
480  call abort_physic("inistats",'1 sol .ne. n*istime physics steps',1)
481endif
482
483istats=nsteppd/istime
484write (*,*) 'istats=',istats
485write (*,*) 'Storing ',istime,'times per day'
486write (*,*) 'thus every ',istats,'physical timestep '
487write (*,*)
488
489do l= 1, nbp_lev
490  sig_s(l)=((ap(l)+ap(l+1))/preff+bp(l)+bp(l+1))/2.
491  pseudoalt(l)=-10.*log(presnivs(l)/preff)   
492enddo
493
494lon_reg_ext(1:nbp_lon)=lon_reg(1:nbp_lon)
495IF (nbp_lon*nbp_lat/=1) THEN
496  ! In 3D, add extra redundant point (180 degrees,
497  ! since lon_reg starts at -180)
498  lon_reg_ext(nbp_lon+1)=-lon_reg_ext(1)
499ENDIF
500
501if (is_master) then
502  ! only the master needs do this
503  ierr = NF_CREATE("stats.nc",IOR(NF_CLOBBER,NF_64BIT_OFFSET),nid)
504  if (ierr.ne.NF_NOERR) then
505    write (*,*) NF_STRERROR(ierr)
506    call abort_physic("inistats",'failed creating stats.nc',1)
507  endif
508
509  ierr = NF_DEF_DIM (nid, "latitude", nbp_lat, idim_lat)
510  IF (nbp_lon*nbp_lat==1) THEN
511    ierr = NF_DEF_DIM (nid, "longitude", 1, idim_lon)
512  ELSE
513    ierr = NF_DEF_DIM (nid, "longitude", nbp_lon+1, idim_lon)
514  ENDIF
515  ierr = NF_DEF_DIM (nid, "altitude", nbp_lev, idim_llm)
516  ierr = NF_DEF_DIM (nid, "llmp1", nbp_lev+1, idim_llmp1)
517  ierr = NF_DEF_DIM (nid, "Time", NF_UNLIMITED, idim_time)
518
519  ierr = NF_ENDDEF(nid)
520
521  call def_var_stats(nid,"Time","Time", &
522                     "days since 0000-00-0 00:00:00",1, &
523                     [idim_time],nvarid,ierr)
524  ! Time is initialised later by mkstats subroutine
525
526  call def_var_stats(nid,"latitude","latitude", &
527                     "degrees_north",1,[idim_lat],nvarid,ierr)
528#ifdef NC_DOUBLE
529  ierr = NF_PUT_VAR_DOUBLE (nid,nvarid,lat_reg/pi*180)
530#else
531  ierr = NF_PUT_VAR_REAL (nid,nvarid,lat_reg/pi*180)
532#endif
533
534  call def_var_stats(nid,"longitude","East longitude", &
535                     "degrees_east",1,[idim_lon],nvarid,ierr)
536#ifdef NC_DOUBLE
537  ierr = NF_PUT_VAR_DOUBLE (nid,nvarid,lon_reg_ext/pi*180)
538#else
539  ierr = NF_PUT_VAR_REAL (nid,nvarid,lon_reg_ext/pi*180)
540#endif
541
542  ! Niveaux verticaux, aps et bps
543  ierr = NF_REDEF (nid)
544#ifdef NC_DOUBLE
[2573]545  ierr = NF_DEF_VAR (nid,"altitude", NF_DOUBLE, 1,[idim_llm],nvarid)
[2559]546#else
[2573]547  ierr = NF_DEF_VAR (nid,"altitude", NF_FLOAT, 1,[idim_llm],nvarid)
[2559]548#endif
549  ierr = NF_PUT_ATT_TEXT (nid,nvarid,"long_name",8,"altitude")
550  ierr = NF_PUT_ATT_TEXT (nid,nvarid,'units',2,"km")
551  ierr = NF_PUT_ATT_TEXT (nid,nvarid,'positive',2,"up")
552  ierr = NF_ENDDEF(nid)
553#ifdef NC_DOUBLE
554  ierr = NF_PUT_VAR_DOUBLE (nid,nvarid,pseudoalt)
555#else
556  ierr = NF_PUT_VAR_REAL (nid,nvarid,pseudoalt)
557#endif
558  call def_var_stats(nid,"aps","hybrid pressure at midlayers", &
559                     " ",1,[idim_llm],nvarid,ierr)
560#ifdef NC_DOUBLE
561  ierr = NF_PUT_VAR_DOUBLE (nid,nvarid,aps)
562#else
563  ierr = NF_PUT_VAR_REAL (nid,nvarid,aps)
564#endif
565
566  call def_var_stats(nid,"bps","hybrid sigma at midlayers", &
567                     " ",1,[idim_llm],nvarid,ierr)
568#ifdef NC_DOUBLE
569  ierr = NF_PUT_VAR_DOUBLE (nid,nvarid,bps)
570#else
571  ierr = NF_PUT_VAR_REAL (nid,nvarid,bps)
572#endif
573
574  ierr=NF_CLOSE(nid)
575
576endif ! of if (is_master)
577
578end subroutine inistats
579
580!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
581
[1130]582subroutine inivar(nid,varid,ngrid,dim,indx,px,ierr)
[2559]583
584! routine to initialize writing a variable in the stats file
585
[1532]586use mod_grid_phy_lmdz, only : nbp_lon, nbp_lat, nbp_lev, klon_glo
[38]587
588implicit none
589
590include "netcdf.inc"
591
[1130]592integer, intent(in) :: nid,varid,dim,indx,ngrid
[1528]593real, dimension(ngrid,nbp_lev), intent(in) :: px
[38]594integer, intent(out) :: ierr
595
596integer :: l,i,j,ig0
[1130]597integer, dimension(4) :: start,sizes
[1528]598real, dimension(nbp_lon+1,nbp_lat,nbp_lev) :: dx3
599real, dimension(nbp_lon+1,nbp_lat) :: dx2
[1532]600real :: dx3_1d(nbp_lev) ! for 1D outputs
601real :: dx2_1d ! for 1D outputs
[38]602
603if (dim.eq.3) then
604
[1130]605   start=(/1,1,1,indx/)
[1532]606   if (klon_glo>1) then ! general 3D case
607     sizes=(/nbp_lon+1,nbp_lat,nbp_lev,1/)
608   else
609     sizes=(/1,1,nbp_lev,1/)
610   endif
[38]611
612!  Passage variable physique -->  variable dynamique
613
[1532]614   if (klon_glo>1) then ! general case
615    DO l=1,nbp_lev
[1528]616      DO i=1,nbp_lon+1
[38]617         dx3(i,1,l)=px(1,l)
[1528]618         dx3(i,nbp_lat,l)=px(ngrid,l)
[38]619      ENDDO
[1528]620      DO j=2,nbp_lat-1
621         ig0= 1+(j-2)*nbp_lon
622         DO i=1,nbp_lon
[38]623            dx3(i,j,l)=px(ig0+i,l)
624         ENDDO
[1528]625         dx3(nbp_lon+1,j,l)=dx3(1,j,l)
[38]626      ENDDO
[1532]627    ENDDO
628   else ! 1D model case
629     dx3_1d(1:nbp_lev)=px(1,1:nbp_lev)
630   endif
[38]631
632#ifdef NC_DOUBLE
[1532]633   if (klon_glo>1) then
634     ierr = NF_PUT_VARA_DOUBLE(nid,varid,start,sizes,dx3)
635   else
636     ierr = NF_PUT_VARA_DOUBLE(nid,varid,start,sizes,dx3_1d)
637   endif
[38]638#else
[1532]639   if (klon_glo>1) then
640     ierr = NF_PUT_VARA_REAL(nid,varid,start,sizes,dx3)
641   else
642     ierr = NF_PUT_VARA_REAL(nid,varid,start,sizes,dx3_1d)
643   endif
[38]644#endif
[1532]645  if (ierr.ne.NF_NOERR) then
646     write (*,*) "inivar error writing variable"
647     write (*,*) NF_STRERROR(ierr)
[2311]648     call abort_physic("inivar","error writing variable",1)
[1532]649  endif
[38]650
651else if (dim.eq.2) then
652
[1130]653      start=(/1,1,indx,0/)
[1532]654      if (klon_glo>1) then ! general 3D case
655        sizes=(/nbp_lon+1,nbp_lat,1,0/)
656      else
657        sizes=(/1,1,1,0/)
658      endif
[38]659
660!    Passage variable physique -->  physique dynamique
661
[1532]662  if (klon_glo>1) then ! general case
[1528]663  DO i=1,nbp_lon+1
[38]664     dx2(i,1)=px(1,1)
[1528]665     dx2(i,nbp_lat)=px(ngrid,1)
[38]666  ENDDO
[1528]667  DO j=2,nbp_lat-1
668     ig0= 1+(j-2)*nbp_lon
669     DO i=1,nbp_lon
[38]670        dx2(i,j)=px(ig0+i,1)
671     ENDDO
[1528]672     dx2(nbp_lon+1,j)=dx2(1,j)
[38]673  ENDDO
[1532]674  else ! 1D model case
675    dx2_1d=px(1,1)
676  endif
677 
[38]678#ifdef NC_DOUBLE
[1532]679   if (klon_glo>1) then
680     ierr = NF_PUT_VARA_DOUBLE(nid,varid,start,sizes,dx2)
681   else
682     ierr = NF_PUT_VARA_DOUBLE(nid,varid,start,sizes,dx2_1d)
683   endif
[38]684#else
[1532]685   if (klon_glo>1) then
686     ierr = NF_PUT_VARA_REAL(nid,varid,start,sizes,dx2)
687   else
688     ierr = NF_PUT_VARA_REAL(nid,varid,start,sizes,dx2_1d)
689   endif
[38]690#endif
[1532]691  if (ierr.ne.NF_NOERR) then
692     write (*,*) "inivar error writing variable"
693     write (*,*) NF_STRERROR(ierr)
[2311]694     call abort_physic("inivar","error writing variable",1)
[1532]695  endif
[38]696
697endif
698
699end subroutine inivar
700
701!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
702
703subroutine def_var_stats(nid,name,title,units,nbdim,dimids,nvarid,ierr)
704
705! This subroutine defines variable 'name' in a (pre-existing and opened)
706! NetCDF file (known from its NetCDF ID 'nid').
707! The number of dimensions 'nbdim' of the variable, as well as the IDs of
708! corresponding dimensions must be set (in array 'dimids').
709! Upon successfull definition of the variable, 'nvarid' contains the
710! NetCDF ID of the variable.
711! The variables' attributes 'title' (Note that 'long_name' would be more
712! appropriate) and 'units' are also set.
713
714implicit none
715
[1528]716include "netcdf.inc"
[38]717
718integer,intent(in) :: nid ! NetCDF file ID
719character(len=*),intent(in) :: name ! the variable's name
720character(len=*),intent(in) :: title ! 'title' attribute of variable
721character(len=*),intent(in) :: units ! 'units' attribute of variable
722integer,intent(in) :: nbdim ! number of dimensions of the variable
723integer,dimension(nbdim),intent(in) :: dimids ! NetCDF IDs of the dimensions
724                                              ! the variable is defined along
725integer,intent(out) :: nvarid ! NetCDF ID of the variable
726integer,intent(out) :: ierr ! returned NetCDF staus code
727
728! 1. Switch to NetCDF define mode
729ierr=NF_REDEF(nid)
730
731! 2. Define the variable
732#ifdef NC_DOUBLE
733ierr = NF_DEF_VAR (nid,adjustl(name),NF_DOUBLE,nbdim,dimids,nvarid)
734#else
735ierr = NF_DEF_VAR (nid,adjustl(name),NF_FLOAT,nbdim,dimids,nvarid)
736#endif
737if(ierr/=NF_NOERR) then
738   write(*,*) "def_var_stats: Failed defining variable "//trim(name)
739   write(*,*) NF_STRERROR(ierr)
[2311]740   call abort_physic("def_var_stats","Failed defining "//trim(name),1)
[38]741endif
742
743! 3. Write attributes
744ierr=NF_PUT_ATT_TEXT(nid,nvarid,"title",&
745                     len_trim(adjustl(title)),adjustl(title))
746if(ierr/=NF_NOERR) then
747   write(*,*) "def_var_stats: Failed writing title attribute for "//trim(name)
748   write(*,*) NF_STRERROR(ierr)
[2311]749   call abort_physic("def_var_stats","Failed writing title for "//trim(name),1)
[38]750endif
751
752ierr=NF_PUT_ATT_TEXT(nid,nvarid,"units",&
753                     len_trim(adjustl(units)),adjustl(units))
754if(ierr/=NF_NOERR) then
755   write(*,*) "def_var_stats: Failed writing units attribute for "//trim(name)
756   write(*,*) NF_STRERROR(ierr)
[2311]757   call abort_physic("def_var_stats","Failed writing units for "//trim(name),1)
[38]758endif
759
760! 4. Switch out of NetCDF define mode
761ierr = NF_ENDDEF(nid)
762
763end subroutine def_var_stats
764
[2559]765!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
766
767subroutine mkstats(ierr)
768
769!  This routine finalizes tha stats.nc file from sums and sums of squares
770!  to means and standard deviations. The data file is overwritten in place.
771
772use mod_phys_lmdz_para, only : is_master
773use mod_grid_phy_lmdz, only : nbp_lon, nbp_lat, nbp_lev, klon_glo
774
775implicit none
776
777include "netcdf.inc"
778
779integer,intent(out) :: ierr ! netCDF return error code
780integer :: nid,nbvar,i,ndims,lt,nvarid
781integer, dimension(4) :: id,varid,start,size
782integer, dimension(5) :: dimids
783character (len=50) :: name,nameout,units,title
784real,allocatable :: sum3d(:,:,:),square3d(:,:,:),mean3d(:,:,:),sd3d(:,:,:)
785real,allocatable :: sum2d(:,:),square2d(:,:),mean2d(:,:),sd2d(:,:)
786real, dimension(istime) :: time
787real, dimension(nbp_lat) :: lat
788real,allocatable :: lon(:)
789real, dimension(nbp_lev) :: alt
790logical :: lcopy=.true.
791!integer :: latid,lonid,altid,timeid
792integer :: meanid,sdid
793!integer, dimension(4) :: dimout
794
795if (is_master) then
796! only the master needs do all this
797
798! Incrementation of count for the last step, which is not done in wstats
799count(istime)=count(istime)+1
800
801if (klon_glo>1) then
802  allocate(lon(nbp_lon+1))
803  allocate(sum3d(nbp_lon+1,nbp_lat,nbp_lev))
804  allocate(square3d(nbp_lon+1,nbp_lat,nbp_lev))
805  allocate(mean3d(nbp_lon+1,nbp_lat,nbp_lev))
806  allocate(sd3d(nbp_lon+1,nbp_lat,nbp_lev))
807  allocate(sum2d(nbp_lon+1,nbp_lat))
808  allocate(square2d(nbp_lon+1,nbp_lat))
809  allocate(mean2d(nbp_lon+1,nbp_lat))
810  allocate(sd2d(nbp_lon+1,nbp_lat))
811else ! 1D model case
812  allocate(lon(1))
813  allocate(sum3d(1,1,nbp_lev))
814  allocate(square3d(1,1,nbp_lev))
815  allocate(mean3d(1,1,nbp_lev))
816  allocate(sd3d(1,1,nbp_lev))
817  allocate(sum2d(1,1))
818  allocate(square2d(1,1))
819  allocate(mean2d(1,1))
820  allocate(sd2d(1,1))
821endif
822
823ierr = NF_OPEN("stats.nc",NF_WRITE,nid)
824
825! We catch the id of dimensions of the stats file
826
827ierr= NF_INQ_DIMID(nid,"latitude",id(1))
828ierr= NF_INQ_DIMID(nid,"longitude",id(2))
829ierr= NF_INQ_DIMID(nid,"altitude",id(3))
830ierr= NF_INQ_DIMID(nid,"Time",id(4))
831
832ierr= NF_INQ_VARID(nid,"latitude",varid(1))
833ierr= NF_INQ_VARID(nid,"longitude",varid(2))
834ierr= NF_INQ_VARID(nid,"altitude",varid(3))
835ierr= NF_INQ_VARID(nid,"Time",varid(4))
836
837! Time initialisation
838
839do i=1,istime
840   time(i)=i*24./istime
841#ifdef NC_DOUBLE
[2573]842   ierr= NF_PUT_VARA_DOUBLE(nid,varid(4),[i],[1],time(i))
[2559]843#else
[2573]844   ierr= NF_PUT_VARA_REAL(nid,varid(4),[i],[1],time(i))
[2559]845#endif
846enddo
847
848! We catche the values of the variables
849
850#ifdef NC_DOUBLE
851         ierr = NF_GET_VAR_DOUBLE(nid,varid(1),lat)
852         ierr = NF_GET_VAR_DOUBLE(nid,varid(2),lon)
853         ierr = NF_GET_VAR_DOUBLE(nid,varid(3),alt)
854#else
855         ierr = NF_GET_VAR_REAL(nid,varid(1),lat)
856         ierr = NF_GET_VAR_REAL(nid,varid(2),lon)
857         ierr = NF_GET_VAR_REAL(nid,varid(3),alt)
858#endif
859
860! We catch the number of variables in the stats file
861ierr = NF_INQ_NVARS(nid,nbvar)
862
863! to catche the "real" number of variables (without the "additionnal variables")
864nbvar=(nbvar-4)/2
865
866do i=1,nbvar
[2573]867   nvarid=(i-1)*2+5
[2559]868
869   ! What's the variable's name?
[2573]870   ierr=NF_INQ_VARNAME(nid,nvarid,name)
[2559]871   write(*,*) "OK variable ",name
872   ! Its units?
873   units=" "
[2573]874   ierr=NF_GET_ATT_TEXT(nid,nvarid,"units",units)
[2559]875   ! Its title?
876   title=" "
[2573]877   ierr=NF_GET_ATT_TEXT(nid,nvarid,"title",title)
[2559]878   ! Its number of dimensions?   
[2573]879   ierr=NF_INQ_VARNDIMS(nid,nvarid,ndims)
[2559]880   ! Its values?
881
882   if(ndims==4) then ! lat, lon, alt & time
883
884!      dimout(1)=lonid
885!      dimout(2)=latid
886!      dimout(3)=altid
887!      dimout(4)=timeid
888
889      if (klon_glo>1) then ! general case
890        size=(/nbp_lon+1,nbp_lat,nbp_lev,1/)
891      else ! 1D model
892        size=(/1,1,nbp_lev,1/)
893      endif
894      do lt=1,istime
895         start=(/1,1,1,lt/)
896         ! Extraction of the "source" variables
897#ifdef NC_DOUBLE
[2573]898         ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,size,sum3d)
899         ierr = NF_GET_VARA_DOUBLE(nid,nvarid+1,start,size,square3d)
[2559]900#else
[2573]901         ierr = NF_GET_VARA_REAL(nid,nvarid,start,size,sum3d)
902         ierr = NF_GET_VARA_REAL(nid,nvarid+1,start,size,square3d)
[2559]903#endif
[2573]904         ! Calculation of these nvariables
[2559]905         mean3d=sum3d/count(lt)
906         sd3d=sqrt(max(0.,square3d/count(lt)-mean3d**2))
907         ! Writing of the variables
908#ifdef NC_DOUBLE
[2573]909         ierr = NF_PUT_VARA_DOUBLE(nid,nvarid,start,size,mean3d)
910         ierr = NF_PUT_VARA_DOUBLE(nid,nvarid+1,start,size,sd3d)
[2559]911#else
[2573]912         ierr = NF_PUT_VARA_REAL(nid,nvarid,start,size,mean3d)
913         ierr = NF_PUT_VARA_REAL(nid,nvarid+1,start,size,sd3d)
[2559]914#endif
915      enddo
916
917    else if (ndims.eq.3) then
918
919!      dimout(1)=lonid
920!      dimout(2)=latid
921!      dimout(3)=timeid
922
923      if (klon_glo>1) then ! general case
924        size=(/nbp_lon+1,nbp_lat,1,0/)
925      else
926        size=(/1,1,1,0/)
927      endif
928      do lt=1,istime
929         start=(/1,1,lt,0/)
930         ! Extraction of the "source" variables
931#ifdef NC_DOUBLE
[2573]932         ierr = NF_GET_VARA_DOUBLE(nid,nvarid,start,size,sum2d)
933         ierr = NF_GET_VARA_DOUBLE(nid,nvarid+1,start,size,square2d)
[2559]934#else
[2573]935         ierr = NF_GET_VARA_REAL(nid,nvarid,start,size,sum2d)
936         ierr = NF_GET_VARA_REAL(nid,nvarid+1,start,size,square2d)
[2559]937#endif
938         ! Calculation of these variables
939         mean2d=sum2d/count(lt)
940         sd2d=sqrt(max(0.,square2d/count(lt)-mean2d**2))
941         ! Writing of the variables
942#ifdef NC_DOUBLE
[2573]943         ierr = NF_PUT_VARA_DOUBLE(nid,nvarid,start,size,mean2d)
944         ierr = NF_PUT_VARA_DOUBLE(nid,nvarid+1,start,size,sd2d)
[2559]945#else
[2573]946         ierr = NF_PUT_VARA_REAL(nid,nvarid,start,size,mean2d)
947         ierr = NF_PUT_VARA_REAL(nid,nvarid+1,start,size,sd2d)
[2559]948#endif
949      enddo
950
951    endif
952enddo
953
954ierr= NF_CLOSE(nid)
955
956endif ! of if (is_master)
957
958end subroutine mkstats
959
960!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
961
962end module wstats_mod
Note: See TracBrowser for help on using the repository browser.