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

Last change on this file since 3765 was 3760, checked in by emillour, 7 months ago

Pluto PCM:
Fix issue with parallelism in writediagsoil. And introduce the "diagsoil"
flag to trigger outputing a diagsoil.nc file or not.
EM

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