source: trunk/LMDZ.MARS/libf/dyn3d/writediagdyn.F90 @ 937

Last change on this file since 937 was 410, checked in by acolaitis, 13 years ago

Modified NCDF norm of our files from classic to 64bit offset to support variables indices of more than integer*4 maximum length. This is a priori retrocompatible with classic format. I have tested it, it works for all file outputs, newstart (on classic or 64-bit offset files). One can check the format of his .nc with ncdump -k file.nc

File size: 16.0 KB
Line 
1subroutine writediagdyn(name,title,units,dimpx,px)
2
3! Write variable 'name' to NetCDF file 'diagdyn.nc'.
4! The variable may be 3D (iip1,jjp1,llm) dynamical field,
5! a 2D (iip1,jjp1) surface field, or a simple scalar (0D variable).
6!
7! Calls to 'writediagdyn' can originate from anywhere in the program;
8! An initialisation of variable 'name' is done if it is the first time
9! that this routine is called with given 'name'; otherwise data is appended
10! (yielding the sought time series of the variable)
11!
12! NB: the rate a which outputs are made can be changed (see parameter isample)
13!
14implicit none
15
16#include"dimensions.h"
17#include"paramet.h"
18#include"control.h"
19#include"netcdf.inc"
20
21! Arguments:
22character(len=*),intent(in) :: name ! 'name' of the variable
23character(len=*),intent(in) :: title ! 'long_name' attribute of the variable
24character(len=*),intent(in) :: units ! 'units' attribute of the variable
25integer,intent(in) :: dimpx ! dimension of the variable (3,2 or 0)
26real,dimension(iip1,jjp1,llm),intent(in) :: px ! variable
27! Note: px might actually be dimensio(iip1,jjp1,1); no problem
28
29! Local variables:
30!real,dimension(iip1,jjp1,llm) :: data3 ! to store 3D data
31! Note iip1,jjp1 known from paramet.h; nsoilmx known from dimphys.h
32!real,dimension(iip1,jjp1) :: data2 ! to store 2D data
33!real :: data0 ! to store 0D data
34integer :: i,j,l ! for loops
35integer :: ig0
36
37real,save :: date ! time counter (in elapsed days)
38! sample rate at which data is to be written to output
39!integer,parameter :: isample=1
40integer,save :: isample ! initialized during Initialization step
41integer,save :: ntime=0 ! counter to internally store time steps
42character(len=20),save :: firstname="1234567890"
43integer,save :: zitau=0
44
45character(len=30) :: filename="diagdyn.nc"
46
47! NetCDF stuff:
48integer :: nid ! NetCDF output file ID
49integer :: varid ! NetCDF ID of a variable
50integer :: ierr ! NetCDF routines return code
51integer,dimension(4) :: id ! NetCDF IDs of the dimensions of the variable
52integer,dimension(4) :: edges,corners
53
54! 1. Initialization step
55if (firstname.eq."1234567890") then
56  ! Initialize isample
57  !isample=1
58  isample=iphysiq
59 
60  ! Store 'name' as 'firstname'
61  firstname=name
62  ! From now on, if 'name'.eq.'firstname', then it is a new time cycle
63 
64  ! Create output NetCDF file
65  ierr=NF_CREATE(filename,IOR(NF_CLOBBER,NF_64BIT_OFFSET),nid)
66  if (ierr.ne.NF_NOERR) then
67    write(*,*)'writediagdyn: Error, failed creating file '//trim(filename)
68    stop
69  endif
70 
71  ! Define dimensions and axis attributes
72  call iniwritediagdyn(nid)
73 
74  ! set zitau to -1 to be compatible with zitau incrementation step below
75  zitau=-1
76 
77else
78  ! If not an initialization call, simply open the NetCDF file
79  ierr=NF_OPEN(filename,NF_WRITE,nid)
80  if (ierr.ne.NF_NOERR) then
81    write(*,*)'writediagdyn: Error, failed opening file '//trim(filename)
82    stop
83  endif
84endif ! of if (firstname.eq."1234567890")
85
86! 2. Increment local time counter, if necessary
87if (name.eq.firstname) then
88  ! if we run across 'firstname', then it is a new dynamical time step
89  zitau=zitau+1
90endif
91
92! 3. Write data, if the time index matches the sample rate
93if (mod(zitau+1,isample).eq.0) then
94
95! 3.1 If first call at this date, update 'time' variable
96  if (name.eq.firstname) then
97    ntime=ntime+1
98    date=float(zitau+1)/float(day_step)
99    ! Note: day_step is known from control.h
100   
101    ! Get NetCDF ID for "time"
102    ierr=NF_INQ_VARID(nid,"time",varid)
103    ! Add the current value of date to the "time" array
104#ifdef NC_DOUBLE
105    ierr=NF_PUT_VARA_DOUBLE(nid,varid,ntime,1,date)
106#else
107    ierr=NF_PUT_VARA_REAL(nid,varid,ntime,1,date)
108#endif
109    if (ierr.ne.NF_NOERR) then
110      write(*,*)"writediagdyn: Failed writing date to time variable"
111      stop
112    endif
113  endif ! of if (name.eq.firstname)
114
115! 3.2 Write the variable to the NetCDF file
116if (dimpx.eq.3) then ! 3.2.1. Case of a 3D variable
117  ! Write (append) the variable to the NetCDF file
118  ! 3.2.1.A. Get the ID of the variable
119  ierr=NF_INQ_VARID(nid,name,varid)
120  if (ierr.ne.NF_NOERR) then
121    ! If we failed geting the variable's ID, we assume it is because
122    ! the variable doesn't exist yet and must be created.
123    ! Start by obtaining corresponding dimensions IDs
124    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
125    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
126    ierr=NF_INQ_DIMID(nid,"altitude",id(3))
127    ierr=NF_INQ_DIMID(nid,"time",id(4))
128    ! Tell the world about it
129    write(*,*) "====================="
130    write(*,*) "writediagdyn: creating variable "//trim(name)
131    call def_var_diagdyn(nid,name,title,units,4,id,varid,ierr)
132  endif ! of if (ierr.ne.NF_NOERR)
133 
134  ! 3.2.1.B. Prepare things to be able to write/append the variable
135  corners(1)=1
136  corners(2)=1
137  corners(3)=1
138  corners(4)=ntime
139 
140  edges(1)=iip1
141  edges(2)=jjp1
142  edges(3)=llm
143  edges(4)=1
144 
145  ! 3.2.1.C. Write the slab of data
146#ifdef NC_DOUBLE
147  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,px)
148#else
149  ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,px)
150#endif
151  if (ierr.ne.NF_NOERR) then
152    write(*,*) "writediagdyn: Error: Failed writing "//trim(name)//&
153               " to file "//trim(filename)//" at time",date
154  endif
155
156elseif (dimpx.eq.2) then ! 3.2.2 Case of a 2D variable
157  ! Write (append) the variable to the NetCDF file
158  ! 3.2.2.A. Get the ID of the variable
159  ierr=NF_INQ_VARID(nid,name,varid)
160  if (ierr.ne.NF_NOERR) then
161    ! If we failed geting the variable's ID, we assume it is because
162    ! the variable doesn't exist yet and must be created.
163    ! Start by obtaining corresponding dimensions IDs
164    ierr=NF_INQ_DIMID(nid,"longitude",id(1))
165    ierr=NF_INQ_DIMID(nid,"latitude",id(2))
166    ierr=NF_INQ_DIMID(nid,"time",id(3))
167    ! Tell the world about it
168    write(*,*) "====================="
169    write(*,*) "writediagdyn: creating variable "//trim(name)
170    call def_var(nid,name,title,units,3,id,varid,ierr)
171  endif ! of if (ierr.ne.NF_NOERR)
172
173  ! 3.2.2.B. Prepare things to be able to write/append the variable
174  corners(1)=1
175  corners(2)=1
176  corners(3)=ntime
177 
178  edges(1)=iip1
179  edges(2)=jjp1
180  edges(3)=1
181 
182  ! 3.2.2.C. Write the slab of data
183#ifdef NC_DOUBLE
184  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,px)
185#else
186  ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,px)
187#endif
188  if (ierr.ne.NF_NOERR) then
189    write(*,*) "writediagdyn: Error: Failed writing "//trim(name)//&
190               " to file "//trim(filename)//" at time",date
191  endif
192
193elseif (dimpx.eq.0) then ! 3.2.3. Case of a 0D variable
194  ! Write (append) the variable to the NetCDF file
195  ! 3.2.3.A. Get the ID of the variable
196  ierr=NF_INQ_VARID(nid,name,varid)
197  if (ierr.ne.NF_NOERR) then
198    ! If we failed geting the variable's ID, we assume it is because
199    ! the variable doesn't exist yet and must be created.
200    ! Start by obtaining corresponding dimensions IDs
201    ierr=NF_INQ_DIMID(nid,"time",id(1))
202    ! Tell the world about it
203    write(*,*) "====================="
204    write(*,*) "writediagdyn: creating variable "//trim(name)
205    call def_var(nid,name,title,units,1,id,varid,ierr)
206  endif ! of if (ierr.ne.NF_NOERR)
207
208  ! B.2. Prepare things to be able to write/append the variable
209  corners(1)=ntime
210 
211  edges(1)=1
212
213  ! B.3. Write the data
214#ifdef NC_DOUBLE
215  ierr=NF_PUT_VARA_DOUBLE(nid,varid,corners,edges,px)
216#else
217  ierr=NF_PUT_VARA_REAL(nid,varid,corners,edges,px)
218#endif
219  if (ierr.ne.NF_NOERR) then
220    write(*,*) "writediagdyn: Error: Failed writing "//trim(name)//&
221               " to file "//trim(filename)//" at time",date
222  endif
223
224endif ! of if (dimpx.eq.3) elseif (dimpx.eq.2) ...
225
226
227endif ! of if (mod(zitau+1,isample).eq.0)
228
229! 4. Close the NetCDF file
230ierr=NF_CLOSE(nid)
231
232end subroutine writediagdyn
233
234!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
235
236subroutine iniwritediagdyn(nid)
237
238! Initialization routine for 'writediagdyn'. Here we create/define
239! dimensions (longitude, latitude, altitude and time) and eventually
240! other fixed (time-independent) parameters.
241
242implicit none
243
244#include"dimensions.h"
245#include"paramet.h"
246#include"comgeom.h"
247#include"comconst.h"
248#include"comvert.h"
249#include"netcdf.inc"
250
251! Arguments:
252integer,intent(in) :: nid ! NetCDF output file ID
253
254! Local variables:
255
256! NetCDF stuff:
257integer :: ierr ! NetCDF routines return code
258integer :: idim_rlatu ! ID of the 'latitude' dimension
259integer :: idim_rlonv ! ID of the 'longitude' dimension
260integer :: idim_alt ! ID of the 'altitude' dimension
261integer :: idim_time  ! ID of the 'time' dimension
262integer :: varid ! to store NetCDF ID of a variable
263integer,dimension(2) :: dimids ! to store IDs of dimensions of a variable
264character(len=60) :: text ! to store some text
265
266
267! 1. Define the dimensions
268! Switch to NetCDF define mode
269ierr=NF_REDEF(nid)
270
271! Define the dimensions
272ierr=NF_DEF_DIM(nid,"longitude",iip1,idim_rlonv)
273! iip1 known from paramet.h
274if (ierr.ne.NF_NOERR) then
275  write(*,*)"iniwritediagdyn: Error, could not define longitude dimension"
276endif
277ierr=NF_DEF_DIM(nid,"latitude",jjp1,idim_rlatu)
278! jjp1 known from paramet.h
279if (ierr.ne.NF_NOERR) then
280  write(*,*)"iniwritediagdyn: Error, could not define latitude dimension"
281endif
282ierr=NF_DEF_DIM(nid,"altitude",llm,idim_alt)
283! llm known from dimensions.h
284if (ierr.ne.NF_NOERR) then
285  write(*,*)"iniwritediagdyn: Error, could not define depth dimension"
286endif
287ierr=NF_DEF_DIM(nid,"time",NF_UNLIMITED,idim_time)
288if (ierr.ne.NF_NOERR) then
289  write(*,*)"iniwritediagdyn: Error, could not define time dimension"
290endif
291
292! Switch out of NetCDF define mode
293ierr=NF_ENDDEF(nid)
294
295! 2. Define (as variables) and write dimensions, as well as their attributes
296! 2.1. Longitude
297ierr=NF_REDEF(nid) ! switch to NetCDF define mode
298
299! Define the variable
300#ifdef NC_DOUBLE
301ierr=NF_DEF_VAR(nid,"longitude",NF_DOUBLE,1,idim_rlonv,varid)
302#else
303ierr=NF_DEF_VAR(nid,"longitude",NF_FLOAT,1,idim_rlonv,varid)
304#endif
305if (ierr.ne.NF_NOERR) then
306  write(*,*)"iniwritediagdyn: Error, could not define longitude variable"
307endif
308
309! Longitude attributes
310text="East longitude"
311ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
312text="degrees_east"
313ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
314
315! Write longitude to file
316ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
317! Write
318#ifdef NC_DOUBLE
319ierr=NF_PUT_VAR_DOUBLE(nid,varid,rlonv*(180./pi))
320#else
321ierr=NF_PUT_VAR_REAL(nid,varid,rlonv*(180./pi))
322#endif
323! Note: rlonv is known from comgeom.h and pi from comconst.h
324if (ierr.ne.NF_NOERR) then
325  write(*,*)"iniwritediagdyn: Error, could not write longitude variable"
326endif
327
328! 2.2. Latitude
329ierr=NF_REDEF(nid) ! switch to NetCDF define mode
330
331! Define the variable
332#ifdef NC_DOUBLE
333ierr=NF_DEF_VAR(nid,"latitude",NF_DOUBLE,1,idim_rlatu,varid)
334#else
335ierr=NF_DEF_VAR(nid,"latitude",NF_FLOAT,1,idim_rlatu,varid)
336#endif
337if (ierr.ne.NF_NOERR) then
338  write(*,*)"iniwritediagdyn: Error, could not define latitude variable"
339endif
340
341! Latitude attributes
342text="North latitude"
343ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
344text="degrees_north"
345ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
346
347! Write latitude to file
348ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
349! Write
350#ifdef NC_DOUBLE
351ierr=NF_PUT_VAR_DOUBLE(nid,varid,rlatu*(180./pi))
352#else
353ierr=NF_PUT_VAR_REAL(nid,varid,rlatu*(180./pi))
354#endif
355! Note: rlatu is known from comgeom.h and pi from comconst.h
356if (ierr.ne.NF_NOERR) then
357  write(*,*)"iniwritediagdyn: Error, could not write latitude variable"
358endif
359
360! 2.3. Altitude
361ierr=NF_REDEF(nid) ! switch to NetCDF define mode
362
363! Define the variable
364#ifdef NC_DOUBLE
365ierr=NF_DEF_VAR(nid,"altitude",NF_DOUBLE,1,idim_alt,varid)
366#else
367ierr=NF_DEF_VAR(nid,"altitude",NF_FLOAT,1,idim_alt,varid)
368#endif
369if (ierr.ne.NF_NOERR) then
370  write(*,*)"iniwritediagdyn: Error, could not define altitude variable"
371endif
372
373! Depth attributes
374text="Pseudo-altitude"
375ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
376text="km"
377ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
378text="up"
379ierr=NF_PUT_ATT_TEXT(nid,varid,"positive",len_trim(text),text)
380
381! Write depth to file
382ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
383! Write
384#ifdef NC_DOUBLE
385ierr=NF_PUT_VAR_DOUBLE(nid,varid,pseudoalt)
386#else
387ierr=NF_PUT_VAR_REAL(nid,varid,pseudoalt)
388#endif
389! Note pseudoalt is known from comvert.h
390if (ierr.ne.NF_NOERR) then
391  write(*,*)"iniwritediagdyn: Error, could not write altitude variable"
392endif
393
394! 2.4. Time
395ierr=NF_REDEF(nid) ! switch to NetCDF define mode
396
397! Define the variable
398#ifdef NC_DOUBLE
399ierr=NF_DEF_VAR(nid,"time",NF_DOUBLE,1,idim_time,varid)
400#else
401ierr=NF_DEF_VAR(nid,"time",NF_FLOAT,1,idim_time,varid)
402#endif
403if (ierr.ne.NF_NOERR) then
404  write(*,*)"iniwritediagdyn: Error, could not define time variable"
405endif
406
407! time attributes
408text="Time"
409ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
410text="days since 0000-01-01 00:00:00"
411ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
412
413ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
414! Note no need to write time variable here; it is done in writediagsoil.
415
416! 3. Other variables to be included
417
418! 3.1 mesh area surrounding each horizontal point
419ierr=NF_REDEF(nid) ! switch to NetCDF define mode
420
421! Define the variable
422dimids(1)=idim_rlonv ! ID of the 'longitude' dimension
423dimids(2)=idim_rlatu ! ID of the 'latitude' dimension
424#ifdef NC_DOUBLE
425ierr=NF_DEF_VAR(nid,"area",NF_DOUBLE,2,dimids,varid)
426#else
427ierr=NF_DEF_VAR(nid,"area",NF_FLOAT,2,dimids,varid)
428#endif
429if (ierr.ne.NF_NOERR) then
430  write(*,*)"iniwritediagdyn: Error, could not define area variable"
431endif
432
433! Area attributes
434text="Mesh area"
435ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
436text="m2"
437ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
438
439! Write area to file
440ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
441! Write
442#ifdef NC_DOUBLE
443ierr=NF_PUT_VAR_DOUBLE(nid,varid,aire)
444#else
445ierr=NF_PUT_VAR_REAL(nid,varid,aire)
446#endif
447! Note: aire is known from comgeom.h
448if (ierr.ne.NF_NOERR) then
449  write(*,*)"iniwritediagdyn: Error, could not write area variable"
450endif
451
452end subroutine iniwritediagdyn
453
454!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
455
456subroutine def_var_diagdyn(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! Modifs: Aug2010 Ehouarn: enforce outputs to be real*4
467
468implicit none
469
470#include "netcdf.inc"
471
472integer,intent(in) :: nid ! NetCDF file ID
473character(len=*),intent(in) :: name ! the variable's name
474character(len=*),intent(in) :: title ! 'title' attribute of variable
475character(len=*),intent(in) :: units ! 'units' attribute of variable
476integer,intent(in) :: nbdim ! number of dimensions of the variable
477integer,dimension(nbdim),intent(in) :: dimids ! NetCDF IDs of the dimensions
478                                              ! the variable is defined along
479integer,intent(out) :: nvarid ! NetCDF ID of the variable
480integer,intent(out) :: ierr ! returned NetCDF staus code
481
482! 1. Switch to NetCDF define mode
483ierr=NF_REDEF(nid)
484
485! 2. Define the variable
486#ifdef NC_DOUBLE
487ierr = NF_DEF_VAR (nid,adjustl(name),NF_DOUBLE,nbdim,dimids,nvarid)
488#else
489ierr = NF_DEF_VAR (nid,adjustl(name),NF_FLOAT,nbdim,dimids,nvarid)
490#endif
491if(ierr/=NF_NOERR) then
492   write(*,*) "def_var_diagdyn: Failed defining variable "//trim(name)
493   write(*,*) NF_STRERROR(ierr)
494   stop ""
495endif
496
497! 3. Write attributes
498ierr=NF_PUT_ATT_TEXT(nid,nvarid,"title",&
499                     len_trim(adjustl(title)),adjustl(title))
500if(ierr/=NF_NOERR) then
501   write(*,*) "def_var_diagdyn: Failed writing title attribute for "//trim(name)
502   write(*,*) NF_STRERROR(ierr)
503   stop ""
504endif
505
506ierr=NF_PUT_ATT_TEXT(nid,nvarid,"units",&
507                     len_trim(adjustl(units)),adjustl(units))
508if(ierr/=NF_NOERR) then
509   write(*,*) "def_var_diagdyn: Failed writing units attribute for "//trim(name)
510   write(*,*) NF_STRERROR(ierr)
511   stop ""
512endif
513
514! 4. Switch out of NetCDF define mode
515ierr = NF_ENDDEF(nid)
516
517end subroutine def_var_diagdyn
Note: See TracBrowser for help on using the repository browser.