source: trunk/LMDZ.MARS/libf/phymars/writediagsoil.F90 @ 3906

Last change on this file since 3906 was 3870, checked in by jmauxion, 9 months ago

Mars PCM:
In writediag* routines, the files are now opened and closed only at dump time instead of every physical step (sensible speed up in 1D mainly).
JM

File size: 13.1 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 conf_phys()
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: mlayer, nsoilmx, inertiedat
24use geometry_mod, only: cell_area
25use time_phylmdz_mod, only: steps_per_sol, outputs_per_sol
26use mod_phys_lmdz_para, only: is_mpi_root, is_master, gather
27use mod_grid_phy_lmdz, only: klon_glo, Grid1Dto2D_glo, nbp_lon, nbp_lat
28use mod_grid_phy_lmdz, only: grid_type, unstructured
29use iniwritesoil_mod, only: iniwritesoil
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! additional check: one can only output diagsoil.nc files
89! in lon-lat case (or 1D)
90if (grid_type==unstructured) then
91  write(*,*) "writediagsoil: Error !!!"
92  write(*,*) "diagsoil.nc outputs not possible on unstructured grids!!"
93  call abort_physic("writediagsoil","impossible on unstructured grid",1)
94endif
95
96! 1. Initialization step
97if (firstname.eq."1234567890") then
98  ! Store 'name' as 'firstname'
99  firstname=name
100  ! From now on, if 'name'.eq.'firstname', then it is a new time cycle
101
102  ! just to be sure, check that firstnom is large enough to hold nom
103  if (len_trim(firstname).lt.len_trim(name)) then
104    write(*,*) "writediagsoil: Error !!!"
105    write(*,*) "   firstname string not long enough!!"
106    write(*,*) "   increase its size to at least ",len_trim(name)
107    call abort_physic("writediagsoil","firstname too short",1)
108  endif
109 
110  ! Set output sample rate
111  isample=steps_per_sol/outputs_per_sol ! same as for diagfi outputs
112  ! Note ecritphy is known from control.h
113 
114  ! Create output NetCDF file
115  if (is_master) then
116   ierr=NF_CREATE(filename,NF_CLOBBER,nid)
117   if (ierr.ne.NF_NOERR) then
118    write(*,*)'writediagsoil: Error, failed creating file '//trim(filename)
119    call abort_physic("writediagsoil","failed creating"//trim(filename),1)
120   endif
121  endif
122
123#ifdef CPP_PARA
124   ! Gather inertiedat() soil thermal inertia on physics grid
125   call Gather(inertiedat,inertiafi_glo)
126   ! Gather cell_area() mesh area on physics grid
127   call Gather(cell_area,areafi_glo)
128#else
129         inertiafi_glo(:,:)=inertiedat(:,:)
130         areafi_glo(:)=cell_area(:)
131#endif
132
133  if (is_master) then
134   ! build inertia() and area()
135   if (klon_glo>1) then
136    do i=1,nbp_lon+1 ! poles
137     inertia(i,1,1:nsoilmx)=inertiafi_glo(1,1:nsoilmx)
138     inertia(i,nbp_lat,1:nsoilmx)=inertiafi_glo(klon_glo,1:nsoilmx)
139     ! for area, divide at the poles by nbp_lon
140     area(i,1)=areafi_glo(1)/nbp_lon
141     area(i,nbp_lat)=areafi_glo(klon_glo)/nbp_lon
142    enddo
143    do j=2,nbp_lat-1
144     ig0= 1+(j-2)*nbp_lon
145     do i=1,nbp_lon
146        inertia(i,j,1:nsoilmx)=inertiafi_glo(ig0+i,1:nsoilmx)
147        area(i,j)=areafi_glo(ig0+i)
148     enddo
149     ! handle redundant point in longitude
150     inertia(nbp_lon+1,j,1:nsoilmx)=inertia(1,j,1:nsoilmx)
151     area(nbp_lon+1,j)=area(1,j)
152    enddo
153   endif
154   
155   ! write "header" of file (longitudes, latitudes, geopotential, ...)
156   if (klon_glo>1) then ! general 3D case
157     call iniwritesoil(nid,ngrid,inertia,area,nbp_lon+1,nbp_lat,nsoilmx,mlayer)
158   else ! 1D model
159     call iniwritesoil(nid,ngrid,inertiafi_glo(1,:),areafi_glo(1),1,1,nsoilmx,mlayer)
160   endif
161   
162   ierr= NF_CLOSE(nid) ! Close the NETCDF file once initialized
163
164  endif ! of if (is_master)
165 
166  ! set zitau to -1 to be compatible with zitau incrementation step below
167  zitau=-1
168endif ! of if (firstname.eq."1234567890")
169
170! 2. Increment local time counter, if necessary
171if (name.eq.firstname) then
172  ! if we run across 'firstname', then it is a new time step
173  zitau=zitau+1
174endif
175
176! 3. Write data, if the time index matches the sample rate
177if (mod(zitau+1,isample).eq.0) then
178  if (is_master) then
179    ! only the master is required to do this
180
181    ! Time to write data, open NETCDF file
182    ierr=NF_OPEN(filename,NF_WRITE,nid)
183
184! 3.1 If first call at this date, update 'time' variable
185    if (name.eq.firstname) then
186      ntime=ntime+1
187      date=float(zitau+1)/float(steps_per_sol)
188      ! Get NetCDF ID for "time"
189      ierr=NF_INQ_VARID(nid,"time",varid)
190      ! Add the current value of date to the "time" array
191!#ifdef NC_DOUBLE
192      ! ierr=NF_PUT_VARA_DOUBLE(nid,varid,ntime,1,date)
193!#else
194      ierr=NF_PUT_VARA_REAL(nid,varid,[ntime],[1],[date])
195!#endif
196     if (ierr.ne.NF_NOERR) then
197      write(*,*)"writediagsoil: Failed writing date to time variable"
198      call abort_physic("writediagsoil","failed writing time",1)
199     endif
200    endif ! of if (name.eq.firstname)
201  endif ! of if (is_master)
202
203! 3.2 Write the variable to the NetCDF file
204if (dimpx.eq.3) then ! Case of a 3D variable
205  ! A. Recast data along 'dynamics' grid
206  if (klon_glo>1) then ! General case
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   do l=1,nsoilmx
221    ! handle the poles
222    do i=1,nbp_lon+1
223      data3(i,1,l)=px(1,l)
224      data3(i,nbp_lat,l)=px(ngrid,l)
225    enddo
226    ! rest of the grid
227    do j=2,nbp_lat-1
228      ig0=1+(j-2)*nbp_lon
229      do i=1,nbp_lon
230        data3(i,j,l)=px(ig0+i,l)
231      enddo
232      data3(nbp_lon+1,j,l)=data3(1,j,l) ! extra (modulo) longitude
233    enddo
234   enddo
235#endif
236  else ! 1D model case
237   data3_1d(1,1:nsoilmx)=px(1,1:nsoilmx)
238  endif
239 
240  ! B. Write (append) the variable to the NetCDF file
241  if (is_master) then
242  ! B.1. Get the ID of the variable
243  ierr=NF_INQ_VARID(nid,name,varid)
244  if (ierr.ne.NF_NOERR) then
245    ! If we failed geting the variable's ID, we assume it is because
246    ! the variable doesn't exist yet and must be created.
247    ! Start by obtaining corresponding dimensions IDs
248    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
249    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
250    ierr=NF_INQ_DIMID(nid,"depth",id(3))
251    ierr=NF_INQ_DIMID(nid,"time",id(4))
252    ! Tell the world about it
253    write(*,*) "====================="
254    write(*,*) "writediagsoil: creating variable "//trim(name)
255    call def_var(nid,name,title,units,4,id,varid,ierr)
256  endif ! of if (ierr.ne.NF_NOERR)
257 
258  ! B.2. Prepare things to be able to write/append the variable
259  corners(1)=1
260  corners(2)=1
261  corners(3)=1
262  corners(4)=ntime
263 
264  if (klon_glo==1) then
265    edges(1)=1
266  else
267    edges(1)=nbp_lon+1
268  endif
269  edges(2)=nbp_lat
270  edges(3)=nsoilmx
271  edges(4)=1
272 
273  ! B.3. Write the slab of data
274!#ifdef NC_DOUBLE
275!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data3)
276!#else
277  if (klon_glo>1) then
278    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data3)
279  else
280    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data3_1d)
281  endif
282!#endif
283  if (ierr.ne.NF_NOERR) then
284    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
285               " to file "//trim(filename)//" at time",date
286  endif
287  endif ! of if (is_master)
288
289elseif (dimpx.eq.2) then ! Case of a 2D variable
290
291  ! A. Recast data along 'dynamics' grid
292  if (klon_glo>1) then ! General case
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    ! handle the poles
308    do i=1,nbp_lon+1
309      data2(i,1)=px(1,1)
310      data2(i,nbp_lat)=px(ngrid,1)
311    enddo
312    ! rest of the grid
313    do j=2,nbp_lat-1
314      ig0=1+(j-2)*nbp_lon
315      do i=1,nbp_lon
316        data2(i,j)=px(ig0+i,1)
317      enddo
318      data2(nbp_lon+1,j)=data2(1,j) ! extra (modulo) longitude
319    enddo
320#endif
321  else ! 1D model case
322    data2_1d=px(1,1)
323  endif
324
325  ! B. Write (append) the variable to the NetCDF file
326  if (is_master) then
327  ! B.1. Get the ID of the variable
328  ierr=NF_INQ_VARID(nid,name,varid)
329  if (ierr.ne.NF_NOERR) then
330    ! If we failed geting the variable's ID, we assume it is because
331    ! the variable doesn't exist yet and must be created.
332    ! Start by obtaining corresponding dimensions IDs
333    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
334    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
335    ierr=NF_INQ_DIMID(nid,"time",id(3))
336    ! Tell the world about it
337    write(*,*) "====================="
338    write(*,*) "writediagsoil: creating variable "//trim(name)
339    call def_var(nid,name,title,units,3,id,varid,ierr)
340  endif ! of if (ierr.ne.NF_NOERR)
341
342  ! B.2. Prepare things to be able to write/append the variable
343  corners(1)=1
344  corners(2)=1
345  corners(3)=ntime
346 
347  if (klon_glo==1) then
348    edges(1)=1
349  else
350    edges(1)=nbp_lon+1
351  endif
352  edges(2)=nbp_lat
353  edges(3)=1
354 
355  ! B.3. Write the slab of data
356!#ifdef NC_DOUBLE
357!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data2)
358!#else
359  if (klon_glo>1) then ! General case
360    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,data2)
361  else
362    ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,[data2_1d])
363  endif
364!#endif
365  if (ierr.ne.NF_NOERR) then
366    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
367               " to file "//trim(filename)//" at time",date
368  endif
369  endif ! of if (is_master)
370
371elseif (dimpx.eq.0) then ! Case of a 0D variable
372#ifdef CPP_PARA
373  write(*,*) "writediagsoil: dimps==0 case not implemented in // mode!!"
374  call abort_physic("writediagsoil","dimps==0 not implemented",1)
375#endif
376  ! A. Copy data value
377  data0=px(1,1)
378
379  ! B. Write (append) the variable to the NetCDF file
380  ! B.1. Get the ID of the variable
381  ierr=NF_INQ_VARID(nid,name,varid)
382  if (ierr.ne.NF_NOERR) then
383    ! If we failed geting the variable's ID, we assume it is because
384    ! the variable doesn't exist yet and must be created.
385    ! Start by obtaining corresponding dimensions IDs
386    ierr=NF_INQ_DIMID(nid,"time",id(1))
387    ! Tell the world about it
388    write(*,*) "====================="
389    write(*,*) "writediagsoil: creating variable "//trim(name)
390    call def_var(nid,name,title,units,1,id,varid,ierr)
391  endif ! of if (ierr.ne.NF_NOERR)
392
393  ! B.2. Prepare things to be able to write/append the variable
394  corners(1)=ntime
395 
396  edges(1)=1
397
398  ! B.3. Write the data
399!#ifdef NC_DOUBLE
400!  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,data0)
401!#else
402  ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,[data0])
403!#endif
404  if (ierr.ne.NF_NOERR) then
405    write(*,*) "writediagsoil: Error: Failed writing "//trim(name)//&
406               " to file "//trim(filename)//" at time",date
407  endif
408
409endif ! of if (dimpx.eq.3) elseif (dimpx.eq.2) ...
410
411! 4. Close the NetCDF file
412  if (is_master) then
413    ! Close until next variable to dump or next dump iteration
414    ierr= NF_CLOSE(nid)
415  endif
416
417endif ! of if (mod(zitau+1,isample).eq.0)
418
419end subroutine writediagsoil
420
421end module writediagsoil_mod
Note: See TracBrowser for help on using the repository browser.