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

Last change on this file since 1403 was 1266, checked in by aslmd, 11 years ago

LMDZ.MARS
IMPORTANT CHANGE

  • Remove all reference/use of nlayermx and dimphys.h
  • Made use of automatic arrays whenever arrays are needed with dimension nlayer
  • Remove lots of obsolete reference to dimensions.h
  • Converted iono.h and param_v4.h into corresponding modules

(with embedded subroutine to allocate arrays)
(no arrays allocated if thermosphere not used)

  • Deleted param.h and put contents into module param_v4_h
  • Adapted testphys1d, newstart, etc...
  • Made DATA arrays in param_read to be initialized by subroutine

fill_data_thermos in module param_v4_h

  • Optimized computations in paramfoto_compact (twice less dlog10 calculations)
  • Checked consistency before/after modification in debug mode
  • Checked performance is not impacted (same as before)
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
243implicit none
244
245#include"dimensions.h"
246#include"paramet.h"
247#include"comgeom.h"
248#include"comconst.h"
249#include"comvert.h"
250#include"netcdf.inc"
251
252! Arguments:
253integer,intent(in) :: nid ! NetCDF output file ID
254
255! Local variables:
256
257! NetCDF stuff:
258integer :: ierr ! NetCDF routines return code
259integer :: idim_rlatu ! ID of the 'latitude' dimension
260integer :: idim_rlonv ! ID of the 'longitude' dimension
261integer :: idim_alt ! ID of the 'altitude' dimension
262integer :: idim_time  ! ID of the 'time' dimension
263integer :: varid ! to store NetCDF ID of a variable
264integer,dimension(2) :: dimids ! to store IDs of dimensions of a variable
265character(len=60) :: text ! to store some text
266
267
268! 1. Define the dimensions
269! Switch to NetCDF define mode
270ierr=NF_REDEF(nid)
271
272! Define the dimensions
273ierr=NF_DEF_DIM(nid,"longitude",iip1,idim_rlonv)
274! iip1 known from paramet.h
275if (ierr.ne.NF_NOERR) then
276  write(*,*)"iniwritediagdyn: Error, could not define longitude dimension"
277endif
278ierr=NF_DEF_DIM(nid,"latitude",jjp1,idim_rlatu)
279! jjp1 known from paramet.h
280if (ierr.ne.NF_NOERR) then
281  write(*,*)"iniwritediagdyn: Error, could not define latitude dimension"
282endif
283ierr=NF_DEF_DIM(nid,"altitude",llm,idim_alt)
284! llm known from dimensions.h
285if (ierr.ne.NF_NOERR) then
286  write(*,*)"iniwritediagdyn: Error, could not define depth dimension"
287endif
288ierr=NF_DEF_DIM(nid,"time",NF_UNLIMITED,idim_time)
289if (ierr.ne.NF_NOERR) then
290  write(*,*)"iniwritediagdyn: Error, could not define time dimension"
291endif
292
293! Switch out of NetCDF define mode
294ierr=NF_ENDDEF(nid)
295
296! 2. Define (as variables) and write dimensions, as well as their attributes
297! 2.1. Longitude
298ierr=NF_REDEF(nid) ! switch to NetCDF define mode
299
300! Define the variable
301#ifdef NC_DOUBLE
302ierr=NF_DEF_VAR(nid,"longitude",NF_DOUBLE,1,idim_rlonv,varid)
303#else
304ierr=NF_DEF_VAR(nid,"longitude",NF_FLOAT,1,idim_rlonv,varid)
305#endif
306if (ierr.ne.NF_NOERR) then
307  write(*,*)"iniwritediagdyn: Error, could not define longitude variable"
308endif
309
310! Longitude attributes
311text="East longitude"
312ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
313text="degrees_east"
314ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
315
316! Write longitude to file
317ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
318! Write
319#ifdef NC_DOUBLE
320ierr=NF_PUT_VAR_DOUBLE(nid,varid,rlonv*(180./pi))
321#else
322ierr=NF_PUT_VAR_REAL(nid,varid,rlonv*(180./pi))
323#endif
324! Note: rlonv is known from comgeom.h and pi from comconst.h
325if (ierr.ne.NF_NOERR) then
326  write(*,*)"iniwritediagdyn: Error, could not write longitude variable"
327endif
328
329! 2.2. Latitude
330ierr=NF_REDEF(nid) ! switch to NetCDF define mode
331
332! Define the variable
333#ifdef NC_DOUBLE
334ierr=NF_DEF_VAR(nid,"latitude",NF_DOUBLE,1,idim_rlatu,varid)
335#else
336ierr=NF_DEF_VAR(nid,"latitude",NF_FLOAT,1,idim_rlatu,varid)
337#endif
338if (ierr.ne.NF_NOERR) then
339  write(*,*)"iniwritediagdyn: Error, could not define latitude variable"
340endif
341
342! Latitude attributes
343text="North latitude"
344ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
345text="degrees_north"
346ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
347
348! Write latitude to file
349ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
350! Write
351#ifdef NC_DOUBLE
352ierr=NF_PUT_VAR_DOUBLE(nid,varid,rlatu*(180./pi))
353#else
354ierr=NF_PUT_VAR_REAL(nid,varid,rlatu*(180./pi))
355#endif
356! Note: rlatu is known from comgeom.h and pi from comconst.h
357if (ierr.ne.NF_NOERR) then
358  write(*,*)"iniwritediagdyn: Error, could not write latitude variable"
359endif
360
361! 2.3. Altitude
362ierr=NF_REDEF(nid) ! switch to NetCDF define mode
363
364! Define the variable
365#ifdef NC_DOUBLE
366ierr=NF_DEF_VAR(nid,"altitude",NF_DOUBLE,1,idim_alt,varid)
367#else
368ierr=NF_DEF_VAR(nid,"altitude",NF_FLOAT,1,idim_alt,varid)
369#endif
370if (ierr.ne.NF_NOERR) then
371  write(*,*)"iniwritediagdyn: Error, could not define altitude variable"
372endif
373
374! Depth attributes
375text="Pseudo-altitude"
376ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
377text="km"
378ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
379text="up"
380ierr=NF_PUT_ATT_TEXT(nid,varid,"positive",len_trim(text),text)
381
382! Write depth to file
383ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
384! Write
385#ifdef NC_DOUBLE
386ierr=NF_PUT_VAR_DOUBLE(nid,varid,pseudoalt)
387#else
388ierr=NF_PUT_VAR_REAL(nid,varid,pseudoalt)
389#endif
390! Note pseudoalt is known from comvert.h
391if (ierr.ne.NF_NOERR) then
392  write(*,*)"iniwritediagdyn: Error, could not write altitude variable"
393endif
394
395! 2.4. Time
396ierr=NF_REDEF(nid) ! switch to NetCDF define mode
397
398! Define the variable
399#ifdef NC_DOUBLE
400ierr=NF_DEF_VAR(nid,"time",NF_DOUBLE,1,idim_time,varid)
401#else
402ierr=NF_DEF_VAR(nid,"time",NF_FLOAT,1,idim_time,varid)
403#endif
404if (ierr.ne.NF_NOERR) then
405  write(*,*)"iniwritediagdyn: Error, could not define time variable"
406endif
407
408! time attributes
409text="Time"
410ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
411text="days since 0000-01-01 00:00:00"
412ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
413
414ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
415! Note no need to write time variable here; it is done in writediagsoil.
416
417! 3. Other variables to be included
418
419! 3.1 mesh area surrounding each horizontal point
420ierr=NF_REDEF(nid) ! switch to NetCDF define mode
421
422! Define the variable
423dimids(1)=idim_rlonv ! ID of the 'longitude' dimension
424dimids(2)=idim_rlatu ! ID of the 'latitude' dimension
425#ifdef NC_DOUBLE
426ierr=NF_DEF_VAR(nid,"area",NF_DOUBLE,2,dimids,varid)
427#else
428ierr=NF_DEF_VAR(nid,"area",NF_FLOAT,2,dimids,varid)
429#endif
430if (ierr.ne.NF_NOERR) then
431  write(*,*)"iniwritediagdyn: Error, could not define area variable"
432endif
433
434! Area attributes
435text="Mesh area"
436ierr=NF_PUT_ATT_TEXT(nid,varid,"long_name",len_trim(text),text)
437text="m2"
438ierr=NF_PUT_ATT_TEXT(nid,varid,"units",len_trim(text),text)
439
440! Write area to file
441ierr=NF_ENDDEF(nid) ! switch out of NetCDF define mode
442! Write
443#ifdef NC_DOUBLE
444ierr=NF_PUT_VAR_DOUBLE(nid,varid,aire)
445#else
446ierr=NF_PUT_VAR_REAL(nid,varid,aire)
447#endif
448! Note: aire is known from comgeom.h
449if (ierr.ne.NF_NOERR) then
450  write(*,*)"iniwritediagdyn: Error, could not write area variable"
451endif
452
453end subroutine iniwritediagdyn
454
455!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
456
457subroutine def_var_diagdyn(nid,name,title,units,nbdim,dimids,nvarid,ierr)
458
459! This subroutine defines variable 'name' in a (pre-existing and opened)
460! NetCDF file (known from its NetCDF ID 'nid').
461! The number of dimensions 'nbdim' of the variable, as well as the IDs of
462! corresponding dimensions must be set (in array 'dimids').
463! Upon successfull definition of the variable, 'nvarid' contains the
464! NetCDF ID of the variable.
465! The variables' attributes 'title' (Note that 'long_name' would be more
466! appropriate) and 'units' are also set.
467! Modifs: Aug2010 Ehouarn: enforce outputs to be real*4
468
469implicit none
470
471#include "netcdf.inc"
472
473integer,intent(in) :: nid ! NetCDF file ID
474character(len=*),intent(in) :: name ! the variable's name
475character(len=*),intent(in) :: title ! 'title' attribute of variable
476character(len=*),intent(in) :: units ! 'units' attribute of variable
477integer,intent(in) :: nbdim ! number of dimensions of the variable
478integer,dimension(nbdim),intent(in) :: dimids ! NetCDF IDs of the dimensions
479                                              ! the variable is defined along
480integer,intent(out) :: nvarid ! NetCDF ID of the variable
481integer,intent(out) :: ierr ! returned NetCDF staus code
482
483! 1. Switch to NetCDF define mode
484ierr=NF_REDEF(nid)
485
486! 2. Define the variable
487#ifdef NC_DOUBLE
488ierr = NF_DEF_VAR (nid,adjustl(name),NF_DOUBLE,nbdim,dimids,nvarid)
489#else
490ierr = NF_DEF_VAR (nid,adjustl(name),NF_FLOAT,nbdim,dimids,nvarid)
491#endif
492if(ierr/=NF_NOERR) then
493   write(*,*) "def_var_diagdyn: Failed defining variable "//trim(name)
494   write(*,*) NF_STRERROR(ierr)
495   stop ""
496endif
497
498! 3. Write attributes
499ierr=NF_PUT_ATT_TEXT(nid,nvarid,"title",&
500                     len_trim(adjustl(title)),adjustl(title))
501if(ierr/=NF_NOERR) then
502   write(*,*) "def_var_diagdyn: Failed writing title attribute for "//trim(name)
503   write(*,*) NF_STRERROR(ierr)
504   stop ""
505endif
506
507ierr=NF_PUT_ATT_TEXT(nid,nvarid,"units",&
508                     len_trim(adjustl(units)),adjustl(units))
509if(ierr/=NF_NOERR) then
510   write(*,*) "def_var_diagdyn: Failed writing units attribute for "//trim(name)
511   write(*,*) NF_STRERROR(ierr)
512   stop ""
513endif
514
515! 4. Switch out of NetCDF define mode
516ierr = NF_ENDDEF(nid)
517
518end subroutine def_var_diagdyn
Note: See TracBrowser for help on using the repository browser.