source: trunk/LMDZ.PLUTO/libf/phypluto/writediagsoil.F90 @ 3506

Last change on this file since 3506 was 3506, checked in by afalco, 2 weeks ago

Pluto: import write_output function from Mars.
xios specific outputs.
AF

File size: 12.1 KB
RevLine 
[3506]1module writediagsoil_mod
2
3implicit none
4
5contains
6
[3184]7subroutine writediagsoil(ngrid,name,title,units,dimpx,px)
8
9! Write variable 'name' to NetCDF file 'diagsoil.nc'.
10! The variable may be 3D (lon,lat,depth) subterranean field,
11! a 2D (lon,lat) surface field, or a simple scalar (0D variable).
12!
13! Calls to 'writediagsoil' can originate from anywhere in the program;
14! An initialisation of variable 'name' is done if it is the first time
15! that this routine is called with given 'name'; otherwise data is appended
16! (yielding the sought time series of the variable)
17
18! Modifs: Aug.2010 Ehouarn: enforce outputs to be real*4
19
20use comsoil_h, only: nsoilmx, inertiedat
21use geometry_mod, only: cell_area
22use time_phylmdz_mod, only: ecritphy, day_step, iphysiq
23use mod_phys_lmdz_para, only : is_mpi_root, is_master, gather
24use mod_grid_phy_lmdz, only : klon_glo, Grid1Dto2D_glo, &
25                              nbp_lon, nbp_lat
26
27implicit none
28
29include"netcdf.inc"
30
31! Arguments:
32integer,intent(in) :: ngrid ! number of (horizontal) points of physics grid
33! i.e. ngrid = 2+(jjm-1)*iim - 1/jjm
34character(len=*),intent(in) :: name ! 'name' of the variable
35character(len=*),intent(in) :: title ! 'long_name' attribute of the variable
36character(len=*),intent(in) :: units ! 'units' attribute of the variable
37integer,intent(in) :: dimpx ! dimension of the variable (3,2 or 0)
38real,dimension(ngrid,nsoilmx),intent(in) :: px ! variable
39
40! Local variables:
41real*4,dimension(nbp_lon+1,nbp_lat,nsoilmx) :: data3 ! to store 3D data
42real*4,dimension(nbp_lon+1,nbp_lat) :: data2 ! to store 2D data
43real*4 :: data0 ! to store 0D data
44real*4 :: data3_1d(1,nsoilmx) ! to store a profile in 1D model
45real*4 :: data2_1d ! to store surface value with 1D model
46integer :: i,j,l ! for loops
47integer :: ig0
48
49real*4,save :: date ! time counter (in elapsed days)
50
51real :: inertia((nbp_lon+1),nbp_lat,nsoilmx)
52real :: area((nbp_lon+1),nbp_lat)
53
54real :: inertiafi_glo(klon_glo,nsoilmx)
55real :: areafi_glo(klon_glo)
56
57integer,save :: isample ! sample rate at which data is to be written to output
58integer,save :: ntime=0 ! counter to internally store time steps
59character(len=20),save :: firstname="1234567890"
60integer,save :: zitau=0
61!$OMP THREADPRIVATE(date,isample,ntime,firstname,zitau)
62
63character(len=30) :: filename="diagsoil.nc"
64
65! NetCDF stuff:
66integer :: nid ! NetCDF output file ID
67integer :: varid ! NetCDF ID of a variable
68integer :: ierr ! NetCDF routines return code
69integer,dimension(4) :: id ! NetCDF IDs of the dimensions of the variable
70integer,dimension(4) :: edges,corners
71
72#ifdef CPP_PARA
73! Added to work in parallel mode
74real dx3_glop(klon_glo,nsoilmx)
75real dx3_glo(nbp_lon,nbp_lat,nsoilmx) ! to store a global 3D data set
76real dx2_glop(klon_glo)
77real dx2_glo(nbp_lon,nbp_lat)     ! to store a global 2D (surface) data set
78real px2(ngrid)
79#endif
80
81! 1. Initialization step
82if (firstname.eq."1234567890") then
83  ! Store 'name' as 'firstname'
84  firstname=name
85  ! From now on, if 'name'.eq.'firstname', then it is a new time cycle
86
87  ! just to be sure, check that firstnom is large enough to hold nom
88  if (len_trim(firstname).lt.len_trim(name)) then
89    write(*,*) "writediagsoil: Error !!!"
90    write(*,*) "   firstname string not long enough!!"
91    write(*,*) "   increase its size to at least ",len_trim(name)
92    stop
93  endif
[3506]94
[3184]95  ! Set output sample rate
96  isample=int(ecritphy) ! same as for diagfi outputs
97  ! Note ecritphy is known from control.h
[3506]98
[3184]99  ! Create output NetCDF file
100  if (is_master) then
101   ierr=NF_CREATE(filename,NF_CLOBBER,nid)
102   if (ierr.ne.NF_NOERR) then
103    write(*,*)'writediagsoil: Error, failed creating file '//trim(filename)
104    stop
105   endif
106
107#ifdef CPP_PARA
108   ! Gather inertiedat() soil thermal inertia on physics grid
109   call Gather(inertiedat,inertiafi_glo)
110   ! Gather cell_area() mesh area on physics grid
111   call Gather(cell_area,areafi_glo)
112#else
113         inertiafi_glo(:,:)=inertiedat(:,:)
114         areafi_glo(:)=cell_area(:)
115#endif
116
117   ! build inertia() and area()
118   if (klon_glo>1) then
119    do i=1,nbp_lon+1 ! poles
120     inertia(i,1,1:nsoilmx)=inertiafi_glo(1,1:nsoilmx)
121     inertia(i,nbp_lat,1:nsoilmx)=inertiafi_glo(klon_glo,1:nsoilmx)
122     ! for area, divide at the poles by nbp_lon
123     area(i,1)=areafi_glo(1)/nbp_lon
124     area(i,nbp_lat)=areafi_glo(klon_glo)/nbp_lon
125    enddo
126    do j=2,nbp_lat-1
127     ig0= 1+(j-2)*nbp_lon
128     do i=1,nbp_lon
129        inertia(i,j,1:nsoilmx)=inertiafi_glo(ig0+i,1:nsoilmx)
130        area(i,j)=areafi_glo(ig0+i)
131     enddo
132     ! handle redundant point in longitude
133     inertia(nbp_lon+1,j,1:nsoilmx)=inertia(1,j,1:nsoilmx)
134     area(nbp_lon+1,j)=area(1,j)
135    enddo
136   endif
[3506]137
[3184]138   ! write "header" of file (longitudes, latitudes, geopotential, ...)
139   if (klon_glo>1) then ! general 3D case
140     call iniwritesoil(nid,ngrid,inertia,area,nbp_lon+1,nbp_lat)
141   else ! 1D model
142     call iniwritesoil(nid,ngrid,inertiafi_glo(1,:),areafi_glo(1),1,1)
143   endif
144
145  endif ! of if (is_master)
[3506]146
[3184]147  ! set zitau to -1 to be compatible with zitau incrementation step below
148  zitau=-1
[3506]149
[3184]150else
151  ! If not an initialization call, simply open the NetCDF file
152  if (is_master) then
153   ierr=NF_OPEN(filename,NF_WRITE,nid)
154  endif
155endif ! of if (firstname.eq."1234567890")
156
157! 2. Increment local time counter, if necessary
158if (name.eq.firstname) then
159  ! if we run across 'firstname', then it is a new time step
160  zitau=zitau+iphysiq
161  ! Note iphysiq is known from control.h
162endif
163
164! 3. Write data, if the time index matches the sample rate
165if (mod(zitau+1,isample).eq.0) then
166
167! 3.1 If first call at this date, update 'time' variable
168  if (name.eq.firstname) then
169    ntime=ntime+1
170    date=float(zitau+1)/float(day_step)
171    ! Note: day_step is known from control.h
[3506]172
[3184]173    if (is_master) then
174     ! Get NetCDF ID for "time"
175     ierr=NF_INQ_VARID(nid,"time",varid)
176     ! Add the current value of date to the "time" array
177!#ifdef NC_DOUBLE
178!     ierr=NF_PUT_VARA_DOUBLE(nid,varid,ntime,1,date)
179!#else
180     ierr=NF_PUT_VARA_REAL(nid,varid,ntime,1,date)
181!#endif
182     if (ierr.ne.NF_NOERR) then
183      write(*,*)"writediagsoil: Failed writing date to time variable"
[3506]184      stop
[3184]185     endif
186    endif ! of if (is_master)
187  endif ! of if (name.eq.firstname)
188
189! 3.2 Write the variable to the NetCDF file
190if (dimpx.eq.3) then ! Case of a 3D variable
191  ! A. Recast data along 'dynamics' grid
192#ifdef CPP_PARA
193  ! gather field on a "global" (without redundant longitude) array
194  call Gather(px,dx3_glop)
195!$OMP MASTER
196  if (is_mpi_root) then
197    call Grid1Dto2D_glo(dx3_glop,dx3_glo)
198    ! copy dx3_glo() to dx3(:) and add redundant longitude
199    data3(1:nbp_lon,:,:)=dx3_glo(1:nbp_lon,:,:)
200    data3(nbp_lon+1,:,:)=data3(1,:,:)
201  endif
202!$OMP END MASTER
203!$OMP BARRIER
204#else
205  if (klon_glo>1) then ! General case
206   do l=1,nsoilmx
207    ! handle the poles
208    do i=1,nbp_lon+1
209      data3(i,1,l)=px(1,l)
210      data3(i,nbp_lat,l)=px(ngrid,l)
211    enddo
212    ! rest of the grid
213    do j=2,nbp_lat-1
214      ig0=1+(j-2)*nbp_lon
215      do i=1,nbp_lon
216        data3(i,j,l)=px(ig0+i,l)
217      enddo
218      data3(nbp_lon+1,j,l)=data3(1,j,l) ! extra (modulo) longitude
219    enddo
220   enddo
221  else ! 1D model case
222   data3_1d(1,1:nsoilmx)=px(1,1:nsoilmx)
223  endif
224#endif
[3506]225
[3184]226  ! B. Write (append) the variable to the NetCDF file
227  if (is_master) then
228  ! B.1. Get the ID of the variable
229  ierr=NF_INQ_VARID(nid,name,varid)
230  if (ierr.ne.NF_NOERR) then
231    ! If we failed geting the variable's ID, we assume it is because
232    ! the variable doesn't exist yet and must be created.
233    ! Start by obtaining corresponding dimensions IDs
234    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
235    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
236    ierr=NF_INQ_DIMID(nid,"depth",id(3))
237    ierr=NF_INQ_DIMID(nid,"time",id(4))
238    ! Tell the world about it
239    write(*,*) "====================="
240    write(*,*) "writediagsoil: creating variable "//trim(name)
241    call def_var(nid,name,title,units,4,id,varid,ierr)
242  endif ! of if (ierr.ne.NF_NOERR)
[3506]243
[3184]244  ! B.2. Prepare things to be able to write/append the variable
245  corners(1)=1
246  corners(2)=1
247  corners(3)=1
248  corners(4)=ntime
[3506]249
[3184]250  if (klon_glo==1) then
251    edges(1)=1
252  else
253    edges(1)=nbp_lon+1
254  endif
255  edges(2)=nbp_lat
256  edges(3)=nsoilmx
257  edges(4)=1
[3506]258
[3184]259  ! B.3. Write the slab of data
260!#ifdef NC_DOUBLE
261!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data3)
262!#else
263  if (klon_glo>1) then
264    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data3)
265  else
266    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data3_1d)
267  endif
268!#endif
269  if (ierr.ne.NF_NOERR) then
270    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
271               " to file "//trim(filename)//" at time",date
272  endif
273  endif ! of if (is_master)
274
275elseif (dimpx.eq.2) then ! Case of a 2D variable
276
277  ! A. Recast data along 'dynamics' grid
278#ifdef CPP_PARA
279  ! gather field on a "global" (without redundant longitude) array
280  px2(:)=px(:,1)
281  call Gather(px2,dx2_glop)
282!$OMP MASTER
283  if (is_mpi_root) then
284    call Grid1Dto2D_glo(dx2_glop,dx2_glo)
285    ! copy dx3_glo() to dx3(:) and add redundant longitude
286    data2(1:nbp_lon,:)=dx2_glo(1:nbp_lon,:)
287    data2(nbp_lon+1,:)=data2(1,:)
288  endif
289!$OMP END MASTER
290!$OMP BARRIER
291#else
292  if (klon_glo>1) then ! general case
293    ! handle the poles
294    do i=1,nbp_lon+1
295      data2(i,1)=px(1,1)
296      data2(i,nbp_lat)=px(ngrid,1)
297    enddo
298    ! rest of the grid
299    do j=2,nbp_lat-1
300      ig0=1+(j-2)*nbp_lon
301      do i=1,nbp_lon
302        data2(i,j)=px(ig0+i,1)
303      enddo
304      data2(nbp_lon+1,j)=data2(1,j) ! extra (modulo) longitude
305    enddo
306  else ! 1D model case
307    data2_1d=px(1,1)
308  endif
309#endif
310
311  ! B. Write (append) the variable to the NetCDF file
312  if (is_master) then
313  ! B.1. Get the ID of the variable
314  ierr=NF_INQ_VARID(nid,name,varid)
315  if (ierr.ne.NF_NOERR) then
316    ! If we failed geting the variable's ID, we assume it is because
317    ! the variable doesn't exist yet and must be created.
318    ! Start by obtaining corresponding dimensions IDs
319    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
320    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
321    ierr=NF_INQ_DIMID(nid,"time",id(3))
322    ! Tell the world about it
323    write(*,*) "====================="
324    write(*,*) "writediagsoil: creating variable "//trim(name)
325    call def_var(nid,name,title,units,3,id,varid,ierr)
326  endif ! of if (ierr.ne.NF_NOERR)
327
328  ! B.2. Prepare things to be able to write/append the variable
329  corners(1)=1
330  corners(2)=1
331  corners(3)=ntime
[3506]332
[3184]333  if (klon_glo==1) then
334    edges(1)=1
335  else
336    edges(1)=nbp_lon+1
337  endif
338  edges(2)=nbp_lat
339  edges(3)=1
[3506]340
[3184]341  ! B.3. Write the slab of data
342!#ifdef NC_DOUBLE
343!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data2)
344!#else
345  if (klon_glo>1) then ! General case
346    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data2)
347  else
348    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data2_1d)
349  endif
350!#endif
351  if (ierr.ne.NF_NOERR) then
352    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
353               " to file "//trim(filename)//" at time",date
354  endif
355  endif ! of if (is_master)
356
357elseif (dimpx.eq.0) then ! Case of a 0D variable
358#ifdef CPP_PARA
359  write(*,*) "writediagsoil: dimps==0 case not implemented in // mode!!"
360  stop
361#endif
362  ! A. Copy data value
363  data0=px(1,1)
364
365  ! B. Write (append) the variable to the NetCDF file
366  ! B.1. Get the ID of the variable
367  ierr=NF_INQ_VARID(nid,name,varid)
368  if (ierr.ne.NF_NOERR) then
369    ! If we failed geting the variable's ID, we assume it is because
370    ! the variable doesn't exist yet and must be created.
371    ! Start by obtaining corresponding dimensions IDs
372    ierr=NF_INQ_DIMID(nid,"time",id(1))
373    ! Tell the world about it
374    write(*,*) "====================="
375    write(*,*) "writediagsoil: creating variable "//trim(name)
376    call def_var(nid,name,title,units,1,id,varid,ierr)
377  endif ! of if (ierr.ne.NF_NOERR)
378
379  ! B.2. Prepare things to be able to write/append the variable
380  corners(1)=ntime
[3506]381
[3184]382  edges(1)=1
383
384  ! B.3. Write the data
385!#ifdef NC_DOUBLE
386!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data0)
387!#else
388  ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data0)
389!#endif
390  if (ierr.ne.NF_NOERR) then
391    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
392               " to file "//trim(filename)//" at time",date
393  endif
394
395endif ! of if (dimpx.eq.3) elseif (dimpx.eq.2) ...
396endif ! of if (mod(zitau+1,isample).eq.0)
397
398! 4. Close the NetCDF file
399if (is_master) then
400  ierr=NF_CLOSE(nid)
401endif
402
403end subroutine writediagsoil
[3506]404
405end module writediagsoil_mod
Note: See TracBrowser for help on using the repository browser.