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

Last change on this file since 1422 was 1422, checked in by milmd, 10 years ago

In GENERIC, MARS and COMMON models replace some include files by modules (usefull for decoupling physics with dynamics).

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