source: trunk/LMDZ.GENERIC/libf/phystd/wstats.F90 @ 2176

Last change on this file since 2176 was 1690, checked in by emillour, 8 years ago

Generic GCM:
Fixing a big bug (dating from revision 1529) in wstats.
EM
--This line, and those below, will be ignored--

M LMDZ.COMMON/arch/arch-X64_ADA.fcm

File size: 14.1 KB
RevLine 
[135]1subroutine wstats(ngrid,nom,titre,unite,dim,px)
2
[1529]3use statto_mod, only: istats,istime,count
[965]4use mod_phys_lmdz_para, only : is_mpi_root, is_master, gather, klon_mpi_begin
[1529]5use mod_grid_phy_lmdz, only : klon_glo, Grid1Dto2D_glo, &
6                              nbp_lon, nbp_lat, nbp_lev
[135]7implicit none
8
[1529]9include "netcdf.inc"
[135]10
11integer,intent(in) :: ngrid
[965]12character (len=*),intent(in) :: nom,titre,unite
[135]13integer,intent(in) :: dim
[1529]14real,intent(in) :: px(ngrid,nbp_lev)
[1531]15real,allocatable,save :: mean3d(:,:,:),sd3d(:,:,:),dx3(:,:,:)
16real,allocatable,save :: mean2d(:,:),sd2d(:,:),dx2(:,:)
[135]17character (len=50) :: namebis
18character (len=50), save :: firstvar
[1315]19!$OMP THREADPRIVATE(firstvar)
[135]20integer :: ierr,varid,nbdim,nid
21integer :: meanid,sdid
[965]22integer, dimension(4)  :: id,start,sizes
[135]23logical, save :: firstcall=.TRUE.
24integer :: l,i,j,ig0
[965]25integer,save :: indx
[135]26
27integer, save :: step=0
[1315]28!$OMP THREADPRIVATE(firstcall,indx,step)
[135]29
[965]30! Added to work in parallel mode
31#ifdef CPP_PARA
[1529]32real px3_glop(klon_glo,nbp_lev) ! to store a 3D data set on global physics grid
33real px3_glo(nbp_lon,nbp_lat,nbp_lev) ! to store a global 3D data set on global lonxlat grid
[965]34real px2_glop(klon_glo) ! to store a 2D data set on global physics grid
[1529]35real px2_glo(nbp_lon,nbp_lat) ! to store a 2D data set on global lonxlat grid
[965]36real px2(ngrid)
[1529]37real px3(ngrid,nbp_lev)
[965]38#else
39! When not running in parallel mode:
[1529]40real px3_glop(ngrid,nbp_lev) ! to store a 3D data set on global physics grid
41real px3_glo(nbp_lon,nbp_lat,nbp_lev) ! to store a global 3D data set on global lonxlat grid
[965]42real px2_glop(ngrid) ! to store a 2D data set on global physics grid
[1529]43real px2_glo(nbp_lon,nbp_lat) ! to store a 2D data set on global lonxlat grid
[965]44#endif
[135]45
[965]46! 1. Initialization (creation of stats.nc file)
[135]47if (firstcall) then
48   firstcall=.false.
49   firstvar=trim((nom))
50   call inistats(ierr)
[1531]51   if (klon_glo>1) then ! general case, 3D GCM
52     allocate(mean3d(nbp_lon+1,nbp_lat,nbp_lev))
53     allocate(sd3d(nbp_lon+1,nbp_lat,nbp_lev))
54     allocate(dx3(nbp_lon+1,nbp_lat,nbp_lev))
55     allocate(mean2d(nbp_lon+1,nbp_lat))
56     allocate(sd2d(nbp_lon+1,nbp_lat))
57     allocate(dx2(nbp_lon+1,nbp_lat))
58   else ! 1D model
59     allocate(mean3d(1,1,nbp_lev))
60     allocate(sd3d(1,1,nbp_lev))
61     allocate(dx3(1,1,nbp_lev))
62     allocate(mean2d(1,1))
63     allocate(sd2d(1,1))
64     allocate(dx2(1,1))
65   endif
[135]66endif
67
[965]68if (firstvar==nom) then ! If we're back to the first variable, increment time counter
[135]69      step = step + 1
70endif
71
72if (mod(step,istats).ne.0) then
[965]73  ! if its not time to write to file, exit
[135]74   RETURN
75endif
76
[965]77! collect fields on a global physics grid
78#ifdef CPP_PARA
79 if (dim.eq.3) then
[1529]80  px3(1:ngrid,1:nbp_lev)=px(1:ngrid,1:nbp_lev)
[965]81  ! Gather fieds on a "global" (without redundant longitude) array
82  call Gather(px3,px3_glop)
83!$OMP MASTER
84  if (is_mpi_root) then
85    call Grid1Dto2D_glo(px3_glop,px3_glo)
86    ! copy dx3_glo() to dx3(:) and add redundant longitude
[1529]87    dx3(1:nbp_lon,:,:)=px3_glo(1:nbp_lon,:,:)
88    dx3(nbp_lon+1,:,:)=dx3(1,:,:)
[965]89  endif
90!$OMP END MASTER
91!$OMP BARRIER
92 else ! dim.eq.2
93  ! Gather fieds on a "global" (without redundant longitude) array
94  px2(:)=px(:,1)
95  call Gather(px2,px2_glop)
96!$OMP MASTER
97          if (is_mpi_root) then
98            call Grid1Dto2D_glo(px2_glop,px2_glo)
99            ! copy px2_glo() to dx2(:) and add redundant longitude
[1529]100            dx2(1:nbp_lon,:)=px2_glo(1:nbp_lon,:)
101            dx2(nbp_lon+1,:)=dx2(1,:)
[965]102          endif
103!$OMP END MASTER
104!$OMP BARRIER
105 endif
106#else
107  if (dim.eq.3) then
[1529]108    px3_glop(:,1:nbp_lev)=px(:,1:nbp_lev)
[965]109!  Passage variable physique -->  variable dynamique
[1529]110    DO l=1,nbp_lev
111      DO i=1,nbp_lon
[965]112         px3_glo(i,1,l)=px(1,l)
[1529]113         px3_glo(i,nbp_lat,l)=px(ngrid,l)
[965]114      ENDDO
[1529]115      DO j=2,nbp_lat-1
116         ig0= 1+(j-2)*nbp_lon
117         DO i=1,nbp_lon
[965]118            px3_glo(i,j,l)=px(ig0+i,l)
119         ENDDO
120      ENDDO
121    ENDDO
122  else ! dim.eq.2
123    px2_glop(:)=px(:,1)
124!    Passage variable physique -->  physique dynamique
[1529]125   DO i=1,nbp_lon
[965]126     px2_glo(i,1)=px(1,1)
[1529]127     px2_glo(i,nbp_lat)=px(ngrid,1)
[965]128   ENDDO
[1529]129   DO j=2,nbp_lat-1
130     ig0= 1+(j-2)*nbp_lon
131     DO i=1,nbp_lon
[965]132        px2_glo(i,j)=px(ig0+i,1)
133     ENDDO
134   ENDDO
135  endif
136#endif
137
138! 2. Write field to file
139
140if (is_master) then
141! only master needs do this
142
[135]143ierr = NF_OPEN("stats.nc",NF_WRITE,nid)
144
145namebis=trim(nom)
[965]146
147! test: check if that variable already exists in file
[135]148ierr= NF_INQ_VARID(nid,namebis,meanid)
149
150if (ierr.ne.NF_NOERR) then
[965]151  ! variable not in file, create/define it
[135]152   if (firstvar==nom) then
[965]153      indx=1
154      count(:)=0
[135]155   endif
156
157
158!declaration de la variable
159
160! choix du nom des coordonnees
161   ierr= NF_INQ_DIMID(nid,"longitude",id(1))
162   ierr= NF_INQ_DIMID(nid,"latitude",id(2))
163   if (dim.eq.3) then
164      ierr= NF_INQ_DIMID(nid,"altitude",id(3))
165      ierr= NF_INQ_DIMID(nid,"Time",id(4))
166      nbdim=4
167   else if (dim==2) then
168      ierr= NF_INQ_DIMID(nid,"Time",id(3))
169      nbdim=3
170   endif
171
172   write (*,*) "====================="
173   write (*,*) "STATS: creation de ",nom
174   namebis=trim(nom)
[1565]175   call def_var_stats(nid,namebis,titre,unite,nbdim,id,meanid,ierr)
[965]176   if (dim.eq.3) then
177     call inivar(nid,meanid,size(px3_glop,1),dim,indx,px3_glop,ierr)
178   else ! dim.eq.2
179     call inivar(nid,meanid,size(px2_glop,1),dim,indx,px2_glop,ierr)
180   endif
[135]181   namebis=trim(nom)//"_sd"
[1565]182   call def_var_stats(nid,namebis,trim(titre)//" total standard deviation over the season",unite,nbdim,id,sdid,ierr)
[965]183   if (dim.eq.3) then
184     call inivar(nid,sdid,size(px3_glop,1),dim,indx,px3_glop,ierr)
185   else ! dim.eq.2
186     call inivar(nid,sdid,size(px2_glop,1),dim,indx,px2_glop,ierr)
187   endif
[135]188
189   ierr= NF_CLOSE(nid)
190   return
191
192else
[965]193   ! variable found in file
[135]194   namebis=trim(nom)//"_sd"
195   ierr= NF_INQ_VARID(nid,namebis,sdid)
196
197endif
198
199if (firstvar==nom) then
[965]200   count(indx)=count(int(indx))+1
201   indx=indx+1
202   if (indx>istime) then
203      indx=1
[135]204   endif
205endif
206
[965]207if (count(indx)==0) then
208   ! very first time we write the variable to file
[135]209   if (dim.eq.3) then
[965]210      start=(/1,1,1,indx/)
[1531]211      if (klon_glo>1) then !general case
212        sizes=(/nbp_lon+1,nbp_lat,nbp_lev,1/)
213      else
214        sizes=(/1,1,nbp_lev,1/)
215      endif
[965]216      mean3d(:,:,:)=0
217      sd3d(:,:,:)=0
[135]218   else if (dim.eq.2) then
[965]219      start=(/1,1,indx,0/)
[1531]220      if (klon_glo>1) then !general case
[1690]221        sizes=(/nbp_lon+1,nbp_lat,1,0/)
[1531]222      else
223        sizes=(/1,1,1,0/)
224      endif
[965]225      mean2d(:,:)=0
226      sd2d(:,:)=0
[135]227   endif
228else
[965]229   ! load values from file
[135]230   if (dim.eq.3) then
[965]231      start=(/1,1,1,indx/)
[1531]232      if (klon_glo>1) then !general case
233        sizes=(/nbp_lon+1,nbp_lat,nbp_lev,1/)
234      else ! 1D model case
235        sizes=(/1,1,nbp_lev,1/)
236      endif
[135]237#ifdef NC_DOUBLE
[965]238      ierr = NF_GET_VARA_DOUBLE(nid,meanid,start,sizes,mean3d)
239      ierr = NF_GET_VARA_DOUBLE(nid,sdid,start,sizes,sd3d)
[135]240#else
[965]241      ierr = NF_GET_VARA_REAL(nid,meanid,start,sizes,mean3d)
242      ierr = NF_GET_VARA_REAL(nid,sdid,start,sizes,sd3d)
[135]243#endif
244      if (ierr.ne.NF_NOERR) then
[1531]245         write (*,*) "wstats error reading :",trim(nom)
[135]246         write (*,*) NF_STRERROR(ierr)
247         stop ""
248      endif
249
250   else if (dim.eq.2) then
[965]251      start=(/1,1,indx,0/)
[1531]252      if (klon_glo>1) then ! general case
253        sizes=(/nbp_lon+1,nbp_lat,1,0/)
254      else
255        sizes=(/1,1,1,0/)
256      endif
[135]257#ifdef NC_DOUBLE
[965]258      ierr = NF_GET_VARA_DOUBLE(nid,meanid,start,sizes,mean2d)
259      ierr = NF_GET_VARA_DOUBLE(nid,sdid,start,sizes,sd2d)
[135]260#else
[965]261      ierr = NF_GET_VARA_REAL(nid,meanid,start,sizes,mean2d)
262      ierr = NF_GET_VARA_REAL(nid,sdid,start,sizes,sd2d)
[135]263#endif
264      if (ierr.ne.NF_NOERR) then
[1531]265         write (*,*) "wstats error reading :",trim(nom)
[135]266         write (*,*) NF_STRERROR(ierr)
267         stop ""
268      endif
269   endif
[965]270endif ! of if (count(indx)==0)
[135]271
[965]272
273! 2.1. Build dx* (data on lon-lat grid, with redundant longitude)
274
[135]275if (dim.eq.3) then
[1529]276  dx3(1:nbp_lon,:,:)=px3_glo(:,:,:)
[1531]277  IF (klon_glo>1) THEN ! in 3D, add redundant longitude point
278    dx3(nbp_lon+1,:,:)=dx3(1,:,:)
279  ENDIF
[965]280else ! dim.eq.2
[1529]281  dx2(1:nbp_lon,:)=px2_glo(:,:)
[1531]282  IF (klon_glo>1) THEN ! in 3D, add redundant longitude point
283    dx2(nbp_lon+1,:)=dx2(1,:)
284  ENDIF
[965]285endif
[135]286
287
[965]288! 2.2. Add current values to previously stored sums
[135]289
[965]290if (dim.eq.3) then
[135]291
[965]292   mean3d(:,:,:)=mean3d(:,:,:)+dx3(:,:,:)
293   sd3d(:,:,:)=sd3d(:,:,:)+dx3(:,:,:)**2
294
[135]295#ifdef NC_DOUBLE
[965]296   ierr = NF_PUT_VARA_DOUBLE(nid,meanid,start,sizes,mean3d)
297   ierr = NF_PUT_VARA_DOUBLE(nid,sdid,start,sizes,sd3d)
[135]298#else
[965]299   ierr = NF_PUT_VARA_REAL(nid,meanid,start,sizes,mean3d)
300   ierr = NF_PUT_VARA_REAL(nid,sdid,start,sizes,sd3d)
[135]301#endif
[1531]302  if (ierr.ne.NF_NOERR) then
303     write (*,*) "wstats error writing :",trim(nom)
304     write (*,*) NF_STRERROR(ierr)
305     stop ""
306  endif
[135]307
308else if (dim.eq.2) then
309
[965]310   mean2d(:,:)= mean2d(:,:)+dx2(:,:)
311   sd2d(:,:)=sd2d(:,:)+dx2(:,:)**2
[135]312
313#ifdef NC_DOUBLE
[965]314   ierr = NF_PUT_VARA_DOUBLE(nid,meanid,start,sizes,mean2d)
315   ierr = NF_PUT_VARA_DOUBLE(nid,sdid,start,sizes,sd2d)
[135]316#else
[965]317   ierr = NF_PUT_VARA_REAL(nid,meanid,start,sizes,mean2d)
318   ierr = NF_PUT_VARA_REAL(nid,sdid,start,sizes,sd2d)
[135]319#endif
[1531]320  if (ierr.ne.NF_NOERR) then
321     write (*,*) "wstats error writing :",trim(nom)
322     write(*,*) "start:",start
323     write(*,*) "sizes:",sizes
324     write(*,*) "mean2d:",mean2d
325     write(*,*) "sd2d:",sd2d
326     write (*,*) NF_STRERROR(ierr)
327     stop ""
328  endif
[135]329
[965]330endif ! of if (dim.eq.3) elseif (dim.eq.2)
[135]331
[965]332  ierr= NF_CLOSE(nid)
333endif ! of if (is_master)
[135]334
[1216]335end subroutine wstats
[135]336
337!======================================================
[965]338subroutine inivar(nid,varid,ngrid,dim,indx,px,ierr)
[1531]339use mod_grid_phy_lmdz, only : nbp_lon, nbp_lat, nbp_lev, klon_glo
[135]340
341implicit none
342
343include "netcdf.inc"
344
[965]345integer, intent(in) :: nid,varid,dim,indx,ngrid
[1529]346real, dimension(ngrid,nbp_lev), intent(in) :: px
[135]347integer, intent(out) :: ierr
348
349integer :: l,i,j,ig0
[965]350integer, dimension(4) :: start,sizes
[1529]351real, dimension(nbp_lon+1,nbp_lat,nbp_lev) :: dx3
352real, dimension(nbp_lon+1,nbp_lat) :: dx2
[1531]353real :: dx3_1d(nbp_lev) ! for 1D outputs
354real :: dx2_1d ! for 1D outputs
[135]355
356if (dim.eq.3) then
357
[965]358   start=(/1,1,1,indx/)
[1531]359   if (klon_glo>1) then ! general 3D case
360     sizes=(/nbp_lon+1,nbp_lat,nbp_lev,1/)
361   else
362     sizes=(/1,1,nbp_lev,1/)
363   endif
[135]364
365!  Passage variable physique -->  variable dynamique
366
[1531]367   if (klon_glo>1) then ! general case
368    DO l=1,nbp_lev
[1529]369      DO i=1,nbp_lon+1
[135]370         dx3(i,1,l)=px(1,l)
[1529]371         dx3(i,nbp_lat,l)=px(ngrid,l)
[135]372      ENDDO
[1529]373      DO j=2,nbp_lat-1
374         ig0= 1+(j-2)*nbp_lon
375         DO i=1,nbp_lon
[135]376            dx3(i,j,l)=px(ig0+i,l)
377         ENDDO
[1529]378         dx3(nbp_lon+1,j,l)=dx3(1,j,l)
[135]379      ENDDO
[1531]380    ENDDO
381   else ! 1D model case
382     dx3_1d(1:nbp_lev)=px(1,1:nbp_lev)
383   endif
[135]384
385#ifdef NC_DOUBLE
[1531]386   if (klon_glo>1) then
387     ierr = NF_PUT_VARA_DOUBLE(nid,varid,start,sizes,dx3)
388   else
389     ierr = NF_PUT_VARA_DOUBLE(nid,varid,start,sizes,dx3_1d)
390   endif
[135]391#else
[1531]392   if (klon_glo>1) then
393     ierr = NF_PUT_VARA_REAL(nid,varid,start,sizes,dx3)
394   else
395     ierr = NF_PUT_VARA_REAL(nid,varid,start,sizes,dx3_1d)
396   endif
[135]397#endif
[1531]398  if (ierr.ne.NF_NOERR) then
399     write (*,*) "inivar error writing variable"
400     write (*,*) NF_STRERROR(ierr)
401     stop ""
402  endif
[135]403
404else if (dim.eq.2) then
405
[965]406      start=(/1,1,indx,0/)
[1531]407      if (klon_glo>1) then ! general 3D case
408        sizes=(/nbp_lon+1,nbp_lat,1,0/)
409      else
410        sizes=(/1,1,1,0/)
411      endif
[135]412
413!    Passage variable physique -->  physique dynamique
414
[1531]415  if (klon_glo>1) then ! general case
[1529]416  DO i=1,nbp_lon+1
[135]417     dx2(i,1)=px(1,1)
[1529]418     dx2(i,nbp_lat)=px(ngrid,1)
[135]419  ENDDO
[1529]420  DO j=2,nbp_lat-1
421     ig0= 1+(j-2)*nbp_lon
422     DO i=1,nbp_lon
[135]423        dx2(i,j)=px(ig0+i,1)
424     ENDDO
[1529]425     dx2(nbp_lon+1,j)=dx2(1,j)
[135]426  ENDDO
[1531]427  else ! 1D model case
428    dx2_1d=px(1,1)
429  endif
430 
[135]431#ifdef NC_DOUBLE
[1531]432   if (klon_glo>1) then
433     ierr = NF_PUT_VARA_DOUBLE(nid,varid,start,sizes,dx2)
434   else
435     ierr = NF_PUT_VARA_DOUBLE(nid,varid,start,sizes,dx2_1d)
436   endif
[135]437#else
[1531]438   if (klon_glo>1) then
439     ierr = NF_PUT_VARA_REAL(nid,varid,start,sizes,dx2)
440   else
441     ierr = NF_PUT_VARA_REAL(nid,varid,start,sizes,dx2_1d)
442   endif
[135]443#endif
[1531]444  if (ierr.ne.NF_NOERR) then
445     write (*,*) "inivar error writing variable"
446     write (*,*) NF_STRERROR(ierr)
447     stop ""
448  endif
[135]449
450endif
451
[1216]452end subroutine inivar
453
454!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
455
456subroutine def_var_stats(nid,name,title,units,nbdim,dimids,nvarid,ierr)
457
458! This subroutine defines variable 'name' in a (pre-existing and opened)
459! NetCDF file (known from its NetCDF ID 'nid').
460! The number of dimensions 'nbdim' of the variable, as well as the IDs of
461! corresponding dimensions must be set (in array 'dimids').
462! Upon successfull definition of the variable, 'nvarid' contains the
463! NetCDF ID of the variable.
464! The variables' attributes 'title' (Note that 'long_name' would be more
465! appropriate) and 'units' are also set.
466
467implicit none
468
[1529]469include "netcdf.inc"
[1216]470
471integer,intent(in) :: nid ! NetCDF file ID
472character(len=*),intent(in) :: name ! the variable's name
473character(len=*),intent(in) :: title ! 'title' attribute of variable
474character(len=*),intent(in) :: units ! 'units' attribute of variable
475integer,intent(in) :: nbdim ! number of dimensions of the variable
476integer,dimension(nbdim),intent(in) :: dimids ! NetCDF IDs of the dimensions
477                                              ! the variable is defined along
478integer,intent(out) :: nvarid ! NetCDF ID of the variable
479integer,intent(out) :: ierr ! returned NetCDF staus code
480
481! 1. Switch to NetCDF define mode
482ierr=NF_REDEF(nid)
483
484! 2. Define the variable
485#ifdef NC_DOUBLE
486ierr = NF_DEF_VAR (nid,adjustl(name),NF_DOUBLE,nbdim,dimids,nvarid)
487#else
488ierr = NF_DEF_VAR (nid,adjustl(name),NF_FLOAT,nbdim,dimids,nvarid)
489#endif
490if(ierr/=NF_NOERR) then
491   write(*,*) "def_var_stats: Failed defining variable "//trim(name)
492   write(*,*) NF_STRERROR(ierr)
493   stop ""
494endif
495
496! 3. Write attributes
497ierr=NF_PUT_ATT_TEXT(nid,nvarid,"title",&
498                     len_trim(adjustl(title)),adjustl(title))
499if(ierr/=NF_NOERR) then
500   write(*,*) "def_var_stats: Failed writing title attribute for "//trim(name)
501   write(*,*) NF_STRERROR(ierr)
502   stop ""
503endif
504
505ierr=NF_PUT_ATT_TEXT(nid,nvarid,"units",&
506                     len_trim(adjustl(units)),adjustl(units))
507if(ierr/=NF_NOERR) then
508   write(*,*) "def_var_stats: Failed writing units attribute for "//trim(name)
509   write(*,*) NF_STRERROR(ierr)
510   stop ""
511endif
512
513! 4. Switch out of NetCDF define mode
514ierr = NF_ENDDEF(nid)
515
516end subroutine def_var_stats
517
Note: See TracBrowser for help on using the repository browser.