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

Last change on this file since 2932 was 2616, checked in by romain.vande, 3 years ago

LMDZ_MARS RV : Open_MP;
Put all the "save" variables as "!$OMP THREADPRIVATE" in phymars.
The code can now be tested, see README for more info

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