Line data Source code
1 : !> \file mo_ncwrite.f90
2 : !> \brief \copybrief mo_ncwrite
3 : !> \details \copydetails mo_ncwrite
4 :
5 : !> \brief Writing netcdf files
6 : !> \details Subroutines for writing arrays on nc file using the netcdf4 library.
7 : !> \author Stephan Thober, Luis Samaniego, Matthias Cuntz
8 : !> \date Nov 2011
9 : !> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
10 : !! FORCES is released under the LGPLv3+ license \license_note
11 : module mo_ncwrite
12 :
13 : use mo_kind, only : i1, i4, sp, dp
14 : use mo_string_utils, only : nonull
15 : use mo_utils, only : ne
16 :
17 : ! functions and constants of netcdf4 library
18 : use netcdf, only : nf90_create, nf90_def_dim, NF90_UNLIMITED, nf90_def_var, &
19 : NF90_CHAR, nf90_put_att, NF90_INT, NF90_INT, NF90_GLOBAL, &
20 : nf90_enddef, nf90_put_var, NF90_FLOAT, NF90_DOUBLE, NF90_BYTE, &
21 : NF90_close, nf90_noerr, nf90_strerror, NF90_CLOBBER, &
22 : NF90_MAX_NAME, NF90_WRITE, nf90_inq_varid, nf90_inquire_variable, &
23 : nf90_inquire_dimension, nf90_open, NF90_64BIT_OFFSET, NF90_NETCDF4, &
24 : nf90_inq_varid, nf90_inq_dimid, nf90_inquire, nf90_get_var, nf90_fill_float, &
25 : nf90_fill_double, nf90_fill_int
26 :
27 : ! public routines -------------------------------------------------------------------
28 : public :: close_netcdf ! save and close the netcdf file
29 : public :: create_netcdf ! create the nc file with variables and their attributes, after they were set
30 : public :: dump_netcdf ! simple dump of variable into a netcdf file
31 : public :: var2nc ! simple dump of multiple variables with attributes into one netcdf file
32 : public :: write_dynamic_netcdf ! write dynamically (one record after the other) in the file
33 : public :: write_static_netcdf ! write static data in the file
34 : ! public types -------------------------------------------------------------------
35 : public :: dims
36 : public :: variable
37 : public :: attribute
38 :
39 : ! public parameters
40 : integer(i4), public, parameter :: nMaxDim = 5 !< nr. max dimensions
41 : integer(i4), public, parameter :: nMaxAtt = 20 !< nr. max attributes
42 : integer(i4), public, parameter :: maxLen = 256 !< nr. string length
43 : integer(i4), public, parameter :: nGAtt = 20 !< nr. global attributes
44 : integer(i4), public, parameter :: nAttDim = 2 !< dim array of attribute values
45 :
46 : ! public types -----------------------------------------------------------------
47 : !> \brief NetCDF dims
48 : type dims
49 : character (len = maxLen) :: name !< dim. name
50 : integer(i4) :: len !< dim. lenght, undefined time => NF90_UNLIMITED
51 : integer(i4) :: dimId !< dim. Id
52 : end type dims
53 :
54 : !> \brief NetCDF attribute
55 : type attribute
56 : character (len = maxLen) :: name !< attribute name
57 : integer(i4) :: xType !< attribute of the values
58 : integer(i4) :: nValues !< number of attributes
59 : character (len = maxLen) :: values !< numbers or "characters" separed by spaces
60 : end type attribute
61 :
62 : !> \brief NetCDF variable
63 : type variable
64 : character (len = maxLen) :: name !< short name
65 : integer(i4) :: xType !< NF90 var. type
66 : integer(i4) :: nLvls !< number of levels
67 : integer(i4) :: nSubs !< number of subparts
68 : logical :: unlimited !< time limited
69 : integer(i4) :: variD !< Id
70 : integer(i4) :: nDims !< field dimension
71 : integer(i4), dimension(nMaxDim) :: dimIds !< passing var. dimensions
72 : integer(i4), dimension(nMaxDim) :: dimTypes !< type of dimensions
73 : integer(i4) :: nAtt !< nr. attributes
74 : type(attribute), dimension(nMaxAtt) :: att !< var. attributes
75 : integer(i4), dimension(nMaxDim) :: start !< starting indices for netcdf
76 : integer(i4), dimension(nMaxDim) :: count !< counter for netcdf
77 : logical :: wFlag !< write flag
78 : integer(i1), pointer :: G0_b !< array pointing model variables
79 : integer(i1), dimension(:), pointer :: G1_b !< array pointing model variables
80 : integer(i1), dimension(:, :), pointer :: G2_b !< array pointing model variables
81 : integer(i1), dimension(:, :, :), pointer :: G3_b !< array pointing model variables
82 : integer(i1), dimension(:, :, :, :), pointer :: G4_b !< array pointing model variables
83 : integer(i4), pointer :: G0_i !< array pointing model variables
84 : integer(i4), dimension(:), pointer :: G1_i !< array pointing model variables
85 : integer(i4), dimension(:, :), pointer :: G2_i !< array pointing model variables
86 : integer(i4), dimension(:, :, :), pointer :: G3_i !< array pointing model variables
87 : integer(i4), dimension(:, :, :, :), pointer :: G4_i !< array pointing model variables
88 : real(sp), pointer :: G0_f !< array pointing model variables
89 : real(sp), dimension(:), pointer :: G1_f !< array pointing model variables
90 : real(sp), dimension(:, :), pointer :: G2_f !< array pointing model variables
91 : real(sp), dimension(:, :, :), pointer :: G3_f !< array pointing model variables
92 : real(sp), dimension(:, :, :, :), pointer :: G4_f !< array pointing model variables
93 : real(dp), pointer :: G0_d !< array pointing model variables
94 : real(dp), dimension(:), pointer :: G1_d !< array pointing model variables
95 : real(dp), dimension(:, :), pointer :: G2_d !< array pointing model variables
96 : real(dp), dimension(:, :, :), pointer :: G3_d !< array pointing model variables
97 : real(dp), dimension(:, :, :, :), pointer :: G4_d !< array pointing model variables
98 : end type variable
99 :
100 : ! public variables -----------------------------------------------------------------
101 : integer(i4), public :: nVars !< nr. variables
102 : integer(i4), public :: nDims !< nr. dimensions
103 : type (dims), public, dimension(:), allocatable :: Dnc !< dimensions list
104 : type(variable), public, dimension(:), allocatable :: V !< variable list, THIS STRUCTURE WILL BE WRITTEN IN THE FILE
105 : type(attribute), public, dimension(nGAtt) :: gatt !< global attributes for netcdf
106 :
107 :
108 : ! ------------------------------------------------------------------
109 :
110 : !> \brief Variable simple write in netcdf.
111 :
112 : !> \details
113 : !! Simple write of a variable in a netcdf file.\n
114 : !! The variabel can be 1 to 5 dimensional and single or double precision.\n
115 : !! 1D and 2D are dumped as static variables. From 3 to 5 dimension, the last
116 : !! dimension will be defined as time.\n
117 : !! The Variable will be called var.
118 : !!
119 : !! \b Example
120 : !!
121 : !! call dump_netcdf('test.nc', myarray)
122 : !! call dump_netcdf('test.nc', myarray, netcdf4=.true.)
123 : !!
124 : !! See also example in test!
125 :
126 : !> \param[in] "character(len=*) :: filename" Name of netcdf output file.
127 : !> \param[in] "real(sp/dp) :: arr(:[,:[,:[,:[,:]]]])" 1D to 5D-array with input numbers.
128 : !> \param[in] "logical, optional :: lfs" True: enable netcdf3 large file support, i.e. 64-bit offset.
129 : !> \param[in] "logical, optional :: logical" True: use netcdf4 format.
130 : !> \param[in] "integer(i4), optional :: deflate_level" Compression level in netcdf4 (default: 1).
131 :
132 : !> \author Matthias Cuntz
133 : !> \date Nov 2012
134 : !> \author Stephan Thober
135 : !> \date Nov 2012
136 : !! - added functions for i4 variables
137 : !> \author Matthias Cuntz and Juliane Mai
138 : !> \date Nov 2012
139 : !! - append
140 : !! - fake time dimension for 1D and 2D
141 : !! - make i4 behave exactly as sp and dp
142 : !> \date Mar 2013
143 : !! - lfs, netcdf4, deflate_level
144 : interface dump_netcdf
145 : module procedure dump_netcdf_1d_sp, dump_netcdf_2d_sp, dump_netcdf_3d_sp, &
146 : dump_netcdf_4d_sp, dump_netcdf_5d_sp, &
147 : dump_netcdf_1d_dp, dump_netcdf_2d_dp, dump_netcdf_3d_dp, &
148 : dump_netcdf_4d_dp, dump_netcdf_5d_dp, &
149 : dump_netcdf_1d_i4, dump_netcdf_2d_i4, dump_netcdf_3d_i4, &
150 : dump_netcdf_4d_i4, dump_netcdf_5d_i4
151 : end interface dump_netcdf
152 :
153 :
154 : ! ------------------------------------------------------------------
155 :
156 : !> \brief Extended dump_netcdf for multiple variables
157 :
158 : !> \details
159 : !! Write different variables including attributes to netcdf
160 : !! file. The attributes are restricted to long_name, units,
161 : !! and missing_value. It is also possible to append variables
162 : !! when an unlimited dimension is specified.
163 : !!
164 : !! \b Example
165 : !!
166 : !! Let <field> be some three dimensional array
167 : !!
168 : !! \code{.f90}
169 : !! dnames(1) = 'x'
170 : !! dnames(2) = 'y'
171 : !! dnames(3) = 'time'
172 : !! \endcode
173 : !!
174 : !! The simplest call to write <field> to a file is
175 : !!
176 : !! \code{.f90}
177 : !! call var2nc('test.nc', field, dnames, 'h')
178 : !! \endcode
179 : !!
180 : !! With attributes it looks like
181 : !!
182 : !! \code{.f90}
183 : !! call var2nc('test.nc', field, dnames, 'h', &
184 : !! long_name = 'height', units = '[m]', missing_value = -9999)
185 : !! \endcode
186 : !!
187 : !! or alternatively
188 : !!
189 : !! \code{.f90}
190 : !! character(256), dimension(3,2) :: attributes
191 : !! attributes(1,1) = 'long_name'
192 : !! attributes(1,2) = 'precipitation'
193 : !! attributes(2,1) = 'units'
194 : !! attributes(2,2) = '[mm/d]'
195 : !! attributes(3,1) = 'missing_value'
196 : !! attributes(3,2) = '-9999.'
197 : !! call var2nc('test.nc', field, dnames, 'h', attributes = attributes, create = .true. )
198 : !! \endcode
199 : !!
200 : !! To be able to dynamically write <field>, an unlimited dimension
201 : !! needs to be specified (in this example field could also be only two
202 : !! dimensional)
203 : !!
204 : !! \code{.f90}
205 : !! call var2nc('test.nc', field(:,:,1), dnames, 'h', dim_unlimited=3)
206 : !! \endcode
207 : !!
208 : !! Now one can append an arbitrary number of time steps, e.g., the next 9
209 : !! and the time has to be added again before
210 : !!
211 : !! \code{.f90}
212 : !! call var2nc('test.nc', (/20,...,100/), dnames(3:3), 'time',
213 : !! dim_unlimited = 1 )
214 : !! call var2nc('test.nc', field(:,:,2:10, dnames, 'h', dim_unlimited=3)
215 : !! \endcode
216 : !!
217 : !! You can also write another variable sharing the same dimensions
218 : !!
219 : !! \code{.f90}
220 : !! call var2nc('test.nc', field_2, dnames(1:2), 'h_2')
221 : !! \endcode
222 : !!
223 : !! The netcdf file can stay open after the first call and subsequent calls can use the file unit
224 : !!
225 : !! \code{.f90}
226 : !! ncid = -1_i4
227 : !! call var2nc('test.nc', field_1, dnames(1:1), 'h_1', ncid=ncid) ! opens file
228 : !! call var2nc('test.nc', field_2, dnames(1:2), 'h_2', ncid=ncid) ! uses ncid from last call
229 : !! call close_netcdf(ncid)
230 : !! \endcode
231 : !!
232 : !! One can also give the start record number (on the unlimited dimension)
233 : !!
234 : !! \code{.f90}
235 : !! ncid = -1_i4
236 : !! call var2nc('test.nc', time1, dnames(3:3), 'time', dim_unlimited=1_i4, ncid=ncid, create=.true.)
237 : !! do i=1, n
238 : !! call var2nc('test.nc', field_2(:,:,i), dnames(1:3), 'h_2', dim_unlimited=3_i4, ncid=ncid, nrec=i)
239 : !! end do
240 : !! call close_netcdf(ncid)
241 : !! \endcode
242 : !!
243 : !! That's it, enjoy!
244 : !!
245 : !! \b Literature
246 : !!
247 : !! The manual of the used netcdf fortran library can be found in
248 : !! Robert Pincus & Ross Rew, The netcdf Fortran 90 Interface Guide
249 :
250 : !> \param[in] "character(*) :: f_name" filename
251 : !> \param[in] "integer(i4)/real(sp,dp) :: arr(:[,:[,:[,:[,:]]]])" array to write
252 : !> \param[in] "character(*) :: dnames(:)" dimension names
253 : !> \param[in] "character(*) :: v_name" variable name
254 : !> \param[in] "integer(i4), optional :: dim_unlimited" index of unlimited dimension
255 : !> \param[in] "character(*), optional :: long_name" attribute
256 : !> \param[in] "character(*), optional :: units" attribute
257 : !> \param[in] "integer(i4)/real(sp,dp), optional :: missing_value" attribute
258 : !> \param[in] "character(256), dimension(:,:), optional :: attributes" two dimensional array of attributes
259 : !! size of first dimension equals number of attributes
260 : !! first entry of second dimension equals attribute name
261 : !! (e.g. long_name)\n
262 : !! second entry of second dimension equals attribute value
263 : !! (e.g. precipitation)\n
264 : !! every attribute is written as string with the exception of
265 : !! missing_value
266 : !> \param[in] "logical, optional :: create" flag - specify whether a
267 : !> output file should be
268 : !> created, default
269 : !> \param[inout] "integer(i4)/real(sp,dp), optional :: ncid" if not given filename will be opened and closed
270 : !! if given and <0 then file will be opened
271 : !! and ncid will return the file unit.
272 : !! if given and >0 then file is assumed open and
273 : !! ncid is used as file unit.
274 : !> \param[in] "integer(i4), optional :: nrec" if given: start point on unlimited dimension.
275 : !> \note It is not allowed to write the following numbers for the indicated type\n
276 : !! number | kind\n
277 : !! -2.1474836E+09 | integer(i4)\n
278 : !! 9.9692100E+36 | real(sp)\n
279 : !! 9.9692099683868690E+36 | real(dp)\n
280 : !! These numbers are netcdf fortran 90 constants! They are used to determine the
281 : !! chunksize of the already written variable. Hence, this routine cannot append
282 : !! correctly to variables when these numbers are used. Only five dimensional
283 : !! variables can be written, only one unlimited dimension can be defined.
284 :
285 : !> \author Stephan Thober & Matthias Cuntz
286 : !> \date May 2014
287 : !! - created
288 : !> \date Jun 2014
289 : !! - added deflate, shuffle, and chunksizes
290 : !! - automatically append variable at the end, renamed _FillValue to missing_value
291 : !> \date Jul 2014
292 : !! - add attributes array, introduced unlimited dimension that is added to the dimensions of the given array
293 : !> \date Jan 2015
294 : !! - changed chunk_size convention to one chunk per unit in unlimited dimension (typically time)
295 : !> \date Feb 2015
296 : !! - d_unlimit was not set in 5d cases
297 : !! - use ne from mo_utils for fill value comparisons
298 : !! - dummy(1) was sp instead of i4 in var2nc_1d_i4
299 : !> \date May 2015
300 : !! - ncid for opening the file only once
301 : !! - nrec for writing a specific record
302 :
303 : interface var2nc
304 : module procedure var2nc_1d_i4, var2nc_1d_sp, var2nc_1d_dp, &
305 : var2nc_2d_i4, var2nc_2d_sp, var2nc_2d_dp, &
306 : var2nc_3d_i4, var2nc_3d_sp, var2nc_3d_dp, &
307 : var2nc_4d_i4, var2nc_4d_sp, var2nc_4d_dp, &
308 : var2nc_5d_i4, var2nc_5d_sp, var2nc_5d_dp
309 : end interface var2nc
310 :
311 : ! ----------------------------------------------------------------------------
312 :
313 : private
314 :
315 : ! ----------------------------------------------------------------------------
316 :
317 : contains
318 :
319 : ! ----------------------------------------------------------------------------
320 :
321 : !> \brief Closes netcdf file stream.
322 :
323 : !> \details
324 : !! Closes a stream of an open netcdf file and saves the file.
325 : !!
326 : !! \b Example
327 : !!
328 : !! See test_mo_ncwrite.
329 : !!
330 : !! \b Literature
331 : !!
332 : !! 1. http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-f90.html
333 :
334 : !> \param[in] "integer(i4) :: ncid" Stream id of an open netcdf file which shall be closed
335 :
336 : !> \note Closes only an already open stream
337 :
338 : !> \author Luis Samaniego
339 : !> \date Feb 2011
340 :
341 : !> \author Stephan Thober
342 : !> \date Dec 2011
343 : !! - added comments and generalized
344 :
345 : !> \author Matthias Cuntz
346 : !> \date Jan 2012
347 : !! - Info
348 : !> \date Mar 2013
349 : !! - removed Info
350 :
351 0 : subroutine close_netcdf(ncId)
352 :
353 : implicit none
354 :
355 : integer(i4), intent(in) :: ncId
356 :
357 : ! close: save new netcdf dataset
358 0 : call check(nf90_close(ncId))
359 :
360 0 : end subroutine close_netcdf
361 :
362 : ! ------------------------------------------------------------------------------
363 :
364 : !> \brief Open and write on new netcdf file.
365 :
366 : !> \details
367 : !! This subroutine will open a new netcdf file and write the variable
368 : !! attributes stored in the structure V in the file. Therefore V
369 : !! has to be already set. See the file set_netcdf in test_mo_ncwrite
370 : !! for an example.
371 : !!
372 : !! \b Literature
373 : !!
374 : !! 1. http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-f90.html
375 :
376 : !> \param[in] "character(len=maxLen) :: File" Filename of file to be written
377 :
378 : !> \param[in] "logical, optional :: lfs" True: enable netcdf3 large file support, i.e. 64-bit offset
379 : !> \param[in] "logical, optional :: logical" True: use netcdf4 format
380 : !> \param[in] "integer(i4), optional :: deflate_level" compression level in netcdf4 (default: 1)
381 : !> \param[out] "integer(i4) :: ncid" integer value of the stream for the opened file
382 :
383 : !> \note This routine only writes attributes and variables which have been stored in V
384 : !! nothing else.
385 :
386 : !> \author Luis Samaniego
387 : !> \date Feb 2011
388 :
389 : !> \author Stephan Thober
390 : !> \date Dec 2011
391 : !! - added comments and generalized
392 : !> \date Feb 2013
393 : !! - added flag for large file support
394 : !> \date Mar 2013
395 : !! - buffersize
396 :
397 : !> \author Matthias Cuntz
398 : !> \date Jan 2012
399 : !! - Info
400 : !> \date Mar 2013
401 : !! - netcdf4, deflate_level
402 : !! - removed Info
403 :
404 0 : subroutine create_netcdf(Filename, ncid, lfs, netcdf4, deflate_level)
405 :
406 : implicit none
407 :
408 : ! netcdf related variables
409 : character(len = *), intent(in) :: Filename
410 : integer(i4), intent(out) :: ncid
411 : logical, intent(in), optional :: lfs ! netcdf3 Large File Support
412 : logical, intent(in), optional :: netcdf4 ! netcdf4
413 : integer(i4), intent(in), optional :: deflate_level ! compression level in netcdf4
414 :
415 : integer(i4) :: i, j, k
416 : integer(i4), dimension(nAttDim) :: att_INT
417 0 : real(sp), dimension(nAttDim) :: att_FLOAT
418 0 : real(dp), dimension(nAttDim) :: att_DOUBLE
419 : character(len = maxLen), dimension(nAttDim) :: att_CHAR
420 : logical :: LargeFile
421 : logical :: inetcdf4
422 : integer(i4) :: deflate
423 : integer(i4) :: buffersize
424 0 : integer(i4), dimension(:), allocatable :: chunksizes ! Size of chunks in netcdf4 writing
425 :
426 0 : LargeFile = .false.
427 0 : if (present(lfs)) LargeFile = lfs
428 0 : inetcdf4 = .true.
429 0 : if (present(netcdf4)) inetcdf4 = netcdf4
430 0 : deflate = 1
431 0 : if (present(deflate_level)) deflate = deflate_level
432 : ! 1 Create netcdf dataset: enter define mode -> get ncId
433 0 : if (inetcdf4) then
434 0 : call check(nf90_create(trim(Filename), NF90_NETCDF4, ncId))
435 : else
436 0 : if (LargeFile) then
437 0 : call check(nf90_create(trim(Filename), NF90_64BIT_OFFSET, ncId, chunksize = buffersize))
438 : else
439 : ! let the netcdf library chose a buffersize, that results in lesser write system calls
440 0 : call check(nf90_create(trim(Filename), NF90_CLOBBER, ncId, chunksize = buffersize))
441 : end if
442 : end if
443 :
444 : ! 2 Define dimensions -> get dimId
445 0 : do i = 1, nDims
446 0 : call check(nf90_def_dim(ncId, Dnc(i)%name, Dnc(i)%len, Dnc(i)%dimId))
447 : end do
448 :
449 : ! 3 Define dimids array, which is used to pass the dimids of the dimensions of
450 : ! the netcdf variables
451 0 : do i = 1, nVars
452 0 : V(i)%unlimited = .false.
453 0 : V(i)%dimids = 0
454 0 : V(i)%start = 1
455 0 : V(i)%count = 1
456 0 : do k = 1, V(i)%nDims
457 0 : if (Dnc(V(i)%dimTypes(k))%len == NF90_UNLIMITED) V(i)%unlimited = .true.
458 0 : V(i)%dimids(k) = Dnc(V(i)%dimTypes(k))%dimId
459 : end do
460 0 : if (V(i)%unlimited) then
461 : ! set counts for unlimited files (time is always the last dimension)
462 0 : if (V(i)%nDims == 1) cycle
463 0 : do k = 1, V(i)%nDims - 1
464 0 : V(i)%count(k) = Dnc(V(i)%dimTypes(k))%len
465 : end do
466 : end if
467 : end do
468 :
469 : ! 4 Define the netcdf variables and attributes -> get varId
470 0 : allocate(chunksizes(maxval(V(1 : nVars)%nDims)))
471 0 : do i = 1, nVars
472 0 : if (.not. V(i)%wFlag) cycle
473 0 : if (inetcdf4) then
474 0 : chunksizes(1 : V(i)%nDims) = Dnc(V(i)%dimTypes(1 : V(i)%nDims))%len
475 0 : chunksizes(V(i)%nDims) = 1
476 0 : call check(nf90_def_var(ncId, V(i)%name, V(i)%xtype, V(i)%dimids(1 : V(i)%nDims), V(i)%varId, &
477 0 : chunksizes = chunksizes(1 : V(i)%nDims), shuffle = .true., deflate_level = deflate))
478 : else
479 0 : call check(nf90_def_var(ncId, V(i)%name, V(i)%xtype, V(i)%dimids(1 : V(i)%nDims), V(i)%varId))
480 : end if
481 0 : do k = 1, V(i)%nAtt
482 0 : select case (V(i)%att(k)%xType)
483 : case (NF90_CHAR)
484 : ! read(V(i)%att(k)%values, *) (att_CHAR(j), j =1, V(i)%att(k)%nValues)
485 0 : read(V(i)%att(k)%values, '(a)') att_CHAR(1)
486 0 : call check(nf90_put_att (ncId, V(i)%varId, V(i)%att(k)%name, att_CHAR(1)))
487 : case (NF90_INT)
488 0 : read(V(i)%att(k)%values, *) (att_INT(j), j = 1, V(i)%att(k)%nValues)
489 0 : call check(nf90_put_att (ncId, V(i)%varId, V(i)%att(k)%name, att_INT(1 : V(i)%att(k)%nValues)))
490 : case (NF90_FLOAT)
491 0 : read(V(i)%att(k)%values, *) (att_FLOAT(j), j = 1, V(i)%att(k)%nValues)
492 0 : call check(nf90_put_att (ncId, V(i)%varId, V(i)%att(k)%name, att_FLOAT(1 : V(i)%att(k)%nValues)))
493 : case (NF90_DOUBLE)
494 0 : read(V(i)%att(k)%values, *) (att_DOUBLE(j), j = 1, V(i)%att(k)%nValues)
495 0 : call check(nf90_put_att (ncId, V(i)%varId, V(i)%att(k)%name, att_DOUBLE(1 : V(i)%att(k)%nValues)))
496 : end select
497 : end do
498 : end do
499 :
500 : ! 5 Global attributes
501 0 : do k = 1, nGAtt
502 0 : if (nonull(Gatt(k)%name)) then
503 0 : call check(nf90_put_att(ncId, NF90_GLOBAL, Gatt(k)%name, Gatt(k)%values))
504 : end if
505 : end do
506 :
507 : ! 6 end definitions: leave define mode
508 0 : call check(nf90_enddef(ncId))
509 :
510 0 : deallocate(chunksizes)
511 :
512 0 : end subroutine create_netcdf
513 :
514 :
515 : ! ------------------------------------------------------------------
516 :
517 0 : subroutine dump_netcdf_1d_sp(filename, arr, append, lfs, netcdf4, deflate_level)
518 :
519 : implicit none
520 :
521 : character(len = *), intent(in) :: filename ! netcdf file name
522 : real(sp), dimension(:), intent(in) :: arr ! input array
523 : logical, optional, intent(in) :: append ! append to existing file
524 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
525 : logical, optional, intent(in) :: netcdf4 ! netcdf4
526 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
527 :
528 : integer(i4), parameter :: ndim = 1 ! Routine for ndim dimensional array
529 : character(len = 1), dimension(4) :: dnames ! Common dimension names
530 : integer(i4), dimension(ndim + 1) :: dims ! Size of each dimension
531 : integer(i4), dimension(ndim + 1) :: dimid ! netcdf IDs of each dimension
532 : integer(i4), dimension(ndim + 2) :: varid ! dimension variables and var id
533 : integer(i4), dimension(ndim + 1) :: start ! start array for write of each time step
534 : integer(i4), dimension(ndim + 1) :: counter ! length array for write of each time step
535 : integer(i4), dimension(ndim + 1) :: chunksizes ! Size of chunks in netcdf4 writing
536 : integer(i4) :: ncid ! netcdf file id
537 : integer(i4) :: i, j
538 : logical :: iappend
539 : integer(i4) :: idim ! read dimension on append
540 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
541 : logical :: LargeFile
542 : logical :: inetcdf4
543 : integer(i4) :: deflate
544 : integer(i4) :: buffersize
545 :
546 : ! append or not
547 0 : if (present(append)) then
548 0 : if (append) then
549 : iappend = .true.
550 : else
551 0 : iappend = .false.
552 : end if
553 : else
554 : iappend = .false.
555 : end if
556 0 : LargeFile = .false.
557 0 : if (present(lfs)) LargeFile = lfs
558 0 : inetcdf4 = .false.
559 0 : if (present(netcdf4)) inetcdf4 = netcdf4
560 0 : deflate = 1
561 0 : if (present(deflate_level)) deflate = deflate_level
562 :
563 : ! dimension names
564 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
565 :
566 0 : if (iappend) then
567 : ! open file
568 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
569 :
570 : ! inquire variables time and var
571 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
572 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
573 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
574 0 : if (idim /= ndim + 1) stop "dump_netcdf_1d_sp: number of variable dimensions /= number of file variable dimensions."
575 :
576 : ! inquire dimensions
577 0 : do i = 1, ndim + 1
578 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
579 0 : if (i < ndim + 1) then
580 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_1d_sp: dimension name problem."
581 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_1d_sp: variable dimension /= file variable dimension."
582 : else
583 0 : if (trim(name) /= 'time') stop "dump_netcdf_1d_sp: time name problem."
584 : end if
585 : enddo
586 :
587 : ! append
588 0 : start(:) = 1
589 0 : counter(:) = dims
590 0 : counter(ndim + 1) = 1
591 0 : do i = 1, 1
592 0 : start(ndim + 1) = dims(ndim + 1) + i
593 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
594 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
595 : end do
596 : else
597 : ! open file
598 0 : if (inetcdf4) then
599 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
600 : else
601 0 : if (LargeFile) then
602 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
603 : else
604 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
605 : end if
606 : end if
607 :
608 : ! define dims
609 0 : dims(1 : ndim) = shape(arr)
610 0 : do i = 1, ndim
611 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
612 : end do
613 : ! define dim time
614 0 : dims(ndim + 1) = 1
615 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim + 1)))
616 :
617 : ! define dim variables
618 0 : do i = 1, ndim
619 0 : if (inetcdf4) then
620 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
621 : else
622 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
623 : end if
624 : end do
625 : ! define time variable
626 0 : if (inetcdf4) then
627 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
628 : else
629 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
630 : end if
631 :
632 : ! define variable
633 0 : if (inetcdf4) then
634 0 : chunksizes(1 : ndim) = dims(1 : ndim)
635 0 : chunksizes(ndim + 1) = 1
636 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 2), &
637 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
638 : else
639 0 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 2)))
640 : end if
641 :
642 : ! end define mode
643 0 : call check(nf90_enddef(ncid))
644 :
645 : ! write dimensions
646 0 : do i = 1, ndim
647 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
648 : end do
649 :
650 : ! write time and variable
651 0 : start(:) = 1
652 0 : counter(:) = dims
653 0 : counter(ndim + 1) = 1
654 0 : do i = 1, 1
655 0 : start(ndim + 1) = i
656 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
657 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
658 : end do
659 : end if
660 :
661 : ! close netcdf file
662 0 : call check(nf90_close(ncid))
663 :
664 0 : end subroutine dump_netcdf_1d_sp
665 :
666 :
667 0 : subroutine dump_netcdf_2d_sp(filename, arr, append, lfs, netcdf4, deflate_level)
668 :
669 : implicit none
670 :
671 : character(len = *), intent(in) :: filename ! netcdf file name
672 : real(sp), dimension(:, :), intent(in) :: arr ! input array
673 : logical, optional, intent(in) :: append ! append to existing file
674 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
675 : logical, optional, intent(in) :: netcdf4 ! netcdf4
676 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
677 :
678 : integer(i4), parameter :: ndim = 2 ! Routine for ndim dimensional array
679 : character(len = 1), dimension(4) :: dnames ! Common dimension names
680 : integer(i4), dimension(ndim + 1) :: dims ! Size of each dimension
681 : integer(i4), dimension(ndim + 1) :: dimid ! netcdf IDs of each dimension
682 : integer(i4), dimension(ndim + 2) :: varid ! dimension variables and var id
683 : integer(i4), dimension(ndim + 1) :: start ! start array for write of each time step
684 : integer(i4), dimension(ndim + 1) :: counter ! length array for write of each time step
685 : integer(i4), dimension(ndim + 1) :: chunksizes ! Size of chunks in netcdf4 writing
686 : integer(i4) :: ncid ! netcdf file id
687 : integer(i4) :: i, j
688 : logical :: iappend
689 : integer(i4) :: idim ! read dimension on append
690 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
691 : logical :: LargeFile
692 : logical :: inetcdf4
693 : integer(i4) :: deflate
694 : integer(i4) :: buffersize
695 :
696 : ! append or not
697 0 : if (present(append)) then
698 0 : if (append) then
699 : iappend = .true.
700 : else
701 0 : iappend = .false.
702 : end if
703 : else
704 : iappend = .false.
705 : end if
706 0 : LargeFile = .false.
707 0 : if (present(lfs)) LargeFile = lfs
708 0 : inetcdf4 = .false.
709 0 : if (present(netcdf4)) inetcdf4 = netcdf4
710 0 : deflate = 1
711 0 : if (present(deflate_level)) deflate = deflate_level
712 :
713 : ! dimension names
714 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
715 :
716 0 : if (iappend) then
717 : ! open file
718 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
719 :
720 : ! inquire variables time and var
721 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
722 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
723 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
724 0 : if (idim /= ndim + 1) stop "dump_netcdf_2d_sp: number of variable dimensions /= number of file variable dimensions."
725 :
726 : ! inquire dimensions
727 0 : do i = 1, ndim + 1
728 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
729 0 : if (i < ndim + 1) then
730 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_2d_sp: dimension name problem."
731 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_2d_sp: variable dimension /= file variable dimension."
732 : else
733 0 : if (trim(name) /= 'time') stop "dump_netcdf_2d_sp: time name problem."
734 : end if
735 : enddo
736 :
737 : ! append
738 0 : start(:) = 1
739 0 : counter(:) = dims
740 0 : counter(ndim + 1) = 1
741 0 : do i = 1, 1
742 0 : start(ndim + 1) = dims(ndim + 1) + i
743 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
744 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
745 : end do
746 : else
747 : ! open file
748 0 : if (inetcdf4) then
749 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
750 : else
751 0 : if (LargeFile) then
752 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
753 : else
754 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
755 : end if
756 : end if
757 :
758 : ! define dims
759 0 : dims(1 : ndim) = shape(arr)
760 0 : do i = 1, ndim
761 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
762 : end do
763 : ! define dim time
764 0 : dims(ndim + 1) = 1
765 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim + 1)))
766 :
767 : ! define dim variables
768 0 : do i = 1, ndim
769 0 : if (inetcdf4) then
770 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
771 : else
772 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
773 : end if
774 : end do
775 : ! define time variable
776 0 : if (inetcdf4) then
777 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
778 : else
779 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
780 : end if
781 :
782 : ! define variable
783 0 : if (inetcdf4) then
784 0 : chunksizes(1 : ndim) = dims(1 : ndim)
785 0 : chunksizes(ndim + 1) = 1
786 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 2), &
787 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
788 : else
789 0 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 2)))
790 : end if
791 :
792 : ! end define mode
793 0 : call check(nf90_enddef(ncid))
794 :
795 : ! write dimensions
796 0 : do i = 1, ndim
797 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
798 : end do
799 :
800 : ! write time and variable
801 0 : start(:) = 1
802 0 : counter(:) = dims
803 0 : counter(ndim + 1) = 1
804 0 : do i = 1, 1
805 0 : start(ndim + 1) = i
806 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
807 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
808 : end do
809 : end if
810 :
811 : ! close netcdf file
812 0 : call check(nf90_close(ncid))
813 :
814 0 : end subroutine dump_netcdf_2d_sp
815 :
816 :
817 0 : subroutine dump_netcdf_3d_sp(filename, arr, append, lfs, netcdf4, deflate_level)
818 :
819 : implicit none
820 :
821 : character(len = *), intent(in) :: filename ! netcdf file name
822 : real(sp), dimension(:, :, :), intent(in) :: arr ! input array
823 : logical, optional, intent(in) :: append ! append to existing file
824 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
825 : logical, optional, intent(in) :: netcdf4 ! netcdf4
826 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
827 :
828 : integer(i4), parameter :: ndim = 3 ! Routine for ndim dimensional array
829 : character(len = 1), dimension(4) :: dnames ! Common dimension names
830 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
831 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
832 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
833 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
834 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
835 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
836 : integer(i4) :: ncid ! netcdf file id
837 : integer(i4) :: i, j
838 : logical :: iappend
839 : integer(i4) :: idim ! read dimension on append
840 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
841 : logical :: LargeFile
842 : logical :: inetcdf4
843 : integer(i4) :: deflate
844 : integer(i4) :: buffersize
845 :
846 : ! append or not
847 0 : if (present(append)) then
848 0 : if (append) then
849 : iappend = .true.
850 : else
851 0 : iappend = .false.
852 : end if
853 : else
854 : iappend = .false.
855 : end if
856 0 : LargeFile = .false.
857 0 : if (present(lfs)) LargeFile = lfs
858 0 : inetcdf4 = .false.
859 0 : if (present(netcdf4)) inetcdf4 = netcdf4
860 0 : deflate = 1
861 0 : if (present(deflate_level)) deflate = deflate_level
862 :
863 : ! dimension names
864 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
865 :
866 0 : if (iappend) then
867 : ! open file
868 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
869 :
870 : ! inquire variables time and var
871 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
872 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
873 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
874 0 : if (idim /= ndim) stop "dump_netcdf_3d_sp: number of variable dimensions /= number of file variable dimensions."
875 :
876 : ! inquire dimensions
877 0 : do i = 1, ndim
878 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
879 0 : if (i < ndim) then
880 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_3d_sp: dimension name problem."
881 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_3d_sp: variable dimension /= file variable dimension."
882 : else
883 0 : if (trim(name) /= 'time') stop "dump_netcdf_3d_sp: time name problem."
884 : end if
885 : enddo
886 :
887 : ! append
888 0 : start(:) = 1
889 0 : counter(:) = dims
890 0 : counter(ndim) = 1
891 0 : do i = 1, size(arr, ndim)
892 0 : start(ndim) = dims(ndim) + i
893 0 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
894 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
895 : end do
896 : else
897 : ! open file
898 0 : if (inetcdf4) then
899 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
900 : else
901 0 : if (LargeFile) then
902 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
903 : else
904 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
905 : end if
906 : end if
907 :
908 : ! define dims
909 0 : dims = shape(arr)
910 0 : do i = 1, ndim - 1
911 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
912 : end do
913 : ! define dim time
914 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
915 :
916 : ! define dim variables
917 0 : do i = 1, ndim - 1
918 0 : if (inetcdf4) then
919 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
920 : else
921 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
922 : end if
923 : end do
924 : ! define time variable
925 0 : if (inetcdf4) then
926 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
927 : else
928 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
929 : end if
930 :
931 : ! define variable
932 0 : if (inetcdf4) then
933 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
934 0 : chunksizes(ndim) = 1
935 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 1), &
936 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
937 : else
938 0 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 1)))
939 : end if
940 :
941 : ! end define mode
942 0 : call check(nf90_enddef(ncid))
943 :
944 : ! write dimensions
945 0 : do i = 1, ndim - 1
946 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
947 : end do
948 :
949 : ! write time and variable
950 0 : start(:) = 1
951 0 : counter(:) = dims
952 0 : counter(ndim) = 1
953 0 : do i = 1, dims(ndim)
954 0 : start(ndim) = i
955 0 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
956 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
957 : end do
958 : end if
959 :
960 : ! close netcdf file
961 0 : call check(nf90_close(ncid))
962 :
963 0 : end subroutine dump_netcdf_3d_sp
964 :
965 :
966 0 : subroutine dump_netcdf_4d_sp(filename, arr, append, lfs, netcdf4, deflate_level)
967 :
968 : implicit none
969 :
970 : character(len = *), intent(in) :: filename ! netcdf file name
971 : real(sp), dimension(:, :, :, :), intent(in) :: arr ! input array
972 : logical, optional, intent(in) :: append ! append to existing file
973 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
974 : logical, optional, intent(in) :: netcdf4 ! netcdf4
975 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
976 :
977 : integer(i4), parameter :: ndim = 4 ! Routine for ndim dimensional array
978 : character(len = 1), dimension(4) :: dnames ! Common dimension names
979 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
980 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
981 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
982 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
983 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
984 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
985 : integer(i4) :: ncid ! netcdf file id
986 : integer(i4) :: i, j
987 : logical :: iappend
988 : integer(i4) :: idim ! read dimension on append
989 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
990 : logical :: LargeFile
991 : logical :: inetcdf4
992 : integer(i4) :: deflate
993 : integer(i4) :: buffersize
994 :
995 : ! append or not
996 0 : if (present(append)) then
997 0 : if (append) then
998 : iappend = .true.
999 : else
1000 0 : iappend = .false.
1001 : end if
1002 : else
1003 : iappend = .false.
1004 : end if
1005 0 : LargeFile = .false.
1006 0 : if (present(lfs)) LargeFile = lfs
1007 0 : inetcdf4 = .false.
1008 0 : if (present(netcdf4)) inetcdf4 = netcdf4
1009 0 : deflate = 1
1010 0 : if (present(deflate_level)) deflate = deflate_level
1011 :
1012 : ! dimension names
1013 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1014 :
1015 0 : if (iappend) then
1016 : ! open file
1017 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
1018 :
1019 : ! inquire variables time and var
1020 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1021 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1022 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1023 0 : if (idim /= ndim) stop "dump_netcdf_4d_sp: number of variable dimensions /= number of file variable dimensions."
1024 :
1025 : ! inquire dimensions
1026 0 : do i = 1, ndim
1027 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1028 0 : if (i < ndim) then
1029 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_4d_sp: dimension name problem."
1030 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_4d_sp: variable dimension /= file variable dimension."
1031 : else
1032 0 : if (trim(name) /= 'time') stop "dump_netcdf_4d_sp: time name problem."
1033 : end if
1034 : enddo
1035 :
1036 : ! append
1037 0 : start(:) = 1
1038 0 : counter(:) = dims
1039 0 : counter(ndim) = 1
1040 0 : do i = 1, size(arr, ndim)
1041 0 : start(ndim) = dims(ndim) + i
1042 0 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1043 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
1044 : end do
1045 : else
1046 : ! open file
1047 0 : if (inetcdf4) then
1048 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
1049 : else
1050 0 : if (LargeFile) then
1051 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
1052 : else
1053 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
1054 : end if
1055 : end if
1056 :
1057 : ! define dims
1058 0 : dims = shape(arr)
1059 0 : do i = 1, ndim - 1
1060 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1061 : end do
1062 : ! define dim time
1063 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
1064 :
1065 : ! define dim variables
1066 0 : do i = 1, ndim - 1
1067 0 : if (inetcdf4) then
1068 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1069 : else
1070 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1071 : end if
1072 : end do
1073 : ! define time variable
1074 0 : if (inetcdf4) then
1075 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1076 : else
1077 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1078 : end if
1079 :
1080 : ! define variable
1081 0 : if (inetcdf4) then
1082 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1083 0 : chunksizes(ndim) = 1
1084 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 1), &
1085 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1086 : else
1087 0 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 1)))
1088 : end if
1089 :
1090 : ! end define mode
1091 0 : call check(nf90_enddef(ncid))
1092 :
1093 : ! write dimensions
1094 0 : do i = 1, ndim - 1
1095 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1096 : end do
1097 :
1098 : ! write time and variable
1099 0 : start(:) = 1
1100 0 : counter(:) = dims
1101 0 : counter(ndim) = 1
1102 0 : do i = 1, dims(ndim)
1103 0 : start(ndim) = i
1104 0 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
1105 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
1106 : end do
1107 : end if
1108 :
1109 : ! close netcdf file
1110 0 : call check(nf90_close(ncid))
1111 :
1112 0 : end subroutine dump_netcdf_4d_sp
1113 :
1114 :
1115 0 : subroutine dump_netcdf_5d_sp(filename, arr, append, lfs, netcdf4, deflate_level)
1116 :
1117 : implicit none
1118 :
1119 : character(len = *), intent(in) :: filename ! netcdf file name
1120 : real(sp), dimension(:, :, :, :, :), intent(in) :: arr ! input array
1121 : logical, optional, intent(in) :: append ! append to existing file
1122 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
1123 : logical, optional, intent(in) :: netcdf4 ! netcdf4
1124 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
1125 :
1126 : integer(i4), parameter :: ndim = 5 ! Routine for ndim dimensional array
1127 : character(len = 1), dimension(4) :: dnames ! Common dimension names
1128 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
1129 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
1130 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
1131 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
1132 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
1133 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
1134 : integer(i4) :: ncid ! netcdf file id
1135 : integer(i4) :: i, j
1136 : logical :: iappend
1137 : integer(i4) :: idim ! read dimension on append
1138 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
1139 : logical :: LargeFile
1140 : logical :: inetcdf4
1141 : integer(i4) :: deflate
1142 : integer(i4) :: buffersize
1143 :
1144 : ! append or not
1145 0 : if (present(append)) then
1146 0 : if (append) then
1147 : iappend = .true.
1148 : else
1149 0 : iappend = .false.
1150 : end if
1151 : else
1152 : iappend = .false.
1153 : end if
1154 0 : LargeFile = .false.
1155 0 : if (present(lfs)) LargeFile = lfs
1156 0 : inetcdf4 = .false.
1157 0 : if (present(netcdf4)) inetcdf4 = netcdf4
1158 0 : deflate = 1
1159 0 : if (present(deflate_level)) deflate = deflate_level
1160 :
1161 : ! dimension names
1162 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1163 :
1164 0 : if (iappend) then
1165 : ! open file
1166 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
1167 :
1168 : ! inquire variables time and var
1169 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1170 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1171 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1172 0 : if (idim /= ndim) stop "dump_netcdf_5d_sp: number of variable dimensions /= number of file variable dimensions."
1173 :
1174 : ! inquire dimensions
1175 0 : do i = 1, ndim
1176 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1177 0 : if (i < ndim) then
1178 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_5d_sp: dimension name problem."
1179 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_5d_sp: variable dimension /= file variable dimension."
1180 : else
1181 0 : if (trim(name) /= 'time') stop "dump_netcdf_5d_sp: time name problem."
1182 : end if
1183 : enddo
1184 :
1185 : ! append
1186 0 : start(:) = 1
1187 0 : counter(:) = dims
1188 0 : counter(ndim) = 1
1189 0 : do i = 1, size(arr, ndim)
1190 0 : start(ndim) = dims(ndim) + i
1191 0 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1192 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
1193 : end do
1194 : else
1195 : ! open file
1196 0 : if (inetcdf4) then
1197 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
1198 : else
1199 0 : if (LargeFile) then
1200 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
1201 : else
1202 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
1203 : end if
1204 : end if
1205 :
1206 : ! define dims
1207 0 : dims = shape(arr)
1208 0 : do i = 1, ndim - 1
1209 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1210 : end do
1211 : ! define dim time
1212 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
1213 :
1214 : ! define dim variables
1215 0 : do i = 1, ndim - 1
1216 0 : if (inetcdf4) then
1217 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1218 : else
1219 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1220 : end if
1221 : end do
1222 : ! define time variable
1223 0 : if (inetcdf4) then
1224 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1225 : else
1226 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1227 : end if
1228 :
1229 : ! define variable
1230 0 : if (inetcdf4) then
1231 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1232 0 : chunksizes(ndim) = 1
1233 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 1), &
1234 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1235 : else
1236 0 : call check(nf90_def_var(ncid, 'var', NF90_FLOAT, dimid, varid(ndim + 1)))
1237 : end if
1238 :
1239 : ! end define mode
1240 0 : call check(nf90_enddef(ncid))
1241 :
1242 : ! write dimensions
1243 0 : do i = 1, ndim - 1
1244 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1245 : end do
1246 :
1247 : ! write time and variable
1248 0 : start(:) = 1
1249 0 : counter(:) = dims
1250 0 : counter(ndim) = 1
1251 0 : do i = 1, dims(ndim)
1252 0 : start(ndim) = i
1253 0 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
1254 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
1255 : end do
1256 : end if
1257 :
1258 : ! close netcdf file
1259 0 : call check(nf90_close(ncid))
1260 :
1261 0 : end subroutine dump_netcdf_5d_sp
1262 :
1263 :
1264 0 : subroutine dump_netcdf_1d_dp(filename, arr, append, lfs, netcdf4, deflate_level)
1265 :
1266 : implicit none
1267 :
1268 : character(len = *), intent(in) :: filename ! netcdf file name
1269 : real(dp), dimension(:), intent(in) :: arr ! input array
1270 : logical, optional, intent(in) :: append ! append to existing file
1271 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
1272 : logical, optional, intent(in) :: netcdf4 ! netcdf4
1273 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
1274 :
1275 : integer(i4), parameter :: ndim = 1 ! Routine for ndim dimensional array
1276 : character(len = 1), dimension(4) :: dnames ! Common dimension names
1277 : integer(i4), dimension(ndim + 1) :: dims ! Size of each dimension
1278 : integer(i4), dimension(ndim + 1) :: dimid ! netcdf IDs of each dimension
1279 : integer(i4), dimension(ndim + 2) :: varid ! dimension variables and var id
1280 : integer(i4), dimension(ndim + 1) :: start ! start array for write of each time step
1281 : integer(i4), dimension(ndim + 1) :: counter ! length array for write of each time step
1282 : integer(i4), dimension(ndim + 1) :: chunksizes ! Size of chunks in netcdf4 writing
1283 : integer(i4) :: ncid ! netcdf file id
1284 : integer(i4) :: i, j
1285 : logical :: iappend
1286 : integer(i4) :: idim ! read dimension on append
1287 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
1288 : logical :: LargeFile
1289 : logical :: inetcdf4
1290 : integer(i4) :: deflate
1291 : integer(i4) :: buffersize
1292 :
1293 : ! append or not
1294 0 : if (present(append)) then
1295 0 : if (append) then
1296 : iappend = .true.
1297 : else
1298 0 : iappend = .false.
1299 : end if
1300 : else
1301 : iappend = .false.
1302 : end if
1303 0 : LargeFile = .false.
1304 0 : if (present(lfs)) LargeFile = lfs
1305 0 : inetcdf4 = .false.
1306 0 : if (present(netcdf4)) inetcdf4 = netcdf4
1307 0 : deflate = 1
1308 0 : if (present(deflate_level)) deflate = deflate_level
1309 :
1310 : ! dimension names
1311 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1312 :
1313 0 : if (iappend) then
1314 : ! open file
1315 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
1316 :
1317 : ! inquire variables time and var
1318 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
1319 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
1320 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
1321 0 : if (idim /= ndim + 1) stop "dump_netcdf_1d_dp: number of variable dimensions /= number of file variable dimensions."
1322 :
1323 : ! inquire dimensions
1324 0 : do i = 1, ndim + 1
1325 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1326 0 : if (i < ndim + 1) then
1327 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_1d_dp: dimension name problem."
1328 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_1d_dp: variable dimension /= file variable dimension."
1329 : else
1330 0 : if (trim(name) /= 'time') stop "dump_netcdf_1d_dp: time name problem."
1331 : end if
1332 : enddo
1333 :
1334 : ! append
1335 0 : start(:) = 1
1336 0 : counter(:) = dims
1337 0 : counter(ndim + 1) = 1
1338 0 : do i = 1, 1
1339 0 : start(ndim + 1) = dims(ndim + 1) + i
1340 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
1341 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
1342 : end do
1343 : else
1344 : ! open file
1345 0 : if (inetcdf4) then
1346 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
1347 : else
1348 0 : if (LargeFile) then
1349 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
1350 : else
1351 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
1352 : end if
1353 : end if
1354 :
1355 : ! define dims
1356 0 : dims(1 : ndim) = shape(arr)
1357 0 : do i = 1, ndim
1358 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1359 : end do
1360 : ! define dim time
1361 0 : dims(ndim + 1) = 1
1362 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim + 1)))
1363 :
1364 : ! define dim variables
1365 0 : do i = 1, ndim
1366 0 : if (inetcdf4) then
1367 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1368 : else
1369 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1370 : end if
1371 : end do
1372 : ! define time variable
1373 0 : if (inetcdf4) then
1374 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
1375 : else
1376 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
1377 : end if
1378 :
1379 : ! define variable
1380 0 : if (inetcdf4) then
1381 0 : chunksizes(1 : ndim) = dims(1 : ndim)
1382 0 : chunksizes(ndim + 1) = 1
1383 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 2), &
1384 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1385 : else
1386 0 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 2)))
1387 : end if
1388 :
1389 : ! end define mode
1390 0 : call check(nf90_enddef(ncid))
1391 :
1392 : ! write dimensions
1393 0 : do i = 1, ndim
1394 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1395 : end do
1396 :
1397 : ! write time and variable
1398 0 : start(:) = 1
1399 0 : counter(:) = dims
1400 0 : counter(ndim + 1) = 1
1401 0 : do i = 1, 1
1402 0 : start(ndim + 1) = i
1403 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
1404 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
1405 : end do
1406 : end if
1407 :
1408 : ! close netcdf file
1409 0 : call check(nf90_close(ncid))
1410 :
1411 0 : end subroutine dump_netcdf_1d_dp
1412 :
1413 :
1414 0 : subroutine dump_netcdf_2d_dp(filename, arr, append, lfs, netcdf4, deflate_level)
1415 :
1416 : implicit none
1417 :
1418 : character(len = *), intent(in) :: filename ! netcdf file name
1419 : real(dp), dimension(:, :), intent(in) :: arr ! input array
1420 : logical, optional, intent(in) :: append ! append to existing file
1421 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
1422 : logical, optional, intent(in) :: netcdf4 ! netcdf4
1423 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
1424 :
1425 : integer(i4), parameter :: ndim = 2 ! Routine for ndim dimensional array
1426 : character(len = 1), dimension(4) :: dnames ! Common dimension names
1427 : integer(i4), dimension(ndim + 1) :: dims ! Size of each dimension
1428 : integer(i4), dimension(ndim + 1) :: dimid ! netcdf IDs of each dimension
1429 : integer(i4), dimension(ndim + 2) :: varid ! dimension variables and var id
1430 : integer(i4), dimension(ndim + 1) :: start ! start array for write of each time step
1431 : integer(i4), dimension(ndim + 1) :: counter ! length array for write of each time step
1432 : integer(i4), dimension(ndim + 1) :: chunksizes ! Size of chunks in netcdf4 writing
1433 : integer(i4) :: ncid ! netcdf file id
1434 : integer(i4) :: i, j
1435 : logical :: iappend
1436 : integer(i4) :: idim ! read dimension on append
1437 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
1438 : logical :: LargeFile
1439 : logical :: inetcdf4
1440 : integer(i4) :: deflate
1441 : integer(i4) :: buffersize
1442 :
1443 : ! append or not
1444 0 : if (present(append)) then
1445 0 : if (append) then
1446 : iappend = .true.
1447 : else
1448 0 : iappend = .false.
1449 : end if
1450 : else
1451 : iappend = .false.
1452 : end if
1453 0 : LargeFile = .false.
1454 0 : if (present(lfs)) LargeFile = lfs
1455 0 : inetcdf4 = .false.
1456 0 : if (present(netcdf4)) inetcdf4 = netcdf4
1457 0 : deflate = 1
1458 0 : if (present(deflate_level)) deflate = deflate_level
1459 :
1460 : ! dimension names
1461 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1462 :
1463 0 : if (iappend) then
1464 : ! open file
1465 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
1466 :
1467 : ! inquire variables time and var
1468 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
1469 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
1470 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
1471 0 : if (idim /= ndim + 1) stop "dump_netcdf_2d_dp: number of variable dimensions /= number of file variable dimensions."
1472 :
1473 : ! inquire dimensions
1474 0 : do i = 1, ndim + 1
1475 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1476 0 : if (i < ndim + 1) then
1477 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_2d_dp: dimension name problem."
1478 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_2d_dp: variable dimension /= file variable dimension."
1479 : else
1480 0 : if (trim(name) /= 'time') stop "dump_netcdf_2d_dp: time name problem."
1481 : end if
1482 : enddo
1483 :
1484 : ! append
1485 0 : start(:) = 1
1486 0 : counter(:) = dims
1487 0 : counter(ndim + 1) = 1
1488 0 : do i = 1, 1
1489 0 : start(ndim + 1) = dims(ndim + 1) + i
1490 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
1491 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
1492 : end do
1493 : else
1494 : ! open file
1495 0 : if (inetcdf4) then
1496 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
1497 : else
1498 0 : if (LargeFile) then
1499 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
1500 : else
1501 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
1502 : end if
1503 : end if
1504 :
1505 : ! define dims
1506 0 : dims(1 : ndim) = shape(arr)
1507 0 : do i = 1, ndim
1508 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1509 : end do
1510 : ! define dim time
1511 0 : dims(ndim + 1) = 1
1512 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim + 1)))
1513 :
1514 : ! define dim variables
1515 0 : do i = 1, ndim
1516 0 : if (inetcdf4) then
1517 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1518 : else
1519 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1520 : end if
1521 : end do
1522 : ! define time variable
1523 0 : if (inetcdf4) then
1524 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
1525 : else
1526 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
1527 : end if
1528 :
1529 : ! define variable
1530 0 : if (inetcdf4) then
1531 0 : chunksizes(1 : ndim) = dims(1 : ndim)
1532 0 : chunksizes(ndim + 1) = 1
1533 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 2), &
1534 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1535 : else
1536 0 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 2)))
1537 : end if
1538 :
1539 : ! end define mode
1540 0 : call check(nf90_enddef(ncid))
1541 :
1542 : ! write dimensions
1543 0 : do i = 1, ndim
1544 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1545 : end do
1546 :
1547 : ! write time and variable
1548 0 : start(:) = 1
1549 0 : counter(:) = dims
1550 0 : counter(ndim + 1) = 1
1551 0 : do i = 1, 1
1552 0 : start(ndim + 1) = i
1553 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
1554 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
1555 : end do
1556 : end if
1557 :
1558 : ! close netcdf file
1559 0 : call check(nf90_close(ncid))
1560 :
1561 0 : end subroutine dump_netcdf_2d_dp
1562 :
1563 :
1564 20 : subroutine dump_netcdf_3d_dp(filename, arr, append, lfs, netcdf4, deflate_level)
1565 :
1566 : implicit none
1567 :
1568 : character(len = *), intent(in) :: filename ! netcdf file name
1569 : real(dp), dimension(:, :, :), intent(in) :: arr ! input array
1570 : logical, optional, intent(in) :: append ! append to existing file
1571 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
1572 : logical, optional, intent(in) :: netcdf4 ! netcdf4
1573 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
1574 :
1575 : integer(i4), parameter :: ndim = 3 ! Routine for ndim dimensional array
1576 : character(len = 1), dimension(4) :: dnames ! Common dimension names
1577 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
1578 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
1579 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
1580 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
1581 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
1582 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
1583 : integer(i4) :: ncid ! netcdf file id
1584 : integer(i4) :: i, j
1585 : logical :: iappend
1586 : integer(i4) :: idim ! read dimension on append
1587 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
1588 : logical :: LargeFile
1589 : logical :: inetcdf4
1590 : integer(i4) :: deflate
1591 : integer(i4) :: buffersize
1592 :
1593 : ! append or not
1594 20 : if (present(append)) then
1595 10 : if (append) then
1596 : iappend = .true.
1597 : else
1598 0 : iappend = .false.
1599 : end if
1600 : else
1601 : iappend = .false.
1602 : end if
1603 20 : LargeFile = .false.
1604 20 : if (present(lfs)) LargeFile = lfs
1605 20 : inetcdf4 = .false.
1606 20 : if (present(netcdf4)) inetcdf4 = netcdf4
1607 20 : deflate = 1
1608 20 : if (present(deflate_level)) deflate = deflate_level
1609 :
1610 : ! dimension names
1611 100 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1612 :
1613 20 : if (iappend) then
1614 : ! open file
1615 10 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
1616 :
1617 : ! inquire variables time and var
1618 10 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1619 10 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1620 10 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1621 10 : if (idim /= ndim) stop "dump_netcdf_3d_dp: number of variable dimensions /= number of file variable dimensions."
1622 :
1623 : ! inquire dimensions
1624 40 : do i = 1, ndim
1625 30 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1626 40 : if (i < ndim) then
1627 20 : if (trim(name) /= dnames(i)) stop "dump_netcdf_3d_dp: dimension name problem."
1628 20 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_3d_dp: variable dimension /= file variable dimension."
1629 : else
1630 10 : if (trim(name) /= 'time') stop "dump_netcdf_3d_dp: time name problem."
1631 : end if
1632 : enddo
1633 :
1634 : ! append
1635 40 : start(:) = 1
1636 10 : counter(:) = dims
1637 10 : counter(ndim) = 1
1638 20 : do i = 1, size(arr, ndim)
1639 10 : start(ndim) = dims(ndim) + i
1640 30 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1641 20 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
1642 : end do
1643 : else
1644 : ! open file
1645 10 : if (inetcdf4) then
1646 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
1647 : ! call check(nf90_set_fill(ncid, NF90_NOFILL, old_fill_mode))
1648 : else
1649 10 : if (LargeFile) then
1650 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
1651 : else
1652 10 : call check(nf90_create(trim(Filename), NF90_CLOBBER, ncid, chunksize = buffersize))
1653 : end if
1654 : end if
1655 :
1656 : ! define dims
1657 40 : dims = shape(arr)
1658 30 : do i = 1, ndim - 1
1659 30 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1660 : end do
1661 : ! define dim time
1662 10 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
1663 :
1664 : ! define dim variables
1665 30 : do i = 1, ndim - 1
1666 30 : if (inetcdf4) then
1667 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1668 : else
1669 20 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1670 : end if
1671 : end do
1672 : ! define time variable
1673 10 : if (inetcdf4) then
1674 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1675 : else
1676 10 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1677 : end if
1678 :
1679 : ! define variable
1680 10 : if (inetcdf4) then
1681 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1682 0 : chunksizes(ndim) = 1
1683 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 1), &
1684 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1685 : else
1686 10 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 1)))
1687 : end if
1688 :
1689 : ! end define mode
1690 10 : call check(nf90_enddef(ncid))
1691 :
1692 : ! write dimensions
1693 30 : do i = 1, ndim - 1
1694 60090 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1695 : end do
1696 :
1697 : ! write time and variable
1698 40 : start(:) = 1
1699 10 : counter(:) = dims
1700 10 : counter(ndim) = 1
1701 20 : do i = 1, dims(ndim)
1702 10 : start(ndim) = i
1703 30 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
1704 20 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
1705 : end do
1706 : end if
1707 :
1708 : ! close netcdf file
1709 20 : call check(nf90_close(ncid))
1710 :
1711 0 : end subroutine dump_netcdf_3d_dp
1712 :
1713 :
1714 0 : subroutine dump_netcdf_4d_dp(filename, arr, append, lfs, netcdf4, deflate_level)
1715 :
1716 : implicit none
1717 :
1718 : character(len = *), intent(in) :: filename ! netcdf file name
1719 : real(dp), dimension(:, :, :, :), intent(in) :: arr ! input array
1720 : logical, optional, intent(in) :: append ! append to existing file
1721 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
1722 : logical, optional, intent(in) :: netcdf4 ! netcdf4
1723 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
1724 :
1725 : integer(i4), parameter :: ndim = 4 ! Routine for ndim dimensional array
1726 : character(len = 1), dimension(4) :: dnames ! Common dimension names
1727 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
1728 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
1729 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
1730 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
1731 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
1732 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
1733 : integer(i4) :: ncid ! netcdf file id
1734 : integer(i4) :: i, j
1735 : logical :: iappend
1736 : integer(i4) :: idim ! read dimension on append
1737 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
1738 : logical :: LargeFile
1739 : logical :: inetcdf4
1740 : integer(i4) :: deflate
1741 : integer(i4) :: buffersize
1742 :
1743 : ! append or not
1744 0 : if (present(append)) then
1745 0 : if (append) then
1746 : iappend = .true.
1747 : else
1748 0 : iappend = .false.
1749 : end if
1750 : else
1751 : iappend = .false.
1752 : end if
1753 0 : LargeFile = .false.
1754 0 : if (present(lfs)) LargeFile = lfs
1755 0 : inetcdf4 = .false.
1756 0 : if (present(netcdf4)) inetcdf4 = netcdf4
1757 0 : deflate = 1
1758 0 : if (present(deflate_level)) deflate = deflate_level
1759 :
1760 : ! dimension names
1761 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1762 :
1763 0 : if (iappend) then
1764 : ! open file
1765 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
1766 :
1767 : ! inquire variables time and var
1768 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1769 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1770 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1771 0 : if (idim /= ndim) stop "dump_netcdf_4d_dp: number of variable dimensions /= number of file variable dimensions."
1772 :
1773 : ! inquire dimensions
1774 0 : do i = 1, ndim
1775 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1776 0 : if (i < ndim) then
1777 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_4d_dp: dimension name problem."
1778 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_4d_dp: variable dimension /= file variable dimension."
1779 : else
1780 0 : if (trim(name) /= 'time') stop "dump_netcdf_4d_dp: time name problem."
1781 : end if
1782 : enddo
1783 :
1784 : ! append
1785 0 : start(:) = 1
1786 0 : counter(:) = dims
1787 0 : counter(ndim) = 1
1788 0 : do i = 1, size(arr, ndim)
1789 0 : start(ndim) = dims(ndim) + i
1790 0 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1791 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
1792 : end do
1793 : else
1794 : ! open file
1795 0 : if (inetcdf4) then
1796 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
1797 : else
1798 0 : if (LargeFile) then
1799 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
1800 : else
1801 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
1802 : end if
1803 : end if
1804 :
1805 : ! define dims
1806 0 : dims = shape(arr)
1807 0 : do i = 1, ndim - 1
1808 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1809 : end do
1810 : ! define dim time
1811 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
1812 :
1813 : ! define dim variables
1814 0 : do i = 1, ndim - 1
1815 0 : if (inetcdf4) then
1816 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1817 : else
1818 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1819 : end if
1820 : end do
1821 : ! define time variable
1822 0 : if (inetcdf4) then
1823 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1824 : else
1825 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1826 : end if
1827 :
1828 : ! define variable
1829 0 : if (inetcdf4) then
1830 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1831 0 : chunksizes(ndim) = 1
1832 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 1), &
1833 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1834 : else
1835 0 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 1)))
1836 : end if
1837 :
1838 : ! end define mode
1839 0 : call check(nf90_enddef(ncid))
1840 :
1841 : ! write dimensions
1842 0 : do i = 1, ndim - 1
1843 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1844 : end do
1845 :
1846 : ! write time and variable
1847 0 : start(:) = 1
1848 0 : counter(:) = dims
1849 0 : counter(ndim) = 1
1850 0 : do i = 1, dims(ndim)
1851 0 : start(ndim) = i
1852 0 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
1853 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
1854 : end do
1855 : end if
1856 :
1857 : ! close netcdf file
1858 0 : call check(nf90_close(ncid))
1859 :
1860 20 : end subroutine dump_netcdf_4d_dp
1861 :
1862 :
1863 0 : subroutine dump_netcdf_5d_dp(filename, arr, append, lfs, netcdf4, deflate_level)
1864 :
1865 : implicit none
1866 :
1867 : character(len = *), intent(in) :: filename ! netcdf file name
1868 : real(dp), dimension(:, :, :, :, :), intent(in) :: arr ! input array
1869 : logical, optional, intent(in) :: append ! append to existing file
1870 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
1871 : logical, optional, intent(in) :: netcdf4 ! netcdf4
1872 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
1873 :
1874 : integer(i4), parameter :: ndim = 5 ! Routine for ndim dimensional array
1875 : character(len = 1), dimension(4) :: dnames ! Common dimension names
1876 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
1877 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
1878 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
1879 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
1880 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
1881 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
1882 : integer(i4) :: ncid ! netcdf file id
1883 : integer(i4) :: i, j
1884 : logical :: iappend
1885 : integer(i4) :: idim ! read dimension on append
1886 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
1887 : logical :: LargeFile
1888 : logical :: inetcdf4
1889 : integer(i4) :: deflate
1890 : integer(i4) :: buffersize
1891 :
1892 : ! append or not
1893 0 : if (present(append)) then
1894 0 : if (append) then
1895 : iappend = .true.
1896 : else
1897 0 : iappend = .false.
1898 : end if
1899 : else
1900 : iappend = .false.
1901 : end if
1902 0 : LargeFile = .false.
1903 0 : if (present(lfs)) LargeFile = lfs
1904 0 : inetcdf4 = .false.
1905 0 : if (present(netcdf4)) inetcdf4 = netcdf4
1906 0 : deflate = 1
1907 0 : if (present(deflate_level)) deflate = deflate_level
1908 :
1909 : ! dimension names
1910 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1911 :
1912 0 : if (iappend) then
1913 : ! open file
1914 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
1915 :
1916 : ! inquire variables time and var
1917 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1918 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1919 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1920 0 : if (idim /= ndim) stop "dump_netcdf_5d_dp: number of variable dimensions /= number of file variable dimensions."
1921 :
1922 : ! inquire dimensions
1923 0 : do i = 1, ndim
1924 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1925 0 : if (i < ndim) then
1926 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_5d_dp: dimension name problem."
1927 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_5d_dp: variable dimension /= file variable dimension."
1928 : else
1929 0 : if (trim(name) /= 'time') stop "dump_netcdf_5d_dp: time name problem."
1930 : end if
1931 : enddo
1932 :
1933 : ! append
1934 0 : start(:) = 1
1935 0 : counter(:) = dims
1936 0 : counter(ndim) = 1
1937 0 : do i = 1, size(arr, ndim)
1938 0 : start(ndim) = dims(ndim) + i
1939 0 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1940 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
1941 : end do
1942 : else
1943 : ! open file
1944 0 : if (inetcdf4) then
1945 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
1946 : else
1947 0 : if (LargeFile) then
1948 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
1949 : else
1950 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
1951 : end if
1952 : end if
1953 :
1954 : ! define dims
1955 0 : dims = shape(arr)
1956 0 : do i = 1, ndim - 1
1957 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1958 : end do
1959 : ! define dim time
1960 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
1961 :
1962 : ! define dim variables
1963 0 : do i = 1, ndim - 1
1964 0 : if (inetcdf4) then
1965 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1966 : else
1967 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
1968 : end if
1969 : end do
1970 : ! define time variable
1971 0 : if (inetcdf4) then
1972 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1973 : else
1974 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
1975 : end if
1976 :
1977 : ! define variable
1978 0 : if (inetcdf4) then
1979 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1980 0 : chunksizes(ndim) = 1
1981 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 1), &
1982 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1983 : else
1984 0 : call check(nf90_def_var(ncid, 'var', NF90_DOUBLE, dimid, varid(ndim + 1)))
1985 : end if
1986 :
1987 : ! end define mode
1988 0 : call check(nf90_enddef(ncid))
1989 :
1990 : ! write dimensions
1991 0 : do i = 1, ndim - 1
1992 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1993 : end do
1994 :
1995 : ! write time and variable
1996 0 : start(:) = 1
1997 0 : counter(:) = dims
1998 0 : counter(ndim) = 1
1999 0 : do i = 1, dims(ndim)
2000 0 : start(ndim) = i
2001 0 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
2002 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
2003 : end do
2004 : end if
2005 :
2006 : ! close netcdf file
2007 0 : call check(nf90_close(ncid))
2008 :
2009 0 : end subroutine dump_netcdf_5d_dp
2010 :
2011 :
2012 0 : subroutine dump_netcdf_1d_i4(filename, arr, append, lfs, netcdf4, deflate_level)
2013 :
2014 : implicit none
2015 :
2016 : character(len = *), intent(in) :: filename ! netcdf file name
2017 : integer(i4), dimension(:), intent(in) :: arr ! input array
2018 : logical, optional, intent(in) :: append ! append to existing file
2019 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
2020 : logical, optional, intent(in) :: netcdf4 ! netcdf4
2021 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
2022 :
2023 : integer(i4), parameter :: ndim = 1 ! Routine for ndim dimensional array
2024 : character(len = 1), dimension(4) :: dnames ! Common dimension names
2025 : integer(i4), dimension(ndim + 1) :: dims ! Size of each dimension
2026 : integer(i4), dimension(ndim + 1) :: dimid ! netcdf IDs of each dimension
2027 : integer(i4), dimension(ndim + 2) :: varid ! dimension variables and var id
2028 : integer(i4), dimension(ndim + 1) :: start ! start array for write of each time step
2029 : integer(i4), dimension(ndim + 1) :: counter ! length array for write of each time step
2030 : integer(i4), dimension(ndim + 1) :: chunksizes ! Size of chunks in netcdf4 writing
2031 : integer(i4) :: ncid ! netcdf file id
2032 : integer(i4) :: i, j
2033 : logical :: iappend
2034 : integer(i4) :: idim ! read dimension on append
2035 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
2036 : logical :: LargeFile
2037 : logical :: inetcdf4
2038 : integer(i4) :: deflate
2039 : integer(i4) :: buffersize
2040 :
2041 : ! append or not
2042 0 : if (present(append)) then
2043 0 : if (append) then
2044 : iappend = .true.
2045 : else
2046 0 : iappend = .false.
2047 : end if
2048 : else
2049 : iappend = .false.
2050 : end if
2051 0 : LargeFile = .false.
2052 0 : if (present(lfs)) LargeFile = lfs
2053 0 : inetcdf4 = .false.
2054 0 : if (present(netcdf4)) inetcdf4 = netcdf4
2055 0 : deflate = 1
2056 0 : if (present(deflate_level)) deflate = deflate_level
2057 :
2058 : ! dimension names
2059 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2060 :
2061 0 : if (iappend) then
2062 : ! open file
2063 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
2064 :
2065 : ! inquire variables time and var
2066 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
2067 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
2068 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
2069 0 : if (idim /= ndim + 1) stop "dump_netcdf_1d_i4: number of variable dimensions /= number of file variable dimensions."
2070 :
2071 : ! inquire dimensions
2072 0 : do i = 1, ndim + 1
2073 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2074 0 : if (i < ndim + 1) then
2075 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_1d_i4: dimension name problem."
2076 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_1d_i4: variable dimension /= file variable dimension."
2077 : else
2078 0 : if (trim(name) /= 'time') stop "dump_netcdf_1d_i4: time name problem."
2079 : end if
2080 : enddo
2081 :
2082 : ! append
2083 0 : start(:) = 1
2084 0 : counter(:) = dims
2085 0 : counter(ndim + 1) = 1
2086 0 : do i = 1, 1
2087 0 : start(ndim + 1) = dims(ndim + 1) + i
2088 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
2089 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
2090 : end do
2091 : else
2092 : ! open file
2093 0 : if (inetcdf4) then
2094 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
2095 : else
2096 0 : if (LargeFile) then
2097 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
2098 : else
2099 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
2100 : end if
2101 : end if
2102 :
2103 : ! define dims
2104 0 : dims(1 : ndim) = shape(arr)
2105 0 : do i = 1, ndim
2106 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2107 : end do
2108 : ! define dim time
2109 0 : dims(ndim + 1) = 1
2110 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim + 1)))
2111 :
2112 : ! define dim variables
2113 0 : do i = 1, ndim
2114 0 : if (inetcdf4) then
2115 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2116 : else
2117 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2118 : end if
2119 : end do
2120 : ! define time variable
2121 0 : if (inetcdf4) then
2122 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
2123 : else
2124 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
2125 : end if
2126 :
2127 : ! define variable
2128 0 : if (inetcdf4) then
2129 0 : chunksizes(1 : ndim) = dims(1 : ndim)
2130 0 : chunksizes(ndim + 1) = 1
2131 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 2), &
2132 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2133 : else
2134 0 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 2)))
2135 : end if
2136 :
2137 : ! end define mode
2138 0 : call check(nf90_enddef(ncid))
2139 :
2140 : ! write dimensions
2141 0 : do i = 1, ndim
2142 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2143 : end do
2144 :
2145 : ! write time and variable
2146 0 : start(:) = 1
2147 0 : counter(:) = dims
2148 0 : counter(ndim + 1) = 1
2149 0 : do i = 1, 1
2150 0 : start(ndim + 1) = i
2151 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
2152 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
2153 : end do
2154 : end if
2155 :
2156 : ! close netcdf file
2157 0 : call check(nf90_close(ncid))
2158 :
2159 0 : end subroutine dump_netcdf_1d_i4
2160 :
2161 :
2162 0 : subroutine dump_netcdf_2d_i4(filename, arr, append, lfs, netcdf4, deflate_level)
2163 :
2164 : implicit none
2165 :
2166 : character(len = *), intent(in) :: filename ! netcdf file name
2167 : integer(i4), dimension(:, :), intent(in) :: arr ! input array
2168 : logical, optional, intent(in) :: append ! append to existing file
2169 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
2170 : logical, optional, intent(in) :: netcdf4 ! netcdf4
2171 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
2172 :
2173 : integer(i4), parameter :: ndim = 2 ! Routine for ndim dimensional array
2174 : character(len = 1), dimension(4) :: dnames ! Common dimension names
2175 : integer(i4), dimension(ndim + 1) :: dims ! Size of each dimension
2176 : integer(i4), dimension(ndim + 1) :: dimid ! netcdf IDs of each dimension
2177 : integer(i4), dimension(ndim + 2) :: varid ! dimension variables and var id
2178 : integer(i4), dimension(ndim + 1) :: start ! start array for write of each time step
2179 : integer(i4), dimension(ndim + 1) :: counter ! length array for write of each time step
2180 : integer(i4), dimension(ndim + 1) :: chunksizes ! Size of chunks in netcdf4 writing
2181 : integer(i4) :: ncid ! netcdf file id
2182 : integer(i4) :: i, j
2183 : logical :: iappend
2184 : integer(i4) :: idim ! read dimension on append
2185 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
2186 : logical :: LargeFile
2187 : logical :: inetcdf4
2188 : integer(i4) :: deflate
2189 : integer(i4) :: buffersize
2190 :
2191 : ! append or not
2192 0 : if (present(append)) then
2193 0 : if (append) then
2194 : iappend = .true.
2195 : else
2196 0 : iappend = .false.
2197 : end if
2198 : else
2199 : iappend = .false.
2200 : end if
2201 0 : LargeFile = .false.
2202 0 : if (present(lfs)) LargeFile = lfs
2203 0 : inetcdf4 = .false.
2204 0 : if (present(netcdf4)) inetcdf4 = netcdf4
2205 0 : deflate = 1
2206 0 : if (present(deflate_level)) deflate = deflate_level
2207 :
2208 : ! dimension names
2209 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2210 :
2211 0 : if (iappend) then
2212 : ! open file
2213 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
2214 :
2215 : ! inquire variables time and var
2216 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
2217 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
2218 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
2219 0 : if (idim /= ndim + 1) stop "dump_netcdf_2d_i4: number of variable dimensions /= number of file variable dimensions."
2220 :
2221 : ! inquire dimensions
2222 0 : do i = 1, ndim + 1
2223 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2224 0 : if (i < ndim + 1) then
2225 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_2d_i4: dimension name problem."
2226 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_2d_i4: variable dimension /= file variable dimension."
2227 : else
2228 0 : if (trim(name) /= 'time') stop "dump_netcdf_2d_i4: time name problem."
2229 : end if
2230 : enddo
2231 :
2232 : ! append
2233 0 : start(:) = 1
2234 0 : counter(:) = dims
2235 0 : counter(ndim + 1) = 1
2236 0 : do i = 1, 1
2237 0 : start(ndim + 1) = dims(ndim + 1) + i
2238 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
2239 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
2240 : end do
2241 : else
2242 : ! open file
2243 0 : if (inetcdf4) then
2244 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
2245 : else
2246 0 : if (LargeFile) then
2247 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
2248 : else
2249 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
2250 : end if
2251 : end if
2252 :
2253 : ! define dims
2254 0 : dims(1 : ndim) = shape(arr)
2255 0 : do i = 1, ndim
2256 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2257 : end do
2258 : ! define dim time
2259 0 : dims(ndim + 1) = 1
2260 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim + 1)))
2261 :
2262 : ! define dim variables
2263 0 : do i = 1, ndim
2264 0 : if (inetcdf4) then
2265 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2266 : else
2267 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2268 : end if
2269 : end do
2270 : ! define time variable
2271 0 : if (inetcdf4) then
2272 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
2273 : else
2274 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim + 1), varid(ndim + 1)))
2275 : end if
2276 :
2277 : ! define variable
2278 0 : if (inetcdf4) then
2279 0 : chunksizes(1 : ndim) = dims(1 : ndim)
2280 0 : chunksizes(ndim + 1) = 1
2281 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 2), &
2282 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2283 : else
2284 0 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 2)))
2285 : end if
2286 :
2287 : ! end define mode
2288 0 : call check(nf90_enddef(ncid))
2289 :
2290 : ! write dimensions
2291 0 : do i = 1, ndim
2292 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2293 : end do
2294 :
2295 : ! write time and variable
2296 0 : start(:) = 1
2297 0 : counter(:) = dims
2298 0 : counter(ndim + 1) = 1
2299 0 : do i = 1, 1
2300 0 : start(ndim + 1) = i
2301 0 : call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
2302 0 : call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
2303 : end do
2304 : end if
2305 :
2306 : ! close netcdf file
2307 0 : call check(nf90_close(ncid))
2308 :
2309 0 : end subroutine dump_netcdf_2d_i4
2310 :
2311 :
2312 0 : subroutine dump_netcdf_3d_i4(filename, arr, append, lfs, netcdf4, deflate_level)
2313 :
2314 : implicit none
2315 :
2316 : character(len = *), intent(in) :: filename ! netcdf file name
2317 : integer(i4), dimension(:, :, :), intent(in) :: arr ! input array
2318 : logical, optional, intent(in) :: append ! append to existing file
2319 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
2320 : logical, optional, intent(in) :: netcdf4 ! netcdf4
2321 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
2322 :
2323 : integer(i4), parameter :: ndim = 3 ! Routine for ndim dimensional array
2324 : character(len = 1), dimension(4) :: dnames ! Common dimension names
2325 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
2326 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
2327 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
2328 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
2329 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
2330 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
2331 : integer(i4) :: ncid ! netcdf file id
2332 : integer(i4) :: i, j
2333 : logical :: iappend
2334 : integer(i4) :: idim ! read dimension on append
2335 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
2336 : logical :: LargeFile
2337 : logical :: inetcdf4
2338 : integer(i4) :: deflate
2339 : integer(i4) :: buffersize
2340 :
2341 : ! append or not
2342 0 : if (present(append)) then
2343 0 : if (append) then
2344 : iappend = .true.
2345 : else
2346 0 : iappend = .false.
2347 : end if
2348 : else
2349 : iappend = .false.
2350 : end if
2351 0 : LargeFile = .false.
2352 0 : if (present(lfs)) LargeFile = lfs
2353 0 : inetcdf4 = .false.
2354 0 : if (present(netcdf4)) inetcdf4 = netcdf4
2355 0 : deflate = 1
2356 0 : if (present(deflate_level)) deflate = deflate_level
2357 :
2358 : ! dimension names
2359 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2360 :
2361 0 : if (iappend) then
2362 : ! open file
2363 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
2364 :
2365 : ! inquire variables time and var
2366 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
2367 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
2368 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
2369 0 : if (idim /= ndim) stop "dump_netcdf_3d_i4: number of variable dimensions /= number of file variable dimensions."
2370 :
2371 : ! inquire dimensions
2372 0 : do i = 1, ndim
2373 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2374 0 : if (i < ndim) then
2375 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_3d_i4: dimension name problem."
2376 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_3d_i4: variable dimension /= file variable dimension."
2377 : else
2378 0 : if (trim(name) /= 'time') stop "dump_netcdf_3d_i4: time name problem."
2379 : end if
2380 : enddo
2381 :
2382 : ! append
2383 0 : start(:) = 1
2384 0 : counter(:) = dims
2385 0 : counter(ndim) = 1
2386 0 : do i = 1, size(arr, ndim)
2387 0 : start(ndim) = dims(ndim) + i
2388 0 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
2389 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
2390 : end do
2391 : else
2392 : ! open file
2393 0 : if (inetcdf4) then
2394 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
2395 : else
2396 0 : if (LargeFile) then
2397 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
2398 : else
2399 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
2400 : end if
2401 : end if
2402 :
2403 : ! define dims
2404 0 : dims = shape(arr)
2405 0 : do i = 1, ndim - 1
2406 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2407 : end do
2408 : ! define dim time
2409 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
2410 :
2411 : ! define dim variables
2412 0 : do i = 1, ndim - 1
2413 0 : if (inetcdf4) then
2414 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2415 : else
2416 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2417 : end if
2418 : end do
2419 : ! define time variable
2420 0 : if (inetcdf4) then
2421 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
2422 : else
2423 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
2424 : end if
2425 :
2426 : ! define variable
2427 0 : if (inetcdf4) then
2428 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
2429 0 : chunksizes(ndim) = 1
2430 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 1), &
2431 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2432 : else
2433 0 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 1)))
2434 : end if
2435 :
2436 : ! end define mode
2437 0 : call check(nf90_enddef(ncid))
2438 :
2439 : ! write dimensions
2440 0 : do i = 1, ndim - 1
2441 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2442 : end do
2443 :
2444 : ! write time and variable
2445 0 : start(:) = 1
2446 0 : counter(:) = dims
2447 0 : counter(ndim) = 1
2448 0 : do i = 1, dims(ndim)
2449 0 : start(ndim) = i
2450 0 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
2451 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
2452 : end do
2453 : end if
2454 :
2455 : ! close netcdf file
2456 0 : call check(nf90_close(ncid))
2457 :
2458 0 : end subroutine dump_netcdf_3d_i4
2459 :
2460 :
2461 0 : subroutine dump_netcdf_4d_i4(filename, arr, append, lfs, netcdf4, deflate_level)
2462 :
2463 : implicit none
2464 :
2465 : character(len = *), intent(in) :: filename ! netcdf file name
2466 : integer(i4), dimension(:, :, :, :), intent(in) :: arr ! input array
2467 : logical, optional, intent(in) :: append ! append to existing file
2468 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
2469 : logical, optional, intent(in) :: netcdf4 ! netcdf4
2470 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
2471 :
2472 : integer(i4), parameter :: ndim = 4 ! Routine for ndim dimensional array
2473 : character(len = 1), dimension(4) :: dnames ! Common dimension names
2474 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
2475 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
2476 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
2477 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
2478 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
2479 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
2480 : integer(i4) :: ncid ! netcdf file id
2481 : integer(i4) :: i, j
2482 : logical :: iappend
2483 : integer(i4) :: idim ! read dimension on append
2484 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
2485 : logical :: LargeFile
2486 : logical :: inetcdf4
2487 : integer(i4) :: deflate
2488 : integer(i4) :: buffersize
2489 :
2490 : ! append or not
2491 0 : if (present(append)) then
2492 0 : if (append) then
2493 : iappend = .true.
2494 : else
2495 0 : iappend = .false.
2496 : end if
2497 : else
2498 : iappend = .false.
2499 : end if
2500 0 : LargeFile = .false.
2501 0 : if (present(lfs)) LargeFile = lfs
2502 0 : inetcdf4 = .false.
2503 0 : if (present(netcdf4)) inetcdf4 = netcdf4
2504 0 : deflate = 1
2505 0 : if (present(deflate_level)) deflate = deflate_level
2506 :
2507 : ! dimension names
2508 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2509 :
2510 0 : if (iappend) then
2511 : ! open file
2512 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
2513 :
2514 : ! inquire variables time and var
2515 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
2516 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
2517 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
2518 0 : if (idim /= ndim) stop "dump_netcdf_4d_i4: number of variable dimensions /= number of file variable dimensions."
2519 :
2520 : ! inquire dimensions
2521 0 : do i = 1, ndim
2522 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2523 0 : if (i < ndim) then
2524 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_4d_i4: dimension name problem."
2525 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_4d_i4: variable dimension /= file variable dimension."
2526 : else
2527 0 : if (trim(name) /= 'time') stop "dump_netcdf_4d_i4: time name problem."
2528 : end if
2529 : enddo
2530 :
2531 : ! append
2532 0 : start(:) = 1
2533 0 : counter(:) = dims
2534 0 : counter(ndim) = 1
2535 0 : do i = 1, size(arr, ndim)
2536 0 : start(ndim) = dims(ndim) + i
2537 0 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
2538 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
2539 : end do
2540 : else
2541 : ! open file
2542 0 : if (inetcdf4) then
2543 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
2544 : else
2545 0 : if (LargeFile) then
2546 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
2547 : else
2548 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
2549 : end if
2550 : end if
2551 :
2552 : ! define dims
2553 0 : dims = shape(arr)
2554 0 : do i = 1, ndim - 1
2555 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2556 : end do
2557 : ! define dim time
2558 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
2559 :
2560 : ! define dim variables
2561 0 : do i = 1, ndim - 1
2562 0 : if (inetcdf4) then
2563 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2564 : else
2565 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2566 : end if
2567 : end do
2568 : ! define time variable
2569 0 : if (inetcdf4) then
2570 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
2571 : else
2572 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
2573 : end if
2574 :
2575 : ! define variable
2576 0 : if (inetcdf4) then
2577 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
2578 0 : chunksizes(ndim) = 1
2579 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 1), &
2580 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2581 : else
2582 0 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 1)))
2583 : end if
2584 :
2585 : ! end define mode
2586 0 : call check(nf90_enddef(ncid))
2587 :
2588 : ! write dimensions
2589 0 : do i = 1, ndim - 1
2590 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2591 : end do
2592 :
2593 : ! write time and variable
2594 0 : start(:) = 1
2595 0 : counter(:) = dims
2596 0 : counter(ndim) = 1
2597 0 : do i = 1, dims(ndim)
2598 0 : start(ndim) = i
2599 0 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
2600 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
2601 : end do
2602 : end if
2603 :
2604 : ! close netcdf file
2605 0 : call check(nf90_close(ncid))
2606 :
2607 0 : end subroutine dump_netcdf_4d_i4
2608 :
2609 :
2610 0 : subroutine dump_netcdf_5d_i4(filename, arr, append, lfs, netcdf4, deflate_level)
2611 :
2612 : implicit none
2613 :
2614 : character(len = *), intent(in) :: filename ! netcdf file name
2615 : integer(i4), dimension(:, :, :, :, :), intent(in) :: arr ! input array
2616 : logical, optional, intent(in) :: append ! append to existing file
2617 : logical, optional, intent(in) :: lfs ! netcdf3 Large File Support
2618 : logical, optional, intent(in) :: netcdf4 ! netcdf4
2619 : integer(i4), optional, intent(in) :: deflate_level ! compression level in netcdf4
2620 :
2621 : integer(i4), parameter :: ndim = 5 ! Routine for ndim dimensional array
2622 : character(len = 1), dimension(4) :: dnames ! Common dimension names
2623 : integer(i4), dimension(ndim) :: dims ! Size of each dimension
2624 : integer(i4), dimension(ndim) :: dimid ! netcdf IDs of each dimension
2625 : integer(i4), dimension(ndim + 1) :: varid ! dimension variables and var id
2626 : integer(i4), dimension(ndim) :: start ! start array for write of each time step
2627 : integer(i4), dimension(ndim) :: counter ! length array for write of each time step
2628 : integer(i4), dimension(ndim) :: chunksizes ! Size of chunks in netcdf4 writing
2629 : integer(i4) :: ncid ! netcdf file id
2630 : integer(i4) :: i, j
2631 : logical :: iappend
2632 : integer(i4) :: idim ! read dimension on append
2633 : character(NF90_MAX_NAME) :: name ! name of dimensions from nf90_inquire_dimension
2634 : logical :: LargeFile
2635 : logical :: inetcdf4
2636 : integer(i4) :: deflate
2637 : integer(i4) :: buffersize
2638 :
2639 : ! append or not
2640 0 : if (present(append)) then
2641 0 : if (append) then
2642 : iappend = .true.
2643 : else
2644 0 : iappend = .false.
2645 : end if
2646 : else
2647 : iappend = .false.
2648 : end if
2649 0 : LargeFile = .false.
2650 0 : if (present(lfs)) LargeFile = lfs
2651 0 : inetcdf4 = .false.
2652 0 : if (present(netcdf4)) inetcdf4 = netcdf4
2653 0 : deflate = 1
2654 0 : if (present(deflate_level)) deflate = deflate_level
2655 :
2656 : ! dimension names
2657 0 : dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2658 :
2659 0 : if (iappend) then
2660 : ! open file
2661 0 : call check(nf90_open(trim(filename), NF90_WRITE, ncid))
2662 :
2663 : ! inquire variables time and var
2664 0 : call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
2665 0 : call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
2666 0 : call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
2667 0 : if (idim /= ndim) stop "dump_netcdf_5d_i4: number of variable dimensions /= number of file variable dimensions."
2668 :
2669 : ! inquire dimensions
2670 0 : do i = 1, ndim
2671 0 : call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2672 0 : if (i < ndim) then
2673 0 : if (trim(name) /= dnames(i)) stop "dump_netcdf_5d_i4: dimension name problem."
2674 0 : if (dims(i) /= size(arr, i)) stop "dump_netcdf_5d_i4: variable dimension /= file variable dimension."
2675 : else
2676 0 : if (trim(name) /= 'time') stop "dump_netcdf_5d_i4: time name problem."
2677 : end if
2678 : enddo
2679 :
2680 : ! append
2681 0 : start(:) = 1
2682 0 : counter(:) = dims
2683 0 : counter(ndim) = 1
2684 0 : do i = 1, size(arr, ndim)
2685 0 : start(ndim) = dims(ndim) + i
2686 0 : call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
2687 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
2688 : end do
2689 : else
2690 : ! open file
2691 0 : if (inetcdf4) then
2692 0 : call check(nf90_create(trim(filename), NF90_NETCDF4, ncid))
2693 : else
2694 0 : if (LargeFile) then
2695 0 : call check(nf90_create(trim(filename), NF90_64BIT_OFFSET, ncid, chunksize = buffersize))
2696 : else
2697 0 : call check(nf90_create(trim(filename), NF90_CLOBBER, ncid, chunksize = buffersize))
2698 : end if
2699 : end if
2700 :
2701 : ! define dims
2702 0 : dims = shape(arr)
2703 0 : do i = 1, ndim - 1
2704 0 : call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2705 : end do
2706 : ! define dim time
2707 0 : call check(nf90_def_dim(ncid, 'time', NF90_UNLIMITED, dimid(ndim)))
2708 :
2709 : ! define dim variables
2710 0 : do i = 1, ndim - 1
2711 0 : if (inetcdf4) then
2712 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2713 : else
2714 0 : call check(nf90_def_var(ncid, dnames(i), NF90_INT, dimid(i), varid(i)))
2715 : end if
2716 : end do
2717 : ! define time variable
2718 0 : if (inetcdf4) then
2719 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
2720 : else
2721 0 : call check(nf90_def_var(ncid, 'time', NF90_INT, dimid(ndim), varid(ndim)))
2722 : end if
2723 :
2724 : ! define variable
2725 0 : if (inetcdf4) then
2726 0 : chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
2727 0 : chunksizes(ndim) = 1
2728 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 1), &
2729 0 : chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2730 : else
2731 0 : call check(nf90_def_var(ncid, 'var', NF90_INT, dimid, varid(ndim + 1)))
2732 : end if
2733 :
2734 : ! end define mode
2735 0 : call check(nf90_enddef(ncid))
2736 :
2737 : ! write dimensions
2738 0 : do i = 1, ndim - 1
2739 0 : call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2740 : end do
2741 :
2742 : ! write time and variable
2743 0 : start(:) = 1
2744 0 : counter(:) = dims
2745 0 : counter(ndim) = 1
2746 0 : do i = 1, dims(ndim)
2747 0 : start(ndim) = i
2748 0 : call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
2749 0 : call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
2750 : end do
2751 : end if
2752 :
2753 : ! close netcdf file
2754 0 : call check(nf90_close(ncid))
2755 :
2756 0 : end subroutine dump_netcdf_5d_i4
2757 :
2758 :
2759 : ! ------------------------------------------------------------------
2760 :
2761 :
2762 0 : subroutine var2nc_1d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
2763 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
2764 : !
2765 : implicit none
2766 : !
2767 : integer(i4), parameter :: ndim_const = 1
2768 : integer(i4) :: ndim
2769 : ! input variables
2770 : character(len = *), intent(in) :: f_name
2771 : integer(i4), dimension(:), intent(in) :: arr
2772 : character(len = *), intent(in) :: v_name
2773 : character(len = *), dimension(:), intent(in) :: dnames
2774 : ! attributes
2775 : integer(i4), optional, intent(in) :: dim_unlimited
2776 : character(len = *), optional, intent(in) :: long_name
2777 : character(len = *), optional, intent(in) :: units
2778 : character(256), dimension(:, :), optional, intent(in) :: attributes
2779 : integer(i4), optional, intent(in) :: missing_value
2780 : logical, optional, intent(in) :: create
2781 : integer(i4), optional, intent(inout) :: ncid
2782 : integer(i4), optional, intent(in) :: nrec
2783 : ! local variables
2784 : logical :: create_loc
2785 : character(256) :: dummy_name
2786 : integer(i4) :: deflate
2787 0 : integer(i4), dimension(:), allocatable :: chunksizes
2788 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
2789 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
2790 : integer(i4) :: idim ! read dimension on append
2791 : integer(i4) :: d_unlimit ! index of unlimited dimension
2792 : integer(i4) :: u_dimid
2793 : integer(i4) :: u_len ! length of unlimited dimension
2794 : integer(i4) :: f_handle
2795 0 : integer(i4), dimension(:), allocatable :: dims
2796 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
2797 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
2798 : integer(i4) :: i ! loop indices
2799 0 : integer(i4), dimension(:), allocatable :: dummy_count
2800 : integer(i4), dimension(1) :: dummy ! dummy read
2801 : logical :: openfile ! tmp logical
2802 : !
2803 0 : ndim = size(dnames, 1)
2804 : ! consistency checks
2805 0 : d_unlimit = 0_i4
2806 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
2807 0 : if ((size(dnames, 1) .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
2808 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
2809 0 : stop '***ERROR see StdOut'
2810 : end if
2811 0 : if (size(dnames, 1) .gt. ndim_const + 1) then
2812 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
2813 0 : stop '***ERROR see StdOut'
2814 : end if
2815 0 : allocate(chunksizes(ndim))
2816 0 : allocate(start(ndim))
2817 0 : allocate(counter(ndim))
2818 0 : allocate(dims(ndim))
2819 0 : allocate(dimid(ndim))
2820 0 : allocate(varid(1 + ndim))
2821 0 : allocate(dummy_count(ndim))
2822 : ! initialize
2823 0 : deflate = 1
2824 0 : if (ndim .gt. ndim_const) then
2825 0 : chunksizes = (/ size(arr, 1), 1 /)
2826 0 : dims(1 : ndim - 1) = shape(arr)
2827 0 : dims(ndim) = 1
2828 : else
2829 0 : chunksizes = (/ size(arr, 1) /)
2830 0 : dims(1 : ndim_const) = shape(arr)
2831 : end if
2832 0 : start(:) = 1
2833 0 : counter(:) = dims
2834 0 : dummy = nf90_fill_int
2835 0 : dummy_count = 1
2836 : ! open the netcdf file
2837 0 : if (present(ncid)) then
2838 0 : if (ncid < 0_i4) then
2839 : openfile = .true.
2840 : else
2841 0 : openfile = .false.
2842 0 : f_handle = ncid
2843 : end if
2844 : else
2845 : openfile = .true.
2846 : end if
2847 : if (openfile) then
2848 0 : create_loc = .false.
2849 0 : if (present(create)) create_loc = create
2850 0 : f_handle = open_netcdf(f_name, create = create_loc)
2851 : end if
2852 : ! check whether variable exists
2853 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
2854 : ! append
2855 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
2856 0 : if (idim .ne. ndim) stop "var2nc_1d_i4: number of variable dimensions /= number of file variable dimensions."
2857 : ! check unlimited dimension
2858 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
2859 0 : if (u_dimid .eq. -1) stop 'var2nc_1d_i4: cannot append, no unlimited dimension defined'
2860 : ! check for unlimited dimension
2861 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_1d_i4: unlimited dimension not specified correctly'
2862 0 : if (present(nrec)) then
2863 0 : start(d_unlimit) = nrec
2864 : else
2865 : ! get length of unlimited dimension
2866 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
2867 : ! adapt start, that is find last written chunk
2868 0 : do i = u_len, 1, -1
2869 0 : if (dummy(1) /= nf90_fill_int) exit
2870 0 : start(d_unlimit) = i
2871 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
2872 : end do
2873 0 : start(d_unlimit) = start(d_unlimit) + 1
2874 : end if
2875 : else
2876 : ! define dimension
2877 0 : do i = 1, ndim
2878 : ! check whether dimension exists
2879 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
2880 : ! create dimension
2881 0 : if (i .eq. d_unlimit) then
2882 : ! define unlimited dimension
2883 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
2884 : else
2885 : ! define limited dimension
2886 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
2887 : end if
2888 : end if
2889 : end do
2890 : ! define variable
2891 : call check(nf90_def_var(f_handle, v_name, NF90_INT, dimid, varid(ndim + 1), &
2892 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
2893 : !
2894 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
2895 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
2896 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
2897 0 : if (present(attributes)) then
2898 0 : do i = 1, size(attributes, dim = 1)
2899 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
2900 : ! write number
2901 0 : read(attributes(i, 2), '(I6)') dummy(1)
2902 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
2903 0 : trim(attributes(i, 1)), dummy(1)))
2904 : else
2905 : ! write string
2906 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
2907 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
2908 : end if
2909 : end do
2910 : end if
2911 : ! end definition
2912 0 : call check(nf90_enddef(f_handle))
2913 : end if
2914 : ! inquire dimensions
2915 0 : do i = 1, ndim_const
2916 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
2917 0 : if (trim(dummy_name) .ne. dnames(i)) &
2918 0 : stop "var2nc_1d_i4: dimension name problem."
2919 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
2920 0 : stop "var2nc_1d_i4: variable dimension /= file variable dimension."
2921 : enddo
2922 : ! write time and variable
2923 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
2924 : ! close netcdf_dataset
2925 0 : if (present(ncid)) then
2926 0 : if (ncid < 0_i4) ncid = f_handle
2927 : else
2928 0 : call close_netcdf(f_handle)
2929 : end if
2930 : !
2931 0 : end subroutine var2nc_1d_i4
2932 :
2933 0 : subroutine var2nc_1d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
2934 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
2935 : !
2936 : implicit none
2937 : !
2938 : integer(i4), parameter :: ndim_const = 1
2939 : integer(i4) :: ndim
2940 : ! input variables
2941 : character(len = *), intent(in) :: f_name
2942 : real(sp), dimension(:), intent(in) :: arr
2943 : character(len = *), dimension(:), intent(in) :: dnames
2944 : character(len = *), intent(in) :: v_name
2945 : ! attributes
2946 : integer(i4), optional, intent(in) :: dim_unlimited
2947 : character(len = *), optional, intent(in) :: long_name
2948 : character(len = *), optional, intent(in) :: units
2949 : character(256), dimension(:, :), optional, intent(in) :: attributes
2950 : real(sp), optional, intent(in) :: missing_value
2951 : logical, optional, intent(in) :: create
2952 : integer(i4), optional, intent(inout) :: ncid
2953 : integer(i4), optional, intent(in) :: nrec
2954 : ! local variables
2955 : logical :: create_loc
2956 : character(256) :: dummy_name
2957 : integer(i4) :: deflate
2958 0 : integer(i4), dimension(:), allocatable :: chunksizes
2959 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
2960 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
2961 : integer(i4) :: idim ! read dimension on append
2962 : integer(i4) :: d_unlimit ! index of unlimited dimension
2963 : integer(i4) :: u_dimid
2964 : integer(i4) :: u_len ! length of unlimited dimension
2965 : integer(i4) :: f_handle
2966 0 : integer(i4), dimension(:), allocatable :: dims
2967 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
2968 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
2969 : integer(i4) :: i ! loop indices
2970 0 : integer(i4), dimension(:), allocatable :: dummy_count
2971 0 : real(sp), dimension(1) :: dummy ! dummy read
2972 : logical :: openfile ! tmp logical
2973 : !
2974 0 : ndim = size(dnames, 1)
2975 : ! consistency checks
2976 0 : d_unlimit = 0_i4
2977 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
2978 0 : if ((size(dnames, 1) .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
2979 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
2980 0 : stop '***ERROR see StdOut'
2981 : end if
2982 0 : if (size(dnames, 1) .gt. ndim_const + 1) then
2983 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
2984 0 : stop '***ERROR see StdOut'
2985 : end if
2986 0 : allocate(chunksizes(ndim))
2987 0 : allocate(start(ndim))
2988 0 : allocate(counter(ndim))
2989 0 : allocate(dims(ndim))
2990 0 : allocate(dimid(ndim))
2991 0 : allocate(varid(1 + ndim))
2992 0 : allocate(dummy_count(ndim))
2993 : ! initialize
2994 0 : deflate = 1
2995 0 : if (ndim .gt. ndim_const) then
2996 0 : chunksizes = (/ size(arr, 1), 1 /)
2997 0 : dims(1 : ndim - 1) = shape(arr)
2998 0 : dims(ndim) = 1
2999 : else
3000 0 : chunksizes = (/ size(arr, 1) /)
3001 0 : dims(1 : ndim_const) = shape(arr)
3002 : end if
3003 0 : start(:) = 1
3004 0 : counter(:) = dims
3005 0 : dummy_count = 1
3006 0 : dummy = nf90_fill_float
3007 : ! open the netcdf file
3008 0 : if (present(ncid)) then
3009 0 : if (ncid < 0_i4) then
3010 : openfile = .true.
3011 : else
3012 0 : openfile = .false.
3013 0 : f_handle = ncid
3014 : end if
3015 : else
3016 : openfile = .true.
3017 : end if
3018 : if (openfile) then
3019 0 : create_loc = .false.
3020 0 : if (present(create)) create_loc = create
3021 0 : f_handle = open_netcdf(f_name, create = create_loc)
3022 : end if
3023 : ! check whether variable exists
3024 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3025 : ! append
3026 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3027 0 : if (idim .ne. ndim) stop "var2nc_1d_sp: number of variable dimensions /= number of file variable dimensions."
3028 : ! check unlimited dimension
3029 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
3030 0 : if (u_dimid .eq. -1) stop 'var2nc_1d_sp: cannot append, no unlimited dimension defined'
3031 : ! check for unlimited dimension
3032 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_1d_sp: unlimited dimension not specified correctly'
3033 0 : if (present(nrec)) then
3034 0 : start(d_unlimit) = nrec
3035 : else
3036 : ! get length of unlimited dimension
3037 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3038 : ! adapt start, that is find last written chunk
3039 0 : do i = u_len, 1, -1
3040 0 : if (ne(dummy(1), nf90_fill_float)) exit
3041 0 : start(d_unlimit) = i
3042 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3043 : end do
3044 0 : start(d_unlimit) = start(d_unlimit) + 1
3045 : end if
3046 : else
3047 : ! define dimension
3048 0 : do i = 1, ndim
3049 : ! check whether dimension exists
3050 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3051 : ! create dimension
3052 0 : if (i .eq. d_unlimit) then
3053 : ! define unlimited dimension
3054 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
3055 : else
3056 : ! define limited dimension
3057 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
3058 : end if
3059 : end if
3060 : end do
3061 : ! define variable
3062 : call check(nf90_def_var(f_handle, v_name, NF90_FLOAT, dimid, varid(ndim + 1), &
3063 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3064 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
3065 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
3066 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
3067 0 : if (present(attributes)) then
3068 0 : do i = 1, size(attributes, dim = 1)
3069 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
3070 : ! write number
3071 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
3072 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3073 0 : trim(attributes(i, 1)), dummy(1)))
3074 : else
3075 : ! write string
3076 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3077 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
3078 : end if
3079 : end do
3080 : end if
3081 : ! end definition
3082 0 : call check(nf90_enddef(f_handle))
3083 : end if
3084 : ! inquire dimensions
3085 0 : do i = 1, ndim_const
3086 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3087 0 : if (trim(dummy_name) .ne. dnames(i)) &
3088 0 : stop "var2nc_1d_sp: dimension name problem."
3089 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3090 0 : stop "var2nc_1d_sp: variable dimension /= file variable dimension."
3091 : enddo
3092 : ! write time and variable
3093 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3094 : ! close netcdf_dataset
3095 0 : if (present(ncid)) then
3096 0 : if (ncid < 0_i4) ncid = f_handle
3097 : else
3098 0 : call close_netcdf(f_handle)
3099 : end if
3100 : !
3101 0 : end subroutine var2nc_1d_sp
3102 :
3103 0 : subroutine var2nc_1d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
3104 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
3105 : !
3106 : implicit none
3107 : !
3108 : integer(i4), parameter :: ndim_const = 1
3109 : integer(i4) :: ndim
3110 : ! input variables
3111 : character(len = *), intent(in) :: f_name
3112 : real(dp), dimension(:), intent(in) :: arr
3113 : character(len = *), intent(in) :: v_name
3114 : character(len = *), dimension(:), intent(in) :: dnames
3115 : ! attributes
3116 : integer(i4), optional, intent(in) :: dim_unlimited
3117 : character(len = *), optional, intent(in) :: long_name
3118 : character(len = *), optional, intent(in) :: units
3119 : character(256), dimension(:, :), optional, intent(in) :: attributes
3120 : real(dp), optional, intent(in) :: missing_value
3121 : logical, optional, intent(in) :: create
3122 : integer(i4), optional, intent(inout) :: ncid
3123 : integer(i4), optional, intent(in) :: nrec
3124 : ! local variables
3125 : logical :: create_loc
3126 : character(256) :: dummy_name
3127 : integer(i4) :: deflate
3128 0 : integer(i4), dimension(:), allocatable :: chunksizes
3129 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
3130 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
3131 : integer(i4) :: idim ! read dimension on append
3132 : integer(i4) :: d_unlimit ! index of unlimited dimension
3133 : integer(i4) :: u_dimid
3134 : integer(i4) :: u_len ! length of unlimited dimension
3135 : integer(i4) :: f_handle
3136 0 : integer(i4), dimension(:), allocatable :: dims
3137 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3138 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3139 : integer(i4) :: i ! loop indices
3140 0 : integer(i4), dimension(:), allocatable :: dummy_count
3141 0 : real(dp), dimension(1) :: dummy ! dummy read
3142 : logical :: openfile ! tmp logical
3143 : !
3144 0 : ndim = size(dnames, 1)
3145 : ! consistency checks
3146 0 : d_unlimit = 0_i4
3147 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
3148 0 : if ((size(dnames, 1) .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3149 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3150 0 : stop '***ERROR see StdOut'
3151 : end if
3152 0 : if (size(dnames, 1) .gt. ndim_const + 1) then
3153 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3154 0 : stop '***ERROR see StdOut'
3155 : end if
3156 0 : allocate(chunksizes(ndim))
3157 0 : allocate(start(ndim))
3158 0 : allocate(counter(ndim))
3159 0 : allocate(dims(ndim))
3160 0 : allocate(dimid(ndim))
3161 0 : allocate(varid(1 + ndim))
3162 0 : allocate(dummy_count(ndim))
3163 : ! initialize
3164 0 : deflate = 1
3165 0 : if (ndim .gt. ndim_const) then
3166 0 : chunksizes = (/ size(arr, 1), 1 /)
3167 0 : dims(1 : ndim - 1) = shape(arr)
3168 0 : dims(ndim) = 1
3169 : else
3170 0 : chunksizes = (/ size(arr, 1) /)
3171 0 : dims(1 : ndim_const) = shape(arr)
3172 : end if
3173 0 : start(:) = 1
3174 0 : counter(:) = dims
3175 0 : dummy_count = 1
3176 0 : dummy = nf90_fill_double
3177 : ! open the netcdf file
3178 0 : if (present(ncid)) then
3179 0 : if (ncid < 0_i4) then
3180 : openfile = .true.
3181 : else
3182 0 : openfile = .false.
3183 0 : f_handle = ncid
3184 : end if
3185 : else
3186 : openfile = .true.
3187 : end if
3188 : if (openfile) then
3189 0 : create_loc = .false.
3190 0 : if (present(create)) create_loc = create
3191 0 : f_handle = open_netcdf(f_name, create = create_loc)
3192 : end if
3193 : ! check whether variable exists
3194 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3195 : ! append
3196 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3197 0 : if (idim .ne. ndim) stop "var2nc_1d_dp: number of variable dimensions /= number of file variable dimensions."
3198 : ! check unlimited dimension
3199 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
3200 0 : if (u_dimid .eq. -1) stop 'var2nc_1d_dp: cannot append, no unlimited dimension defined'
3201 : ! check for unlimited dimension
3202 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_1d_dp: unlimited dimension not specified correctly'
3203 0 : if (present(nrec)) then
3204 0 : start(d_unlimit) = nrec
3205 : else
3206 : ! get length of unlimited dimension
3207 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3208 : ! adapt start, that is find last written chunk
3209 0 : do i = u_len, 1, -1
3210 0 : if (ne(dummy(1), nf90_fill_double)) exit
3211 0 : start(d_unlimit) = i
3212 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3213 : end do
3214 0 : start(d_unlimit) = start(d_unlimit) + 1
3215 : end if
3216 : else
3217 : ! define dimension
3218 0 : do i = 1, ndim
3219 : ! check whether dimension exists
3220 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3221 : ! create dimension
3222 0 : if (i .eq. d_unlimit) then
3223 : ! define unlimited dimension
3224 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
3225 : else
3226 : ! define limited dimension
3227 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
3228 : end if
3229 : end if
3230 : end do
3231 : ! define variable
3232 : call check(nf90_def_var(f_handle, v_name, NF90_DOUBLE, dimid, varid(ndim + 1), &
3233 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3234 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
3235 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
3236 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
3237 0 : if (present(attributes)) then
3238 0 : do i = 1, size(attributes, dim = 1)
3239 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
3240 : ! write number
3241 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
3242 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3243 0 : trim(attributes(i, 1)), dummy(1)))
3244 : else
3245 : ! write string
3246 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3247 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
3248 : end if
3249 : end do
3250 : end if
3251 : ! end definition
3252 0 : call check(nf90_enddef(f_handle))
3253 : end if
3254 : ! inquire dimensions
3255 0 : do i = 1, ndim_const
3256 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3257 0 : if (trim(dummy_name) .ne. dnames(i)) &
3258 0 : stop "var2nc_1d_dp: dimension name problem."
3259 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3260 0 : stop "var2nc_1d_dp: variable dimension /= file variable dimension."
3261 : enddo
3262 : ! write time and variable
3263 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3264 : ! close netcdf_dataset
3265 0 : if (present(ncid)) then
3266 0 : if (ncid < 0_i4) ncid = f_handle
3267 : else
3268 0 : call close_netcdf(f_handle)
3269 : end if
3270 : !
3271 0 : end subroutine var2nc_1d_dp
3272 :
3273 0 : subroutine var2nc_2d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
3274 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
3275 : !
3276 : implicit none
3277 : !
3278 : integer(i4), parameter :: ndim_const = 2
3279 : integer(i4) :: ndim
3280 : ! input variables
3281 : character(len = *), intent(in) :: f_name
3282 : integer(i4), dimension(:, :), intent(in) :: arr
3283 : character(len = *), intent(in) :: v_name
3284 : character(len = *), dimension(:), intent(in) :: dnames
3285 : ! optional
3286 : integer(i4), optional, intent(in) :: dim_unlimited
3287 : character(len = *), optional, intent(in) :: long_name
3288 : character(len = *), optional, intent(in) :: units
3289 : integer(i4), optional, intent(in) :: missing_value
3290 : character(256), dimension(:, :), optional, intent(in) :: attributes
3291 : logical, optional, intent(in) :: create
3292 : integer(i4), optional, intent(inout) :: ncid
3293 : integer(i4), optional, intent(in) :: nrec
3294 : ! local variables
3295 : logical :: create_loc
3296 : character(256) :: dummy_name
3297 : integer(i4) :: deflate
3298 0 : integer(i4), dimension(:), allocatable :: chunksizes
3299 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
3300 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
3301 : integer(i4) :: idim ! read dimension on append
3302 : integer(i4) :: f_handle
3303 : integer(i4) :: d_unlimit ! index of unlimited dimension
3304 : integer(i4) :: u_dimid ! dimid of unlimited dimension
3305 : integer(i4) :: u_len ! length of unlimited dimension
3306 0 : integer(i4), dimension(:), allocatable :: dims
3307 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3308 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3309 : integer(i4) :: i ! loop indices
3310 0 : integer(i4), dimension(:), allocatable :: dummy_count
3311 : integer(i4), dimension(1) :: dummy ! dummy read
3312 : logical :: openfile ! tmp logical
3313 : !
3314 0 : ndim = size(dnames, 1)
3315 : ! consistency checks
3316 0 : d_unlimit = 0_i4
3317 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
3318 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3319 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3320 0 : stop '***ERROR see StdOut'
3321 : end if
3322 0 : if (ndim .gt. ndim_const + 1) then
3323 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3324 0 : stop '***ERROR see StdOut'
3325 : end if
3326 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
3327 : (d_unlimit .lt. 0_i4)) then
3328 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
3329 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
3330 0 : stop '***ERROR see StdOut'
3331 : end if
3332 : !
3333 0 : allocate(chunksizes(ndim))
3334 0 : allocate(start(ndim))
3335 0 : allocate(counter(ndim))
3336 0 : allocate(dims(ndim))
3337 0 : allocate(dimid(ndim))
3338 0 : allocate(varid(1 + ndim))
3339 0 : allocate(dummy_count(ndim))
3340 : ! initialize
3341 0 : deflate = 1
3342 0 : if (ndim .gt. ndim_const) then
3343 0 : chunksizes = (/ size(arr, 1), size(arr, 2), 1 /)
3344 0 : dims(1 : ndim - 1) = shape(arr)
3345 0 : dims(ndim) = 1
3346 : else
3347 0 : chunksizes = (/ size(arr, 1), size(arr, 2) /)
3348 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
3349 0 : dims(1 : ndim_const) = shape(arr)
3350 : end if
3351 0 : start(:) = 1_i4
3352 0 : counter(:) = dims
3353 0 : dummy_count = 1_i4
3354 0 : dummy = nf90_fill_int
3355 : ! open the netcdf file
3356 0 : if (present(ncid)) then
3357 0 : if (ncid < 0_i4) then
3358 : openfile = .true.
3359 : else
3360 0 : openfile = .false.
3361 0 : f_handle = ncid
3362 : end if
3363 : else
3364 : openfile = .true.
3365 : end if
3366 : if (openfile) then
3367 0 : create_loc = .false.
3368 0 : if (present(create)) create_loc = create
3369 0 : f_handle = open_netcdf(f_name, create = create_loc)
3370 : end if
3371 : ! check whether variable exists
3372 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3373 : ! append
3374 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3375 : ! consistency checks
3376 0 : if (idim .ne. ndim) stop "var2nc_2d_i4: number of variable dimensions /= number of file variable dimensions."
3377 : ! check unlimited dimension
3378 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
3379 0 : if (u_dimid .eq. -1) stop 'var2nc_2d_i4: cannot append, no unlimited dimension defined'
3380 : ! check for unlimited dimension
3381 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_2d_i4: unlimited dimension not specified correctly'
3382 0 : if (present(nrec)) then
3383 0 : start(d_unlimit) = nrec
3384 : else
3385 : ! get length of unlimited dimension
3386 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3387 : ! adapt start, that is find last written chunk
3388 0 : do i = u_len, 1, -1
3389 0 : if (dummy(1) /= nf90_fill_int) exit
3390 0 : start(d_unlimit) = i
3391 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3392 : end do
3393 0 : start(d_unlimit) = start(d_unlimit) + 1
3394 : end if
3395 : else
3396 : ! define dimensions
3397 0 : do i = 1, ndim
3398 : ! check whether dimension exists
3399 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3400 : ! create dimension
3401 0 : if (i .eq. d_unlimit) then
3402 : ! define unlimited dimension
3403 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
3404 : else
3405 : ! define limited dimension
3406 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
3407 : end if
3408 : end if
3409 : end do
3410 : ! define variable
3411 0 : call check(nf90_def_var(f_handle, v_name, NF90_INT, dimid, varid(ndim + 1), &
3412 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3413 : ! add attributes
3414 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
3415 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
3416 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
3417 0 : if (present(attributes)) then
3418 0 : do i = 1, size(attributes, dim = 1)
3419 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
3420 : ! write number
3421 0 : read(attributes(i, 2), '(I6)') dummy(1)
3422 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3423 0 : trim(attributes(i, 1)), dummy(1)))
3424 : else
3425 : ! write string
3426 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3427 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
3428 : end if
3429 : end do
3430 : end if
3431 : ! end definition
3432 0 : call check(nf90_enddef(f_handle))
3433 : end if
3434 : ! check dimensions before writing
3435 0 : do i = 1, ndim_const
3436 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3437 0 : if (trim(dummy_name) .ne. dnames(i)) &
3438 0 : stop "var2nc_2d_i4: dimension name problem."
3439 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3440 0 : stop "var2nc_2d_i4: variable dimension /= file variable dimension."
3441 : end do
3442 : ! write variable
3443 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3444 : ! close netcdf_dataset
3445 0 : if (present(ncid)) then
3446 0 : if (ncid < 0_i4) ncid = f_handle
3447 : else
3448 0 : call close_netcdf(f_handle)
3449 : end if
3450 : !
3451 0 : end subroutine var2nc_2d_i4
3452 :
3453 0 : subroutine var2nc_2d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
3454 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
3455 : !
3456 : implicit none
3457 : !
3458 : integer(i4), parameter :: ndim_const = 2
3459 : integer(i4) :: ndim
3460 : ! input variables
3461 : character(len = *), intent(in) :: f_name
3462 : real(sp), dimension(:, :), intent(in) :: arr
3463 : character(len = *), intent(in) :: v_name
3464 : character(len = *), dimension(:), intent(in) :: dnames
3465 : ! optional
3466 : integer(i4), optional, intent(in) :: dim_unlimited
3467 : character(len = *), optional, intent(in) :: long_name
3468 : character(len = *), optional, intent(in) :: units
3469 : real(sp), optional, intent(in) :: missing_value
3470 : character(256), dimension(:, :), optional, intent(in) :: attributes
3471 : logical, optional, intent(in) :: create
3472 : integer(i4), optional, intent(inout) :: ncid
3473 : integer(i4), optional, intent(in) :: nrec
3474 : ! local variables
3475 : logical :: create_loc
3476 : character(256) :: dummy_name
3477 : integer(i4) :: deflate
3478 0 : integer(i4), dimension(:), allocatable :: chunksizes
3479 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
3480 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
3481 : integer(i4) :: idim ! read dimension on append
3482 : integer(i4) :: f_handle
3483 : integer(i4) :: d_unlimit ! index of unlimited dimension
3484 : integer(i4) :: u_dimid ! dimid of unlimited dimension
3485 : integer(i4) :: u_len ! length of unlimited dimension
3486 0 : integer(i4), dimension(:), allocatable :: dims
3487 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3488 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3489 : integer(i4) :: i ! loop indices
3490 0 : integer(i4), dimension(:), allocatable :: dummy_count
3491 0 : real(sp), dimension(1) :: dummy ! dummy read
3492 : logical :: openfile ! tmp logical
3493 : !
3494 0 : ndim = size(dnames, 1)
3495 : ! consistency checks
3496 0 : d_unlimit = 0_i4
3497 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
3498 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3499 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3500 0 : stop '***ERROR see StdOut'
3501 : end if
3502 0 : if (ndim .gt. ndim_const + 1) then
3503 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3504 0 : stop '***ERROR see StdOut'
3505 : end if
3506 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
3507 : (d_unlimit .lt. 0_i4)) then
3508 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
3509 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
3510 0 : stop '***ERROR see StdOut'
3511 : end if
3512 : !
3513 0 : allocate(chunksizes(ndim))
3514 0 : allocate(start(ndim))
3515 0 : allocate(counter(ndim))
3516 0 : allocate(dims(ndim))
3517 0 : allocate(dimid(ndim))
3518 0 : allocate(varid(1 + ndim))
3519 0 : allocate(dummy_count(ndim))
3520 : ! initialize
3521 0 : deflate = 1
3522 0 : if (ndim .gt. ndim_const) then
3523 0 : chunksizes = (/ size(arr, 1), size(arr, 2), 1 /)
3524 0 : dims(1 : ndim - 1) = shape(arr)
3525 0 : dims(ndim) = 1
3526 : else
3527 0 : chunksizes = (/ size(arr, 1), size(arr, 2) /)
3528 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
3529 0 : dims(1 : ndim_const) = shape(arr)
3530 : end if
3531 0 : start(:) = 1_i4
3532 0 : counter(:) = dims
3533 0 : dummy_count = 1_i4
3534 0 : dummy = nf90_fill_float
3535 : ! open the netcdf file
3536 0 : if (present(ncid)) then
3537 0 : if (ncid < 0_i4) then
3538 : openfile = .true.
3539 : else
3540 0 : openfile = .false.
3541 0 : f_handle = ncid
3542 : end if
3543 : else
3544 : openfile = .true.
3545 : end if
3546 : if (openfile) then
3547 0 : create_loc = .false.
3548 0 : if (present(create)) create_loc = create
3549 0 : f_handle = open_netcdf(f_name, create = create_loc)
3550 : end if
3551 : ! check whether variable exists
3552 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3553 : ! append
3554 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3555 : ! consistency checks
3556 0 : if (idim .ne. ndim) stop "var2nc_2d_sp: number of variable dimensions /= number of file variable dimensions."
3557 : ! check unlimited dimension
3558 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
3559 0 : if (u_dimid .eq. -1) stop 'var2nc_2d_sp: cannot append, no unlimited dimension defined'
3560 : ! check for unlimited dimension
3561 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_2d_sp: unlimited dimension not specified correctly'
3562 0 : if (present(nrec)) then
3563 0 : start(d_unlimit) = nrec
3564 : else
3565 : ! get length of unlimited dimension
3566 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3567 : ! adapt start, that is find last written chunk
3568 0 : do i = u_len, 1, -1
3569 0 : if (ne(dummy(1), nf90_fill_float)) exit
3570 0 : start(d_unlimit) = i
3571 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3572 : end do
3573 0 : start(d_unlimit) = start(d_unlimit) + 1
3574 : end if
3575 : else
3576 : ! define dimensions
3577 0 : do i = 1, ndim
3578 : ! check whether dimension exists
3579 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3580 : ! create dimension
3581 0 : if (i .eq. d_unlimit) then
3582 : ! define unlimited dimension
3583 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
3584 : else
3585 : ! define limited dimension
3586 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
3587 : end if
3588 : end if
3589 : end do
3590 : ! define variable
3591 0 : call check(nf90_def_var(f_handle, v_name, NF90_FLOAT, dimid, varid(ndim + 1), &
3592 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3593 : ! add attributes
3594 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
3595 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
3596 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
3597 0 : if (present(attributes)) then
3598 0 : do i = 1, size(attributes, dim = 1)
3599 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
3600 : ! write number
3601 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
3602 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3603 0 : trim(attributes(i, 1)), dummy(1)))
3604 : else
3605 : ! write string
3606 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3607 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
3608 : end if
3609 : end do
3610 : end if
3611 : ! end definition
3612 0 : call check(nf90_enddef(f_handle))
3613 : end if
3614 : ! check dimensions before writing
3615 0 : do i = 1, ndim_const
3616 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3617 0 : if (trim(dummy_name) .ne. dnames(i)) &
3618 0 : stop "var2nc_2d_sp: dimension name problem."
3619 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3620 0 : stop "var2nc_2d_sp: variable dimension /= file variable dimension."
3621 : end do
3622 : ! write variable
3623 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3624 : ! close netcdf_dataset
3625 0 : if (present(ncid)) then
3626 0 : if (ncid < 0_i4) ncid = f_handle
3627 : else
3628 0 : call close_netcdf(f_handle)
3629 : end if
3630 : !
3631 0 : end subroutine var2nc_2d_sp
3632 :
3633 0 : subroutine var2nc_2d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
3634 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
3635 : !
3636 : implicit none
3637 : !
3638 : integer(i4), parameter :: ndim_const = 2
3639 : integer(i4) :: ndim
3640 : ! input variables
3641 : character(len = *), intent(in) :: f_name
3642 : real(dp), dimension(:, :), intent(in) :: arr
3643 : character(len = *), intent(in) :: v_name
3644 : character(len = *), dimension(:), intent(in) :: dnames
3645 : ! optional
3646 : integer(i4), optional, intent(in) :: dim_unlimited
3647 : character(len = *), optional, intent(in) :: long_name
3648 : character(len = *), optional, intent(in) :: units
3649 : real(dp), optional, intent(in) :: missing_value
3650 : character(256), dimension(:, :), optional, intent(in) :: attributes
3651 : logical, optional, intent(in) :: create
3652 : integer(i4), optional, intent(inout) :: ncid
3653 : integer(i4), optional, intent(in) :: nrec
3654 : ! local variables
3655 : logical :: create_loc
3656 : character(256) :: dummy_name
3657 : integer(i4) :: deflate
3658 0 : integer(i4), dimension(:), allocatable :: chunksizes
3659 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
3660 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
3661 : integer(i4) :: idim ! read dimension on append
3662 : integer(i4) :: f_handle
3663 : integer(i4) :: d_unlimit ! index of unlimited dimension
3664 : integer(i4) :: u_dimid ! dimid of unlimited dimension
3665 : integer(i4) :: u_len ! length of unlimited dimension
3666 0 : integer(i4), dimension(:), allocatable :: dims
3667 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3668 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3669 : integer(i4) :: i ! loop indices
3670 0 : integer(i4), dimension(:), allocatable :: dummy_count
3671 0 : real(dp), dimension(1) :: dummy ! dummy read
3672 : logical :: openfile ! tmp logical
3673 : !
3674 0 : ndim = size(dnames, 1)
3675 : ! consistency checks
3676 0 : d_unlimit = 0_i4
3677 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
3678 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3679 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3680 0 : stop '***ERROR see StdOut'
3681 : end if
3682 0 : if (ndim .gt. ndim_const + 1) then
3683 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3684 0 : stop '***ERROR see StdOut'
3685 : end if
3686 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
3687 : (d_unlimit .lt. 0_i4)) then
3688 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
3689 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
3690 0 : stop '***ERROR see StdOut'
3691 : end if
3692 : !
3693 0 : allocate(chunksizes(ndim))
3694 0 : allocate(start(ndim))
3695 0 : allocate(counter(ndim))
3696 0 : allocate(dims(ndim))
3697 0 : allocate(dimid(ndim))
3698 0 : allocate(varid(1 + ndim))
3699 0 : allocate(dummy_count(ndim))
3700 : ! initialize
3701 0 : deflate = 1
3702 0 : if (ndim .gt. ndim_const) then
3703 0 : chunksizes = (/ size(arr, 1), size(arr, 2), 1 /)
3704 0 : dims(1 : ndim - 1) = shape(arr)
3705 0 : dims(ndim) = 1
3706 : else
3707 0 : chunksizes = (/ size(arr, 1), size(arr, 2) /)
3708 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
3709 0 : dims(1 : ndim_const) = shape(arr)
3710 : end if
3711 0 : start(:) = 1_i4
3712 0 : counter(:) = dims
3713 0 : dummy_count = 1
3714 0 : dummy = nf90_fill_double
3715 : ! open the netcdf file
3716 0 : if (present(ncid)) then
3717 0 : if (ncid < 0_i4) then
3718 : openfile = .true.
3719 : else
3720 0 : openfile = .false.
3721 0 : f_handle = ncid
3722 : end if
3723 : else
3724 : openfile = .true.
3725 : end if
3726 : if (openfile) then
3727 0 : create_loc = .false.
3728 0 : if (present(create)) create_loc = create
3729 0 : f_handle = open_netcdf(f_name, create = create_loc)
3730 : end if
3731 : ! check whether variable exists
3732 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3733 : ! append
3734 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3735 : ! consistency checks
3736 0 : if (idim .ne. ndim) stop "var2nc_2d_dp: number of variable dimensions /= number of file variable dimensions."
3737 : ! check unlimited dimension
3738 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
3739 0 : if (u_dimid .eq. -1) stop 'var2nc_2d_dp: cannot append, no unlimited dimension defined'
3740 : ! check for unlimited dimension
3741 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_2d_dp: unlimited dimension not specified correctly'
3742 0 : if (present(nrec)) then
3743 0 : start(d_unlimit) = nrec
3744 : else
3745 : ! get length of unlimited dimension
3746 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3747 : ! adapt start, that is find last written chunk
3748 0 : do i = u_len, 1, -1
3749 0 : if (ne(dummy(1), nf90_fill_double)) exit
3750 0 : start(d_unlimit) = i
3751 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3752 : end do
3753 0 : start(d_unlimit) = start(d_unlimit) + 1
3754 : end if
3755 : else
3756 : ! define dimensions
3757 0 : do i = 1, ndim
3758 : ! check whether dimension exists
3759 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3760 : ! create dimension
3761 0 : if (i .eq. d_unlimit) then
3762 : ! define unlimited dimension
3763 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
3764 : else
3765 : ! define limited dimension
3766 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
3767 : end if
3768 : end if
3769 : end do
3770 : ! define variable
3771 0 : call check(nf90_def_var(f_handle, v_name, NF90_DOUBLE, dimid, varid(ndim + 1), &
3772 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3773 : ! add attributes
3774 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
3775 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
3776 0 : if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
3777 0 : if (present(attributes)) then
3778 0 : do i = 1, size(attributes, dim = 1)
3779 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
3780 : ! write number
3781 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
3782 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3783 0 : trim(attributes(i, 1)), dummy(1)))
3784 : else
3785 : ! write string
3786 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3787 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
3788 : end if
3789 : end do
3790 : end if
3791 : ! end definition
3792 0 : call check(nf90_enddef(f_handle))
3793 : end if
3794 : ! check dimensions before writing
3795 0 : do i = 1, ndim_const
3796 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3797 0 : if (trim(dummy_name) .ne. dnames(i)) &
3798 0 : stop "var2nc_2d_dp: dimension name problem."
3799 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3800 0 : stop "var2nc_2d_dp: variable dimension /= file variable dimension."
3801 : end do
3802 : ! write variable
3803 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3804 : ! close netcdf_dataset
3805 0 : if (present(ncid)) then
3806 0 : if (ncid < 0_i4) ncid = f_handle
3807 : else
3808 0 : call close_netcdf(f_handle)
3809 : end if
3810 : !
3811 0 : end subroutine var2nc_2d_dp
3812 :
3813 0 : subroutine var2nc_3d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
3814 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
3815 : !
3816 : implicit none
3817 : !
3818 : integer(i4), parameter :: ndim_const = 3
3819 : integer(i4) :: ndim
3820 : ! input variables
3821 : character(len = *), intent(in) :: f_name
3822 : integer(i4), dimension(:, :, :), intent(in) :: arr
3823 : character(len = *), intent(in) :: v_name
3824 : character(len = *), dimension(:), intent(in) :: dnames
3825 : ! optional
3826 : integer(i4), optional, intent(in) :: dim_unlimited
3827 : character(len = *), optional, intent(in) :: long_name
3828 : character(len = *), optional, intent(in) :: units
3829 : integer(i4), optional, intent(in) :: missing_value
3830 : character(256), dimension(:, :), optional, intent(in) :: attributes
3831 : logical, optional, intent(in) :: create
3832 : integer(i4), optional, intent(inout) :: ncid
3833 : integer(i4), optional, intent(in) :: nrec
3834 : ! local variables
3835 : logical :: create_loc
3836 : character(256) :: dummy_name
3837 : integer(i4) :: deflate
3838 0 : integer(i4), dimension(:), allocatable :: chunksizes
3839 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
3840 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
3841 : integer(i4) :: idim ! read dimension on append
3842 : integer(i4) :: f_handle
3843 : integer(i4) :: d_unlimit ! index of unlimited dimension
3844 : integer(i4) :: u_dimid ! dimid of unlimited dimension
3845 : integer(i4) :: u_len ! length of unlimited dimension
3846 0 : integer(i4), dimension(:), allocatable :: dims
3847 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3848 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3849 : integer(i4) :: i ! loop indices
3850 0 : integer(i4), dimension(:), allocatable :: dummy_count
3851 : integer(i4), dimension(1) :: dummy ! dummy read
3852 : logical :: openfile ! tmp logical
3853 : !
3854 0 : ndim = size(dnames, 1)
3855 : ! consistency checks
3856 0 : d_unlimit = 0_i4
3857 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
3858 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3859 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3860 0 : stop '***ERROR see StdOut'
3861 : end if
3862 0 : if (ndim .gt. ndim_const + 1) then
3863 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3864 0 : stop '***ERROR see StdOut'
3865 : end if
3866 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
3867 : (d_unlimit .lt. 0_i4)) then
3868 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
3869 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
3870 0 : stop '***ERROR see StdOut'
3871 : end if
3872 : !
3873 0 : allocate(chunksizes(ndim))
3874 0 : allocate(start(ndim))
3875 0 : allocate(counter(ndim))
3876 0 : allocate(dims(ndim))
3877 0 : allocate(dimid(ndim))
3878 0 : allocate(varid(1 + ndim))
3879 0 : allocate(dummy_count(ndim))
3880 : ! initialize
3881 0 : deflate = 1
3882 0 : if (ndim .gt. ndim_const) then
3883 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), 1 /)
3884 0 : dims(1 : ndim - 1) = shape(arr)
3885 0 : dims(ndim) = 1
3886 : else
3887 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3) /)
3888 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
3889 0 : dims(1 : ndim_const) = shape(arr)
3890 : end if
3891 0 : start(:) = 1_i4
3892 0 : counter(:) = dims
3893 0 : dummy_count = 1_i4
3894 0 : dummy = nf90_fill_int
3895 : ! open the netcdf file
3896 0 : if (present(ncid)) then
3897 0 : if (ncid < 0_i4) then
3898 : openfile = .true.
3899 : else
3900 0 : openfile = .false.
3901 0 : f_handle = ncid
3902 : end if
3903 : else
3904 : openfile = .true.
3905 : end if
3906 : if (openfile) then
3907 0 : create_loc = .false.
3908 0 : if (present(create)) create_loc = create
3909 0 : f_handle = open_netcdf(f_name, create = create_loc)
3910 : end if
3911 : ! check whether variable exists
3912 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3913 : ! append
3914 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3915 : ! consistency checks
3916 0 : if (idim .ne. ndim) stop "var2nc_3d_i4: number of variable dimensions /= number of file variable dimensions."
3917 : ! check unlimited dimension
3918 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
3919 0 : if (u_dimid .eq. -1) stop 'var2nc_3d_i4: cannot append, no unlimited dimension defined'
3920 : ! check for unlimited dimension
3921 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_3d_i4: unlimited dimension not specified correctly'
3922 0 : if (present(nrec)) then
3923 0 : start(d_unlimit) = nrec
3924 : else
3925 : ! get length of unlimited dimension
3926 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3927 : ! adapt start, that is find last written chunk
3928 0 : do i = u_len, 1, -1
3929 0 : if (dummy(1) /= nf90_fill_int) exit
3930 0 : start(d_unlimit) = i
3931 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3932 : end do
3933 0 : start(d_unlimit) = start(d_unlimit) + 1
3934 : end if
3935 : else
3936 : ! define dimensions
3937 0 : do i = 1, ndim
3938 : ! check whether dimension exists
3939 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3940 : ! create dimension
3941 0 : if (i .eq. d_unlimit) then
3942 : ! define unlimited dimension
3943 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
3944 : else
3945 : ! define limited dimension
3946 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
3947 : end if
3948 : end if
3949 : end do
3950 : ! define variable
3951 0 : call check(nf90_def_var(f_handle, v_name, NF90_INT, dimid, varid(ndim + 1), &
3952 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3953 : ! add attributes
3954 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
3955 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
3956 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
3957 0 : if (present(attributes)) then
3958 0 : do i = 1, size(attributes, dim = 1)
3959 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
3960 : ! write number
3961 0 : read(attributes(i, 2), '(I6)') dummy(1)
3962 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3963 0 : trim(attributes(i, 1)), dummy(1)))
3964 : else
3965 : ! write string
3966 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
3967 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
3968 : end if
3969 : end do
3970 : end if
3971 : ! end definition
3972 0 : call check(nf90_enddef(f_handle))
3973 : end if
3974 : ! check dimensions before writing
3975 0 : do i = 1, ndim_const
3976 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3977 0 : if (trim(dummy_name) .ne. dnames(i)) &
3978 0 : stop "var2nc_3d_i4: dimension name problem."
3979 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3980 0 : stop "var2nc_3d_i4: variable dimension /= file variable dimension."
3981 : end do
3982 : ! write variable
3983 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3984 : ! close netcdf_dataset
3985 0 : if (present(ncid)) then
3986 0 : if (ncid < 0_i4) ncid = f_handle
3987 : else
3988 0 : call close_netcdf(f_handle)
3989 : end if
3990 : !
3991 0 : end subroutine var2nc_3d_i4
3992 :
3993 0 : subroutine var2nc_3d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
3994 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
3995 : !
3996 : implicit none
3997 : !
3998 : integer(i4), parameter :: ndim_const = 3
3999 : integer(i4) :: ndim
4000 : ! input variables
4001 : character(len = *), intent(in) :: f_name
4002 : real(sp), dimension(:, :, :), intent(in) :: arr
4003 : character(len = *), intent(in) :: v_name
4004 : character(len = *), dimension(:), intent(in) :: dnames
4005 : ! optional
4006 : integer(i4), optional, intent(in) :: dim_unlimited
4007 : character(len = *), optional, intent(in) :: long_name
4008 : character(len = *), optional, intent(in) :: units
4009 : real(sp), optional, intent(in) :: missing_value
4010 : character(256), dimension(:, :), optional, intent(in) :: attributes
4011 : logical, optional, intent(in) :: create
4012 : integer(i4), optional, intent(inout) :: ncid
4013 : integer(i4), optional, intent(in) :: nrec
4014 : ! local variables
4015 : logical :: create_loc
4016 : character(256) :: dummy_name
4017 : integer(i4) :: deflate
4018 0 : integer(i4), dimension(:), allocatable :: chunksizes
4019 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
4020 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
4021 : integer(i4) :: idim ! read dimension on append
4022 : integer(i4) :: f_handle
4023 : integer(i4) :: d_unlimit ! index of unlimited dimension
4024 : integer(i4) :: u_dimid ! dimid of unlimited dimension
4025 : integer(i4) :: u_len ! length of unlimited dimension
4026 0 : integer(i4), dimension(:), allocatable :: dims
4027 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4028 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4029 : integer(i4) :: i ! loop indices
4030 0 : integer(i4), dimension(:), allocatable :: dummy_count
4031 0 : real(sp), dimension(1) :: dummy ! dummy read
4032 : logical :: openfile ! tmp logical
4033 : !
4034 0 : ndim = size(dnames, 1)
4035 : ! consistency checks
4036 0 : d_unlimit = 0_i4
4037 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
4038 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4039 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4040 0 : stop '***ERROR see StdOut'
4041 : end if
4042 0 : if (ndim .gt. ndim_const + 1) then
4043 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4044 0 : stop '***ERROR see StdOut'
4045 : end if
4046 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4047 : (d_unlimit .lt. 0_i4)) then
4048 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4049 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4050 0 : stop '***ERROR see StdOut'
4051 : end if
4052 : !
4053 0 : allocate(chunksizes(ndim))
4054 0 : allocate(start(ndim))
4055 0 : allocate(counter(ndim))
4056 0 : allocate(dims(ndim))
4057 0 : allocate(dimid(ndim))
4058 0 : allocate(varid(1 + ndim))
4059 0 : allocate(dummy_count(ndim))
4060 : ! initialize
4061 0 : deflate = 1
4062 : ! set chunk sizes and dimension names
4063 0 : if (ndim .gt. ndim_const) then
4064 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), 1 /)
4065 0 : dims(1 : ndim - 1) = shape(arr)
4066 0 : dims(ndim) = 1
4067 : else
4068 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3) /)
4069 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4070 0 : dims(1 : ndim_const) = shape(arr)
4071 : end if
4072 0 : start(:) = 1_i4
4073 0 : counter(:) = dims
4074 0 : dummy_count = 1_i4
4075 0 : dummy = nf90_fill_float
4076 : ! open the netcdf file
4077 0 : if (present(ncid)) then
4078 0 : if (ncid < 0_i4) then
4079 : openfile = .true.
4080 : else
4081 0 : openfile = .false.
4082 0 : f_handle = ncid
4083 : end if
4084 : else
4085 : openfile = .true.
4086 : end if
4087 : if (openfile) then
4088 0 : create_loc = .false.
4089 0 : if (present(create)) create_loc = create
4090 0 : f_handle = open_netcdf(f_name, create = create_loc)
4091 : end if
4092 : ! check whether variable exists
4093 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4094 : ! append
4095 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4096 : ! consistency checks
4097 0 : if (idim .ne. ndim) stop "var2nc_3d_sp: number of variable dimensions /= number of file variable dimensions."
4098 : ! check unlimited dimension
4099 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
4100 0 : if (u_dimid .eq. -1) stop 'var2nc_3d_sp: cannot append, no unlimited dimension defined'
4101 : ! check for unlimited dimension
4102 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_3d_sp: unlimited dimension not specified correctly'
4103 0 : if (present(nrec)) then
4104 0 : start(d_unlimit) = nrec
4105 : else
4106 : ! get length of unlimited dimension
4107 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4108 : ! adapt start, that is find last written chunk
4109 0 : do i = u_len, 1, -1
4110 0 : if (ne(dummy(1), nf90_fill_float)) exit
4111 0 : start(d_unlimit) = i
4112 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4113 : end do
4114 0 : start(d_unlimit) = start(d_unlimit) + 1
4115 : end if
4116 : else
4117 : ! define dimensions
4118 0 : do i = 1, ndim
4119 : ! check whether dimension exists
4120 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4121 : ! create dimension
4122 0 : if (i .eq. d_unlimit) then
4123 : ! define unlimited dimension
4124 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
4125 : else
4126 : ! define limited dimension
4127 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
4128 : end if
4129 : end if
4130 : end do
4131 : ! define variable
4132 0 : call check(nf90_def_var(f_handle, v_name, NF90_FLOAT, dimid, varid(ndim + 1), &
4133 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4134 : ! add attributes
4135 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
4136 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
4137 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
4138 0 : if (present(attributes)) then
4139 0 : do i = 1, size(attributes, dim = 1)
4140 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
4141 : ! write number
4142 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
4143 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4144 0 : trim(attributes(i, 1)), dummy(1)))
4145 : else
4146 : ! write string
4147 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4148 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
4149 : end if
4150 : end do
4151 : end if
4152 : ! end definition
4153 0 : call check(nf90_enddef(f_handle))
4154 : end if
4155 : ! check dimensions before writing
4156 0 : do i = 1, ndim_const
4157 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4158 0 : if (trim(dummy_name) .ne. dnames(i)) &
4159 0 : stop "var2nc_3d_sp: dimension name problem."
4160 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4161 0 : stop "var2nc_3d_sp: variable dimension /= file variable dimension."
4162 : end do
4163 : ! write variable
4164 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4165 : ! close netcdf_dataset
4166 0 : if (present(ncid)) then
4167 0 : if (ncid < 0_i4) ncid = f_handle
4168 : else
4169 0 : call close_netcdf(f_handle)
4170 : end if
4171 : !
4172 0 : end subroutine var2nc_3d_sp
4173 :
4174 0 : subroutine var2nc_3d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
4175 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
4176 : !
4177 : implicit none
4178 : !
4179 : integer(i4), parameter :: ndim_const = 3
4180 : integer(i4) :: ndim
4181 : ! input variables
4182 : character(len = *), intent(in) :: f_name
4183 : real(dp), dimension(:, :, :), intent(in) :: arr
4184 : character(len = *), intent(in) :: v_name
4185 : character(len = *), dimension(:), intent(in) :: dnames
4186 : ! optional
4187 : integer(i4), optional, intent(in) :: dim_unlimited
4188 : character(len = *), optional, intent(in) :: long_name
4189 : character(len = *), optional, intent(in) :: units
4190 : real(dp), optional, intent(in) :: missing_value
4191 : character(256), dimension(:, :), optional, intent(in) :: attributes
4192 : logical, optional, intent(in) :: create
4193 : integer(i4), optional, intent(inout) :: ncid
4194 : integer(i4), optional, intent(in) :: nrec
4195 : ! local variables
4196 : logical :: create_loc
4197 : character(256) :: dummy_name
4198 : integer(i4) :: deflate
4199 0 : integer(i4), dimension(:), allocatable :: chunksizes
4200 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
4201 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
4202 : integer(i4) :: idim ! read dimension on append
4203 : integer(i4) :: f_handle
4204 : integer(i4) :: d_unlimit ! index of unlimited dimension
4205 : integer(i4) :: u_dimid ! dimid of unlimited dimension
4206 : integer(i4) :: u_len ! length of unlimited dimension
4207 0 : integer(i4), dimension(:), allocatable :: dims
4208 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4209 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4210 : integer(i4) :: i ! loop indices
4211 0 : integer(i4), dimension(:), allocatable :: dummy_count
4212 0 : real(dp), dimension(1) :: dummy ! dummy read
4213 : logical :: openfile ! tmp logical
4214 : !
4215 0 : ndim = size(dnames, 1)
4216 : ! consistency checks
4217 0 : d_unlimit = 0_i4
4218 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
4219 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4220 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4221 0 : stop '***ERROR see StdOut'
4222 : end if
4223 0 : if (ndim .gt. ndim_const + 1) then
4224 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4225 0 : stop '***ERROR see StdOut'
4226 : end if
4227 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4228 : (d_unlimit .lt. 0_i4)) then
4229 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4230 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4231 0 : stop '***ERROR see StdOut'
4232 : end if
4233 : !
4234 0 : allocate(chunksizes(ndim))
4235 0 : allocate(start(ndim))
4236 0 : allocate(counter(ndim))
4237 0 : allocate(dims(ndim))
4238 0 : allocate(dimid(ndim))
4239 0 : allocate(varid(1 + ndim))
4240 0 : allocate(dummy_count(ndim))
4241 : ! initialize
4242 0 : deflate = 1
4243 0 : if (ndim .gt. ndim_const) then
4244 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), 1 /)
4245 0 : dims(1 : ndim - 1) = shape(arr)
4246 0 : dims(ndim) = 1
4247 : else
4248 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3) /)
4249 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4250 0 : dims(1 : ndim_const) = shape(arr)
4251 : end if
4252 0 : start(:) = 1_i4
4253 0 : counter(:) = dims
4254 0 : dummy_count = 1
4255 0 : dummy = nf90_fill_double
4256 : ! open the netcdf file
4257 0 : if (present(ncid)) then
4258 0 : if (ncid < 0_i4) then
4259 : openfile = .true.
4260 : else
4261 0 : openfile = .false.
4262 0 : f_handle = ncid
4263 : end if
4264 : else
4265 : openfile = .true.
4266 : end if
4267 : if (openfile) then
4268 0 : create_loc = .false.
4269 0 : if (present(create)) create_loc = create
4270 0 : f_handle = open_netcdf(f_name, create = create_loc)
4271 : end if
4272 : ! check whether variable exists
4273 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4274 : ! append
4275 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4276 : ! consistency checks
4277 0 : if (idim .ne. ndim) stop "var2nc_3d_dp: number of variable dimensions /= number of file variable dimensions."
4278 : ! check unlimited dimension
4279 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
4280 0 : if (u_dimid .eq. -1) stop 'var2nc_3d_dp: cannot append, no unlimited dimension defined'
4281 : ! check for unlimited dimension
4282 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_3d_dp: unlimited dimension not specified correctly'
4283 0 : if (present(nrec)) then
4284 0 : start(d_unlimit) = nrec
4285 : else
4286 : ! get length of unlimited dimension
4287 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4288 : ! adapt start, that is find last written chunk
4289 0 : do i = u_len, 1, -1
4290 0 : if (ne(dummy(1), nf90_fill_double)) exit
4291 0 : start(d_unlimit) = i
4292 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4293 : end do
4294 0 : start(d_unlimit) = start(d_unlimit) + 1
4295 : end if
4296 : else
4297 : ! define dimensions
4298 0 : do i = 1, ndim
4299 : ! check whether dimension exists
4300 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4301 : ! create dimension
4302 0 : if (i .eq. d_unlimit) then
4303 : ! define unlimited dimension
4304 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
4305 : else
4306 : ! define limited dimension
4307 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
4308 : end if
4309 : end if
4310 : end do
4311 : ! define variable
4312 0 : call check(nf90_def_var(f_handle, v_name, NF90_DOUBLE, dimid, varid(ndim + 1), &
4313 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4314 : ! add attributes
4315 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
4316 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
4317 0 : if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
4318 0 : if (present(attributes)) then
4319 0 : do i = 1, size(attributes, dim = 1)
4320 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
4321 : ! write number
4322 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
4323 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4324 0 : trim(attributes(i, 1)), dummy(1)))
4325 : else
4326 : ! write string
4327 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4328 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
4329 : end if
4330 : end do
4331 : end if
4332 : ! end definition
4333 0 : call check(nf90_enddef(f_handle))
4334 : end if
4335 : ! check dimensions before writing
4336 0 : do i = 1, ndim_const
4337 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4338 0 : if (trim(dummy_name) .ne. dnames(i)) &
4339 0 : stop "var2nc_3d_dp: dimension name problem."
4340 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4341 0 : stop "var2nc_3d_dp: variable dimension /= file variable dimension."
4342 : end do
4343 : ! write variable
4344 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4345 : ! close netcdf_dataset
4346 0 : if (present(ncid)) then
4347 0 : if (ncid < 0_i4) ncid = f_handle
4348 : else
4349 0 : call close_netcdf(f_handle)
4350 : end if
4351 : !
4352 0 : end subroutine var2nc_3d_dp
4353 :
4354 0 : subroutine var2nc_4d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
4355 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
4356 : !
4357 : implicit none
4358 : !
4359 : integer(i4), parameter :: ndim_const = 4
4360 : integer(i4) :: ndim
4361 : ! input variables
4362 : character(len = *), intent(in) :: f_name
4363 : integer(i4), dimension(:, :, :, :), intent(in) :: arr
4364 : character(len = *), intent(in) :: v_name
4365 : character(len = *), dimension(:), intent(in) :: dnames
4366 : ! optional
4367 : integer(i4), optional, intent(in) :: dim_unlimited
4368 : character(len = *), optional, intent(in) :: long_name
4369 : character(len = *), optional, intent(in) :: units
4370 : integer(i4), optional, intent(in) :: missing_value
4371 : character(256), dimension(:, :), optional, intent(in) :: attributes
4372 : logical, optional, intent(in) :: create
4373 : integer(i4), optional, intent(inout) :: ncid
4374 : integer(i4), optional, intent(in) :: nrec
4375 : ! local variables
4376 : logical :: create_loc
4377 : character(256) :: dummy_name
4378 : integer(i4) :: deflate
4379 0 : integer(i4), dimension(:), allocatable :: chunksizes
4380 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
4381 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
4382 : integer(i4) :: idim ! read dimension on append
4383 : integer(i4) :: f_handle
4384 : integer(i4) :: d_unlimit ! index of unlimited dimension
4385 : integer(i4) :: u_dimid ! dimid of unlimited dimension
4386 : integer(i4) :: u_len ! length of unlimited dimension
4387 0 : integer(i4), dimension(:), allocatable :: dims
4388 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4389 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4390 : integer(i4) :: i ! loop indices
4391 0 : integer(i4), dimension(:), allocatable :: dummy_count
4392 : integer(i4), dimension(1) :: dummy ! dummy read
4393 : logical :: openfile ! tmp logical
4394 : !
4395 0 : ndim = size(dnames, 1)
4396 : ! consistency checks
4397 0 : d_unlimit = 0_i4
4398 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
4399 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4400 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4401 0 : stop '***ERROR see StdOut'
4402 : end if
4403 0 : if (ndim .gt. ndim_const + 1) then
4404 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4405 0 : stop '***ERROR see StdOut'
4406 : end if
4407 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4408 : (d_unlimit .lt. 0_i4)) then
4409 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4410 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4411 0 : stop '***ERROR see StdOut'
4412 : end if
4413 : !
4414 0 : allocate(chunksizes(ndim))
4415 0 : allocate(start(ndim))
4416 0 : allocate(counter(ndim))
4417 0 : allocate(dims(ndim))
4418 0 : allocate(dimid(ndim))
4419 0 : allocate(varid(1 + ndim))
4420 0 : allocate(dummy_count(ndim))
4421 : ! initialize
4422 0 : deflate = 1
4423 0 : if (ndim .gt. ndim_const) then
4424 : chunksizes = (/ size(arr, 1), size(arr, 2), &
4425 0 : size(arr, 3), size(arr, 4), 1 /)
4426 0 : dims(1 : ndim - 1) = shape(arr)
4427 0 : dims(ndim) = 1
4428 : else
4429 : chunksizes = (/ size(arr, 1), size(arr, 2), &
4430 0 : size(arr, 3), size(arr, 4) /)
4431 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4432 0 : dims(1 : ndim_const) = shape(arr)
4433 : end if
4434 0 : start(:) = 1_i4
4435 0 : counter(:) = dims
4436 0 : dummy_count = 1_i4
4437 0 : dummy = nf90_fill_int
4438 : ! open the netcdf file
4439 0 : if (present(ncid)) then
4440 0 : if (ncid < 0_i4) then
4441 : openfile = .true.
4442 : else
4443 0 : openfile = .false.
4444 0 : f_handle = ncid
4445 : end if
4446 : else
4447 : openfile = .true.
4448 : end if
4449 : if (openfile) then
4450 0 : create_loc = .false.
4451 0 : if (present(create)) create_loc = create
4452 0 : f_handle = open_netcdf(f_name, create = create_loc)
4453 : end if
4454 : ! check whether variable exists
4455 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4456 : ! append
4457 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4458 : ! consistency checks
4459 0 : if (idim .ne. ndim) stop "var2nc_4d_i4: number of variable dimensions /= number of file variable dimensions."
4460 : ! check unlimited dimension
4461 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
4462 0 : if (u_dimid .eq. -1) stop 'var2nc_4d_i4: cannot append, no unlimited dimension defined'
4463 : ! check for unlimited dimension
4464 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_4d_sp: unlimited dimension not specified correctly'
4465 0 : if (present(nrec)) then
4466 0 : start(d_unlimit) = nrec
4467 : else
4468 : ! get length of unlimited dimension
4469 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4470 : ! adapt start, that is find last written chunk
4471 0 : do i = u_len, 1, -1
4472 0 : if (dummy(1) /= nf90_fill_int) exit
4473 0 : start(d_unlimit) = i
4474 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4475 : end do
4476 0 : start(d_unlimit) = start(d_unlimit) + 1
4477 : end if
4478 : else
4479 : ! define dimensions
4480 0 : do i = 1, ndim
4481 : ! check whether dimension exists
4482 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4483 : ! create dimension
4484 0 : if (i .eq. d_unlimit) then
4485 : ! define unlimited dimension
4486 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
4487 : else
4488 : ! define limited dimension
4489 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
4490 : end if
4491 : end if
4492 : end do
4493 : ! define variable
4494 0 : call check(nf90_def_var(f_handle, v_name, NF90_INT, dimid, varid(ndim + 1), &
4495 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4496 : ! add attributes
4497 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
4498 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
4499 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
4500 0 : if (present(attributes)) then
4501 0 : do i = 1, size(attributes, dim = 1)
4502 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
4503 : ! write number
4504 0 : read(attributes(i, 2), '(I6)') dummy(1)
4505 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4506 0 : trim(attributes(i, 1)), dummy(1)))
4507 : else
4508 : ! write string
4509 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4510 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
4511 : end if
4512 : end do
4513 : end if
4514 : ! end definition
4515 0 : call check(nf90_enddef(f_handle))
4516 : end if
4517 : ! check dimensions before writing
4518 0 : do i = 1, ndim_const
4519 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4520 0 : if (trim(dummy_name) .ne. dnames(i)) &
4521 0 : stop "var2nc_4d_i4: dimension name problem."
4522 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4523 0 : stop "var2nc_4d_i4: variable dimension /= file variable dimension."
4524 : end do
4525 : ! write variable
4526 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4527 : ! close netcdf_dataset
4528 0 : if (present(ncid)) then
4529 0 : if (ncid < 0_i4) ncid = f_handle
4530 : else
4531 0 : call close_netcdf(f_handle)
4532 : end if
4533 : !
4534 0 : end subroutine var2nc_4d_i4
4535 :
4536 0 : subroutine var2nc_4d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
4537 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
4538 : !
4539 : implicit none
4540 : !
4541 : integer(i4), parameter :: ndim_const = 4
4542 : integer(i4) :: ndim
4543 : ! input variables
4544 : character(len = *), intent(in) :: f_name
4545 : real(sp), dimension(:, :, :, :), intent(in) :: arr
4546 : character(len = *), intent(in) :: v_name
4547 : character(len = *), dimension(:), intent(in) :: dnames
4548 : ! optional
4549 : integer(i4), optional, intent(in) :: dim_unlimited
4550 : character(len = *), optional, intent(in) :: long_name
4551 : character(len = *), optional, intent(in) :: units
4552 : real(sp), optional, intent(in) :: missing_value
4553 : character(256), dimension(:, :), optional, intent(in) :: attributes
4554 : logical, optional, intent(in) :: create
4555 : integer(i4), optional, intent(inout) :: ncid
4556 : integer(i4), optional, intent(in) :: nrec
4557 : ! local variables
4558 : logical :: create_loc
4559 : character(256) :: dummy_name
4560 : integer(i4) :: deflate
4561 0 : integer(i4), dimension(:), allocatable :: chunksizes
4562 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
4563 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
4564 : integer(i4) :: idim ! read dimension on append
4565 : integer(i4) :: f_handle
4566 : integer(i4) :: d_unlimit ! index of unlimited dimension
4567 : integer(i4) :: u_dimid ! dimid of unlimited dimension
4568 : integer(i4) :: u_len ! length of unlimited dimension
4569 0 : integer(i4), dimension(:), allocatable :: dims
4570 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4571 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4572 : integer(i4) :: i ! loop indices
4573 0 : integer(i4), dimension(:), allocatable :: dummy_count
4574 0 : real(sp), dimension(1) :: dummy ! dummy read
4575 : logical :: openfile ! tmp logical
4576 : !
4577 0 : ndim = size(dnames, 1)
4578 : ! consistency checks
4579 0 : d_unlimit = 0_i4
4580 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
4581 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4582 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4583 0 : stop '***ERROR see StdOut'
4584 : end if
4585 0 : if (ndim .gt. ndim_const + 1) then
4586 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4587 0 : stop '***ERROR see StdOut'
4588 : end if
4589 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4590 : (d_unlimit .lt. 0_i4)) then
4591 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4592 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4593 0 : stop '***ERROR see StdOut'
4594 : end if
4595 : !
4596 0 : allocate(chunksizes(ndim))
4597 0 : allocate(start(ndim))
4598 0 : allocate(counter(ndim))
4599 0 : allocate(dims(ndim))
4600 0 : allocate(dimid(ndim))
4601 0 : allocate(varid(1 + ndim))
4602 0 : allocate(dummy_count(ndim))
4603 : ! initialize
4604 0 : deflate = 1
4605 0 : if (ndim .gt. ndim_const) then
4606 : chunksizes = (/ size(arr, 1), size(arr, 2), &
4607 0 : size(arr, 3), size(arr, 4), 1 /)
4608 0 : dims(1 : ndim - 1) = shape(arr)
4609 0 : dims(ndim) = 1
4610 : else
4611 : chunksizes = (/ size(arr, 1), size(arr, 2), &
4612 0 : size(arr, 3), size(arr, 4) /)
4613 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4614 0 : dims(1 : ndim_const) = shape(arr)
4615 : end if
4616 0 : start(:) = 1_i4
4617 0 : counter(:) = dims
4618 0 : dummy_count = 1_i4
4619 0 : dummy = nf90_fill_float
4620 : ! open the netcdf file
4621 0 : if (present(ncid)) then
4622 0 : if (ncid < 0_i4) then
4623 : openfile = .true.
4624 : else
4625 0 : openfile = .false.
4626 0 : f_handle = ncid
4627 : end if
4628 : else
4629 : openfile = .true.
4630 : end if
4631 : if (openfile) then
4632 0 : create_loc = .false.
4633 0 : if (present(create)) create_loc = create
4634 0 : f_handle = open_netcdf(f_name, create = create_loc)
4635 : end if
4636 : ! check whether variable exists
4637 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4638 : ! append
4639 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4640 : ! consistency checks
4641 0 : if (idim .ne. ndim) stop "var2nc_4d_sp: number of variable dimensions /= number of file variable dimensions."
4642 : ! check unlimited dimension
4643 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
4644 0 : if (u_dimid .eq. -1) stop 'var2nc_4d_sp: cannot append, no unlimited dimension defined'
4645 : ! check for unlimited dimension
4646 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_4d_sp: unlimited dimension not specified correctly'
4647 0 : if (present(nrec)) then
4648 0 : start(d_unlimit) = nrec
4649 : else
4650 : ! get length of unlimited dimension
4651 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4652 : ! adapt start, that is find last written chunk
4653 0 : do i = u_len, 1, -1
4654 0 : if (ne(dummy(1), nf90_fill_float)) exit
4655 0 : start(d_unlimit) = i
4656 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4657 : end do
4658 0 : start(d_unlimit) = start(d_unlimit) + 1
4659 : end if
4660 : else
4661 : ! define dimensions
4662 0 : do i = 1, ndim
4663 : ! check whether dimension exists
4664 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4665 : ! create dimension
4666 0 : if (i .eq. d_unlimit) then
4667 : ! define unlimited dimension
4668 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
4669 : else
4670 : ! define limited dimension
4671 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
4672 : end if
4673 : end if
4674 : end do
4675 : ! define variable
4676 0 : call check(nf90_def_var(f_handle, v_name, NF90_FLOAT, dimid, varid(ndim + 1), &
4677 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4678 : ! add attributes
4679 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
4680 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
4681 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
4682 0 : if (present(attributes)) then
4683 0 : do i = 1, size(attributes, dim = 1)
4684 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
4685 : ! write number
4686 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
4687 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4688 0 : trim(attributes(i, 1)), dummy(1)))
4689 : else
4690 : ! write string
4691 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4692 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
4693 : end if
4694 : end do
4695 : end if
4696 : ! end definition
4697 0 : call check(nf90_enddef(f_handle))
4698 : end if
4699 : ! check dimensions before writing
4700 0 : do i = 1, ndim_const
4701 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4702 0 : if (trim(dummy_name) .ne. dnames(i)) &
4703 0 : stop "var2nc_4d_sp: dimension name problem."
4704 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4705 0 : stop "var2nc_4d_sp: variable dimension /= file variable dimension."
4706 : end do
4707 : ! write variable
4708 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4709 : ! close netcdf_dataset
4710 0 : if (present(ncid)) then
4711 0 : if (ncid < 0_i4) ncid = f_handle
4712 : else
4713 0 : call close_netcdf(f_handle)
4714 : end if
4715 : !
4716 0 : end subroutine var2nc_4d_sp
4717 :
4718 0 : subroutine var2nc_4d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
4719 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
4720 : !
4721 : implicit none
4722 : !
4723 : integer(i4), parameter :: ndim_const = 4
4724 : integer(i4) :: ndim
4725 : ! input variables
4726 : character(len = *), intent(in) :: f_name
4727 : real(dp), dimension(:, :, :, :), intent(in) :: arr
4728 : character(len = *), intent(in) :: v_name
4729 : character(len = *), dimension(:), intent(in) :: dnames
4730 : ! optional
4731 : integer(i4), optional, intent(in) :: dim_unlimited
4732 : character(len = *), optional, intent(in) :: long_name
4733 : character(len = *), optional, intent(in) :: units
4734 : real(dp), optional, intent(in) :: missing_value
4735 : character(256), dimension(:, :), optional, intent(in) :: attributes
4736 : logical, optional, intent(in) :: create
4737 : integer(i4), optional, intent(inout) :: ncid
4738 : integer(i4), optional, intent(in) :: nrec
4739 : ! local variables
4740 : logical :: create_loc
4741 : character(256) :: dummy_name
4742 : integer(i4) :: deflate
4743 0 : integer(i4), dimension(:), allocatable :: chunksizes
4744 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
4745 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
4746 : integer(i4) :: idim ! read dimension on append
4747 : integer(i4) :: f_handle
4748 : integer(i4) :: d_unlimit ! index of unlimited dimension
4749 : integer(i4) :: u_dimid ! dimid of unlimited dimension
4750 : integer(i4) :: u_len ! length of unlimited dimension
4751 0 : integer(i4), dimension(:), allocatable :: dims
4752 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4753 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4754 : integer(i4) :: i ! loop indices
4755 0 : integer(i4), dimension(:), allocatable :: dummy_count
4756 0 : real(dp), dimension(1) :: dummy ! dummy read
4757 : logical :: openfile ! tmp logical
4758 : !
4759 0 : ndim = size(dnames, 1)
4760 : ! consistency checks
4761 0 : d_unlimit = 0_i4
4762 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
4763 0 : if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4764 0 : print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4765 0 : stop '***ERROR see StdOut'
4766 : end if
4767 0 : if (ndim .gt. ndim_const + 1) then
4768 0 : print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4769 0 : stop '***ERROR see StdOut'
4770 : end if
4771 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4772 : (d_unlimit .lt. 0_i4)) then
4773 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4774 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4775 0 : stop '***ERROR see StdOut'
4776 : end if
4777 : !
4778 0 : allocate(chunksizes(ndim))
4779 0 : allocate(start(ndim))
4780 0 : allocate(counter(ndim))
4781 0 : allocate(dims(ndim))
4782 0 : allocate(dimid(ndim))
4783 0 : allocate(varid(1 + ndim))
4784 0 : allocate(dummy_count(ndim))
4785 : ! Initialize
4786 0 : deflate = 1
4787 0 : if (ndim .gt. ndim_const) then
4788 : chunksizes = (/ size(arr, 1), size(arr, 2), &
4789 0 : size(arr, 3), size(arr, 4), 1 /)
4790 0 : dims(1 : ndim - 1) = shape(arr)
4791 0 : dims(ndim) = 1
4792 : else
4793 : chunksizes = (/ size(arr, 1), size(arr, 2), &
4794 0 : size(arr, 3), size(arr, 4) /)
4795 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4796 0 : dims(1 : ndim_const) = shape(arr)
4797 : end if
4798 0 : start(:) = 1_i4
4799 0 : counter(:) = dims
4800 0 : dummy_count = 1
4801 0 : dummy = nf90_fill_double
4802 : ! open the netcdf file
4803 0 : if (present(ncid)) then
4804 0 : if (ncid < 0_i4) then
4805 : openfile = .true.
4806 : else
4807 0 : openfile = .false.
4808 0 : f_handle = ncid
4809 : end if
4810 : else
4811 : openfile = .true.
4812 : end if
4813 : if (openfile) then
4814 0 : create_loc = .false.
4815 0 : if (present(create)) create_loc = create
4816 0 : f_handle = open_netcdf(f_name, create = create_loc)
4817 : end if
4818 : ! check whether variable exists
4819 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4820 : ! append
4821 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4822 : ! consistency checks
4823 0 : if (idim .ne. ndim) stop "var2nc_4d_dp: number of variable dimensions /= number of file variable dimensions."
4824 : ! check unlimited dimension
4825 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
4826 0 : if (u_dimid .eq. -1) stop 'var2nc_4d_dp: cannot append, no unlimited dimension defined'
4827 : ! check for unlimited dimension
4828 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_4d_dp: unlimited dimension not specified correctly'
4829 0 : if (present(nrec)) then
4830 0 : start(d_unlimit) = nrec
4831 : else
4832 : ! get length of unlimited dimension
4833 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4834 : ! adapt start, that is find last written chunk
4835 0 : do i = u_len, 1, -1
4836 0 : if (ne(dummy(1), nf90_fill_double)) exit
4837 0 : start(d_unlimit) = i
4838 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4839 : end do
4840 0 : start(d_unlimit) = start(d_unlimit) + 1
4841 : end if
4842 : else
4843 : ! define dimensions
4844 0 : do i = 1, ndim
4845 : ! check whether dimension exists
4846 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4847 : ! create dimension
4848 0 : if (i .eq. d_unlimit) then
4849 : ! define unlimited dimension
4850 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
4851 : else
4852 : ! define limited dimension
4853 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
4854 : end if
4855 : end if
4856 : end do
4857 : ! define variable
4858 0 : call check(nf90_def_var(f_handle, v_name, NF90_DOUBLE, dimid, varid(ndim + 1), &
4859 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4860 : ! add attributes
4861 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
4862 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
4863 0 : if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
4864 0 : if (present(attributes)) then
4865 0 : do i = 1, size(attributes, dim = 1)
4866 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
4867 : ! write number
4868 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
4869 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4870 0 : trim(attributes(i, 1)), dummy(1)))
4871 : else
4872 : ! write string
4873 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
4874 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
4875 : end if
4876 : end do
4877 : end if
4878 : ! end definition
4879 0 : call check(nf90_enddef(f_handle))
4880 : end if
4881 : ! check dimensions before writing
4882 0 : do i = 1, ndim_const
4883 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4884 0 : if (trim(dummy_name) .ne. dnames(i)) &
4885 0 : stop "var2nc_4d_dp: dimension name problem."
4886 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4887 0 : stop "var2nc_4d_dp: variable dimension /= file variable dimension."
4888 : end do
4889 : ! write variable
4890 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4891 : ! close netcdf_dataset
4892 0 : if (present(ncid)) then
4893 0 : if (ncid < 0_i4) ncid = f_handle
4894 : else
4895 0 : call close_netcdf(f_handle)
4896 : end if
4897 : !
4898 0 : end subroutine var2nc_4d_dp
4899 :
4900 0 : subroutine var2nc_5d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
4901 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
4902 : !
4903 : implicit none
4904 : !
4905 : integer(i4), parameter :: ndim_const = 5
4906 : integer(i4) :: ndim
4907 : ! input variables
4908 : character(len = *), intent(in) :: f_name
4909 : integer(i4), dimension(:, :, :, :, :), intent(in) :: arr
4910 : character(len = *), intent(in) :: v_name
4911 : character(len = *), dimension(:), intent(in) :: dnames
4912 : ! optional
4913 : integer(i4), optional, intent(in) :: dim_unlimited
4914 : character(len = *), optional, intent(in) :: long_name
4915 : character(len = *), optional, intent(in) :: units
4916 : integer(i4), optional, intent(in) :: missing_value
4917 : character(256), dimension(:, :), optional, intent(in) :: attributes
4918 : logical, optional, intent(in) :: create
4919 : integer(i4), optional, intent(inout) :: ncid
4920 : integer(i4), optional, intent(in) :: nrec
4921 : ! local variables
4922 : logical :: create_loc
4923 : character(256) :: dummy_name
4924 : integer(i4) :: deflate
4925 0 : integer(i4), dimension(:), allocatable :: chunksizes
4926 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
4927 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
4928 : integer(i4) :: idim ! read dimension on append
4929 : integer(i4) :: f_handle
4930 : integer(i4) :: d_unlimit ! index of unlimited dimension
4931 : integer(i4) :: u_dimid ! dimid of unlimited dimension
4932 : integer(i4) :: u_len ! length of unlimited dimension
4933 0 : integer(i4), dimension(:), allocatable :: dims
4934 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4935 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4936 : integer(i4) :: i ! loop indices
4937 0 : integer(i4), dimension(:), allocatable :: dummy_count
4938 : integer(i4), dimension(1) :: dummy ! dummy read
4939 : logical :: openfile ! tmp logical
4940 : !
4941 0 : ndim = size(dnames, 1)
4942 0 : d_unlimit = 0_i4
4943 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
4944 : ! consistency checks
4945 0 : if (ndim .gt. ndim_const) then
4946 0 : print *, '***ERROR more than five dimension names given'
4947 0 : stop '***ERROR see StdOut'
4948 : end if
4949 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4950 : (d_unlimit .lt. 0_i4)) then
4951 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4952 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4953 0 : stop '***ERROR see StdOut'
4954 : end if
4955 : !
4956 0 : allocate(chunksizes(ndim))
4957 0 : allocate(start(ndim))
4958 0 : allocate(counter(ndim))
4959 0 : allocate(dims(ndim))
4960 0 : allocate(dimid(ndim))
4961 0 : allocate(varid(1 + ndim))
4962 0 : allocate(dummy_count(ndim))
4963 : ! initialize
4964 0 : deflate = 1
4965 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), size(arr, 4), size(arr, 5) /)
4966 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4967 0 : dims(1 : ndim) = shape(arr)
4968 0 : start(:) = 1_i4
4969 0 : counter(:) = dims
4970 0 : dummy_count = 1_i4
4971 0 : dummy = nf90_fill_int
4972 0 : d_unlimit = 0_i4
4973 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
4974 : ! open the netcdf file
4975 0 : if (present(ncid)) then
4976 0 : if (ncid < 0_i4) then
4977 : openfile = .true.
4978 : else
4979 0 : openfile = .false.
4980 0 : f_handle = ncid
4981 : end if
4982 : else
4983 : openfile = .true.
4984 : end if
4985 : if (openfile) then
4986 0 : create_loc = .false.
4987 0 : if (present(create)) create_loc = create
4988 0 : f_handle = open_netcdf(f_name, create = create_loc)
4989 : end if
4990 : ! check whether variable exists
4991 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4992 : ! append
4993 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4994 : ! consistency checks
4995 0 : if (idim .ne. ndim) stop "var2nc_5d_i4: number of variable dimensions /= number of file variable dimensions."
4996 : ! check unlimited dimension
4997 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
4998 0 : if (u_dimid .eq. -1) stop 'var2nc_5d_i4: cannot append, no unlimited dimension defined'
4999 : ! check for unlimited dimension
5000 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_5d_sp: unlimited dimension not specified correctly'
5001 0 : if (present(nrec)) then
5002 0 : start(d_unlimit) = nrec
5003 : else
5004 : ! get length of unlimited dimension
5005 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
5006 : ! adapt start, that is find last written chunk
5007 0 : do i = u_len, 1, -1
5008 0 : if (dummy(1) /= nf90_fill_int) exit
5009 0 : start(d_unlimit) = i
5010 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
5011 : end do
5012 0 : start(d_unlimit) = start(d_unlimit) + 1
5013 : end if
5014 : else
5015 : ! define dimensions
5016 0 : do i = 1, ndim
5017 : ! check whether dimension exists
5018 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
5019 : ! create dimension
5020 0 : if (i .eq. d_unlimit) then
5021 : ! define unlimited dimension
5022 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
5023 : else
5024 : ! define limited dimension
5025 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
5026 : end if
5027 : end if
5028 : end do
5029 : ! define variable
5030 0 : call check(nf90_def_var(f_handle, v_name, NF90_INT, dimid, varid(ndim + 1), &
5031 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
5032 : ! add attributes
5033 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
5034 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
5035 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
5036 0 : if (present(attributes)) then
5037 0 : do i = 1, size(attributes, dim = 1)
5038 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
5039 : ! write number
5040 0 : read(attributes(i, 2), '(I6)') dummy(1)
5041 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
5042 0 : trim(attributes(i, 1)), dummy(1)))
5043 : else
5044 : ! write string
5045 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
5046 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
5047 : end if
5048 : end do
5049 : end if
5050 : ! end definition
5051 0 : call check(nf90_enddef(f_handle))
5052 : end if
5053 : ! check dimensions before writing
5054 0 : do i = 1, ndim_const
5055 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
5056 0 : if (trim(dummy_name) .ne. dnames(i)) &
5057 0 : stop "var2nc_5d_i4: dimension name problem."
5058 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
5059 0 : stop "var2nc_5d_i4: variable dimension /= file variable dimension."
5060 : end do
5061 : ! write variable
5062 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
5063 : ! close netcdf_dataset
5064 0 : if (present(ncid)) then
5065 0 : if (ncid < 0_i4) ncid = f_handle
5066 : else
5067 0 : call close_netcdf(f_handle)
5068 : end if
5069 : !
5070 0 : end subroutine var2nc_5d_i4
5071 :
5072 0 : subroutine var2nc_5d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
5073 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
5074 : !
5075 : implicit none
5076 : !
5077 : integer(i4), parameter :: ndim_const = 5
5078 : integer(i4) :: ndim
5079 : ! input variables
5080 : character(len = *), intent(in) :: f_name
5081 : real(sp), dimension(:, :, :, :, :), intent(in) :: arr
5082 : character(len = *), intent(in) :: v_name
5083 : character(len = *), dimension(:), intent(in) :: dnames
5084 : ! optional
5085 : integer(i4), optional, intent(in) :: dim_unlimited
5086 : character(len = *), optional, intent(in) :: long_name
5087 : character(len = *), optional, intent(in) :: units
5088 : real(sp), optional, intent(in) :: missing_value
5089 : character(256), dimension(:, :), optional, intent(in) :: attributes
5090 : logical, optional, intent(in) :: create
5091 : integer(i4), optional, intent(inout) :: ncid
5092 : integer(i4), optional, intent(in) :: nrec
5093 : ! local variables
5094 : logical :: create_loc
5095 : character(256) :: dummy_name
5096 : integer(i4) :: deflate
5097 0 : integer(i4), dimension(:), allocatable :: chunksizes
5098 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
5099 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
5100 : integer(i4) :: idim ! read dimension on append
5101 : integer(i4) :: f_handle
5102 : integer(i4) :: d_unlimit ! index of unlimited dimension
5103 : integer(i4) :: u_dimid ! dimid of unlimited dimension
5104 : integer(i4) :: u_len ! length of unlimited dimension
5105 0 : integer(i4), dimension(:), allocatable :: dims
5106 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
5107 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
5108 : integer(i4) :: i ! loop indices
5109 0 : integer(i4), dimension(:), allocatable :: dummy_count
5110 0 : real(sp), dimension(1) :: dummy ! dummy read
5111 : logical :: openfile ! tmp logical
5112 : !
5113 0 : ndim = size(dnames, 1)
5114 0 : d_unlimit = 0_i4
5115 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
5116 : ! consistency checks
5117 0 : if (ndim .gt. ndim_const) then
5118 0 : print *, '***ERROR more than five dimension names given'
5119 0 : stop '***ERROR see StdOut'
5120 : end if
5121 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
5122 : (d_unlimit .lt. 0_i4)) then
5123 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
5124 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
5125 0 : stop '***ERROR see StdOut'
5126 : end if
5127 : !
5128 0 : allocate(chunksizes(ndim))
5129 0 : allocate(start(ndim))
5130 0 : allocate(counter(ndim))
5131 0 : allocate(dims(ndim))
5132 0 : allocate(dimid(ndim))
5133 0 : allocate(varid(1 + ndim))
5134 0 : allocate(dummy_count(ndim))
5135 : ! initialize
5136 0 : deflate = 1
5137 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), size(arr, 4), size(arr, 5) /)
5138 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
5139 0 : dims(1 : ndim) = shape(arr)
5140 0 : start(:) = 1_i4
5141 0 : counter(:) = dims
5142 0 : dummy_count = 1_i4
5143 0 : dummy = nf90_fill_float
5144 0 : d_unlimit = 0_i4
5145 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
5146 : ! open the netcdf file
5147 0 : if (present(ncid)) then
5148 0 : if (ncid < 0_i4) then
5149 : openfile = .true.
5150 : else
5151 0 : openfile = .false.
5152 0 : f_handle = ncid
5153 : end if
5154 : else
5155 : openfile = .true.
5156 : end if
5157 : if (openfile) then
5158 0 : create_loc = .false.
5159 0 : if (present(create)) create_loc = create
5160 0 : f_handle = open_netcdf(f_name, create = create_loc)
5161 : end if
5162 : ! check whether variable exists
5163 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
5164 : ! append
5165 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
5166 : ! consistency checks
5167 0 : if (idim .ne. ndim) stop "var2nc_5d_sp: number of variable dimensions /= number of file variable dimensions."
5168 : ! check unlimited dimension
5169 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
5170 0 : if (u_dimid .eq. -1) stop 'var2nc_5d_sp: cannot append, no unlimited dimension defined'
5171 : ! check for unlimited dimension
5172 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_5d_sp: unlimited dimension not specified correctly'
5173 0 : if (present(nrec)) then
5174 0 : start(d_unlimit) = nrec
5175 : else
5176 : ! get length of unlimited dimension
5177 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
5178 : ! adapt start, that is find last written chunk
5179 0 : do i = u_len, 1, -1
5180 0 : if (ne(dummy(1), nf90_fill_float)) exit
5181 0 : start(d_unlimit) = i
5182 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
5183 : end do
5184 0 : start(d_unlimit) = start(d_unlimit) + 1
5185 : end if
5186 : else
5187 : ! define dimensions
5188 0 : do i = 1, ndim
5189 : ! check whether dimension exists
5190 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
5191 : ! create dimension
5192 0 : if (i .eq. d_unlimit) then
5193 : ! define unlimited dimension
5194 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
5195 : else
5196 : ! define limited dimension
5197 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
5198 : end if
5199 : end if
5200 : end do
5201 : ! define variable
5202 0 : call check(nf90_def_var(f_handle, v_name, NF90_FLOAT, dimid, varid(ndim + 1), &
5203 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
5204 : ! add attributes
5205 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
5206 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
5207 0 : if (present(missing_value)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'missing_value', missing_value))
5208 0 : if (present(attributes)) then
5209 0 : do i = 1, size(attributes, dim = 1)
5210 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
5211 : ! write number
5212 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
5213 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
5214 0 : trim(attributes(i, 1)), dummy(1)))
5215 : else
5216 : ! write string
5217 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
5218 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
5219 : end if
5220 : end do
5221 : end if
5222 : ! end definition
5223 0 : call check(nf90_enddef(f_handle))
5224 : end if
5225 : ! check dimensions before writing
5226 0 : do i = 1, ndim_const
5227 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
5228 0 : if (trim(dummy_name) .ne. dnames(i)) &
5229 0 : stop "var2nc_5d_sp: dimension name problem."
5230 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
5231 0 : stop "var2nc_5d_sp: variable dimension /= file variable dimension."
5232 : end do
5233 : ! write variable
5234 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
5235 : ! close netcdf_dataset
5236 0 : if (present(ncid)) then
5237 0 : if (ncid < 0_i4) ncid = f_handle
5238 : else
5239 0 : call close_netcdf(f_handle)
5240 : end if
5241 : !
5242 0 : end subroutine var2nc_5d_sp
5243 :
5244 0 : subroutine var2nc_5d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
5245 0 : long_name, units, missing_value, attributes, create, ncid, nrec)
5246 : !
5247 : implicit none
5248 : !
5249 : integer(i4), parameter :: ndim_const = 5
5250 : integer(i4) :: ndim
5251 : ! input variables
5252 : character(len = *), intent(in) :: f_name
5253 : real(dp), dimension(:, :, :, :, :), intent(in) :: arr
5254 : character(len = *), intent(in) :: v_name
5255 : character(len = *), dimension(:), intent(in) :: dnames
5256 : ! optional
5257 : integer(i4), optional, intent(in) :: dim_unlimited
5258 : character(len = *), optional, intent(in) :: long_name
5259 : character(len = *), optional, intent(in) :: units
5260 : real(dp), optional, intent(in) :: missing_value
5261 : character(256), dimension(:, :), optional, intent(in) :: attributes
5262 : logical, optional, intent(in) :: create
5263 : integer(i4), optional, intent(inout) :: ncid
5264 : integer(i4), optional, intent(in) :: nrec
5265 : ! local variables
5266 : logical :: create_loc
5267 : character(256) :: dummy_name
5268 : integer(i4) :: deflate
5269 0 : integer(i4), dimension(:), allocatable :: chunksizes
5270 0 : integer(i4), dimension(:), allocatable :: start ! start array for write
5271 0 : integer(i4), dimension(:), allocatable :: counter ! length array for write
5272 : integer(i4) :: idim ! read dimension on append
5273 : integer(i4) :: f_handle
5274 : integer(i4) :: d_unlimit ! index of unlimited dimension
5275 : integer(i4) :: u_dimid ! dimid of unlimited dimension
5276 : integer(i4) :: u_len ! length of unlimited dimension
5277 0 : integer(i4), dimension(:), allocatable :: dims
5278 0 : integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
5279 0 : integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
5280 : integer(i4) :: i ! loop indices
5281 0 : integer(i4), dimension(:), allocatable :: dummy_count
5282 0 : real(dp), dimension(1) :: dummy ! dummy read
5283 : logical :: openfile ! tmp logical
5284 : !
5285 0 : ndim = size(dnames, 1)
5286 0 : d_unlimit = 0_i4
5287 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
5288 : ! consistency checks
5289 0 : if (ndim .gt. ndim_const) then
5290 0 : print *, '***ERROR more than five dimension names given'
5291 0 : stop '***ERROR see StdOut'
5292 : end if
5293 0 : if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
5294 : (d_unlimit .lt. 0_i4)) then
5295 0 : print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
5296 0 : print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
5297 0 : stop '***ERROR see StdOut'
5298 : end if
5299 : !
5300 0 : allocate(chunksizes(ndim))
5301 0 : allocate(start(ndim))
5302 0 : allocate(counter(ndim))
5303 0 : allocate(dims(ndim))
5304 0 : allocate(dimid(ndim))
5305 0 : allocate(varid(1 + ndim))
5306 0 : allocate(dummy_count(ndim))
5307 : ! initialize
5308 0 : deflate = 1
5309 0 : chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), size(arr, 4), size(arr, 5) /)
5310 0 : if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
5311 0 : dims(1 : ndim) = shape(arr)
5312 0 : start(:) = 1_i4
5313 0 : counter(:) = dims
5314 0 : dummy_count = 1
5315 0 : dummy = nf90_fill_double
5316 0 : d_unlimit = 0_i4
5317 0 : if (present(dim_unlimited)) d_unlimit = dim_unlimited
5318 : ! open the netcdf file
5319 0 : if (present(ncid)) then
5320 0 : if (ncid < 0_i4) then
5321 : openfile = .true.
5322 : else
5323 0 : openfile = .false.
5324 0 : f_handle = ncid
5325 : end if
5326 : else
5327 : openfile = .true.
5328 : end if
5329 : if (openfile) then
5330 0 : create_loc = .false.
5331 0 : if (present(create)) create_loc = create
5332 0 : f_handle = open_netcdf(f_name, create = create_loc)
5333 : end if
5334 : ! check whether variable exists
5335 0 : if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
5336 : ! append
5337 0 : call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
5338 : ! consistency checks
5339 0 : if (idim .ne. ndim) stop "var2nc_5d_dp: number of variable dimensions /= number of file variable dimensions."
5340 : ! check unlimited dimension
5341 0 : call check(nf90_inquire(f_handle, unlimitedDimId = u_dimid))
5342 0 : if (u_dimid .eq. -1) stop 'var2nc_5d_dp: cannot append, no unlimited dimension defined'
5343 : ! check for unlimited dimension
5344 0 : if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_5d_dp: unlimited dimension not specified correctly'
5345 0 : if (present(nrec)) then
5346 0 : start(d_unlimit) = nrec
5347 : else
5348 : ! get length of unlimited dimension
5349 0 : call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
5350 : ! adapt start, that is find last written chunk
5351 0 : do i = u_len, 1, -1
5352 0 : if (ne(dummy(1), nf90_fill_double)) exit
5353 0 : start(d_unlimit) = i
5354 0 : call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
5355 : end do
5356 0 : start(d_unlimit) = start(d_unlimit) + 1
5357 : end if
5358 : else
5359 : ! define dimensions
5360 0 : do i = 1, ndim
5361 : ! check whether dimension exists
5362 0 : if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
5363 : ! create dimension
5364 0 : if (i .eq. d_unlimit) then
5365 : ! define unlimited dimension
5366 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), NF90_UNLIMITED, dimid(i)))
5367 : else
5368 : ! define limited dimension
5369 0 : call check(nf90_def_dim(f_handle, trim(dnames(i)), dims(i), dimid(i)))
5370 : end if
5371 : end if
5372 : end do
5373 : ! define variable
5374 0 : call check(nf90_def_var(f_handle, v_name, NF90_DOUBLE, dimid, varid(ndim + 1), &
5375 0 : chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
5376 : ! add attributes
5377 0 : if (present(long_name)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'long_name', long_name))
5378 0 : if (present(units)) call check(nf90_put_att (f_handle, varid(ndim + 1), 'units', units))
5379 0 : if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
5380 0 : if (present(attributes)) then
5381 0 : do i = 1, size(attributes, dim = 1)
5382 0 : if (trim(attributes(i, 1)) .eq. 'missing_value') then
5383 : ! write number
5384 0 : read(attributes(i, 2), '(F10.2)') dummy(1)
5385 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
5386 0 : trim(attributes(i, 1)), dummy(1)))
5387 : else
5388 : ! write string
5389 0 : call check(nf90_put_att(f_handle, varid(ndim + 1), &
5390 0 : trim(attributes(i, 1)), trim(attributes(i, 2))))
5391 : end if
5392 : end do
5393 : end if
5394 : ! end definition
5395 0 : call check(nf90_enddef(f_handle))
5396 : end if
5397 : ! check dimensions before writing
5398 0 : do i = 1, ndim_const
5399 0 : call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
5400 0 : if (trim(dummy_name) .ne. dnames(i)) &
5401 0 : stop "var2nc_5d_dp: dimension name problem."
5402 0 : if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
5403 0 : stop "var2nc_5d_dp: variable dimension /= file variable dimension."
5404 : end do
5405 : ! write variable
5406 0 : call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
5407 : ! close netcdf_dataset
5408 0 : if (present(ncid)) then
5409 0 : if (ncid < 0_i4) ncid = f_handle
5410 : else
5411 0 : call close_netcdf(f_handle)
5412 : end if
5413 : !
5414 0 : end subroutine var2nc_5d_dp
5415 :
5416 : ! ----------------------------------------------------------------------------
5417 : !> \brief dynamic writer
5418 : !> \details This routine writes data, where one dimension has the unlimited attribute.
5419 : !! Therefore, the number of the record which should be written has to be
5420 : !! specified.
5421 : !! See: http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-f90.html
5422 :
5423 : !> \param[in] "integer(i4) :: nc" stream id of an open netcdf file where data should be written
5424 : !! can be obtained by an create_netcdf call
5425 : !> \param[in] "integer(i4) :: rec" record id of record which will be written in the file
5426 :
5427 : !> \note Writes only data, where the data pointers of the structure V are assigned
5428 : !! and where one dimension has the unlimited attribute. Moreover only one
5429 : !! record will be written.
5430 : !! Writes only 1 to 4 dim arrays, integer, single or double precision.
5431 :
5432 : !> \author Luis Samaniego
5433 : !> \date Feb 2011
5434 : !> \author Stephan Thober
5435 : !> \date Dec 2011
5436 : !! - added comments and generalized
5437 : !> \author Matthias Cuntz
5438 : !> \date Jan 2012
5439 : !! - Info
5440 : !> \author Stephan Thober
5441 : !> \date Jan 2012
5442 : !! - iRec is not optional
5443 : !> \author Matthias Cuntz
5444 : !> \date Mar 2013
5445 : !! - removed Info
5446 0 : subroutine write_dynamic_netcdf(ncId, irec)
5447 :
5448 : implicit none
5449 :
5450 : ! netcdf related variables
5451 : integer(i4), intent(in) :: ncId
5452 : integer(i4), intent(in) :: iRec
5453 :
5454 : integer(i4) :: i
5455 : ! NOTES: 1) netcdf file must be on *** data mode ***
5456 : ! 2) start and end of the data chuck is controled by
5457 : ! V(:)%start and V(:)%count
5458 :
5459 : ! set values for variables (one scalar or grid at a time)
5460 :
5461 0 : do i = 1, nVars
5462 0 : if (.not. V(i)%unlimited) cycle
5463 0 : if (.not. V(i)%wFlag) cycle
5464 0 : V(i)%start (V(i)%nDims) = iRec
5465 0 : select case (V(i)%xtype)
5466 : case(NF90_BYTE)
5467 0 : select case (V(i)%nDims)
5468 : case (0)
5469 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G0_b, V(i)%start))
5470 : case (1)
5471 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G1_b, V(i)%start, V(i)%count))
5472 : case (2)
5473 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G2_b, V(i)%start, V(i)%count))
5474 : case (3)
5475 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G3_b, V(i)%start, V(i)%count))
5476 : case (4)
5477 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G4_b, V(i)%start, V(i)%count))
5478 : end select
5479 : case (NF90_INT)
5480 0 : select case (V(i)%nDims - 1)
5481 : case (0)
5482 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G0_i, V(i)%start))
5483 : case (1)
5484 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G1_i, V(i)%start, V(i)%count))
5485 : case (2)
5486 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G2_i, V(i)%start, V(i)%count))
5487 : case (3)
5488 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G3_i, V(i)%start, V(i)%count))
5489 : case (4)
5490 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G4_i, V(i)%start, V(i)%count))
5491 : end select
5492 : case (NF90_FLOAT)
5493 0 : select case (V(i)%nDims - 1)
5494 : case (0)
5495 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G0_f, V(i)%start))
5496 : case (1)
5497 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G1_f, V(i)%start, V(i)%count))
5498 : case (2)
5499 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G2_f, V(i)%start, V(i)%count))
5500 : case (3)
5501 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G3_f, V(i)%start, V(i)%count))
5502 : case (4)
5503 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G4_f, V(i)%start, V(i)%count))
5504 : end select
5505 : case (NF90_DOUBLE)
5506 0 : select case (V(i)%nDims - 1)
5507 : case (0)
5508 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G0_d, V(i)%start))
5509 : case (1)
5510 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G1_d, V(i)%start, V(i)%count))
5511 : case (2)
5512 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G2_d, V(i)%start, V(i)%count))
5513 : case (3)
5514 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G3_d, V(i)%start, V(i)%count))
5515 : case (4)
5516 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G4_d, V(i)%start, V(i)%count))
5517 : end select
5518 : end select
5519 : end do
5520 :
5521 0 : end subroutine write_dynamic_netcdf
5522 :
5523 : ! ----------------------------------------------------------------------------
5524 : !> \brief static writer
5525 : !> \details This routines writes static data in the netcdf file that is data
5526 : !! where no dimension has the unlimited attribute.
5527 : !! See: http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-f90.html
5528 :
5529 : !> \param[in] "integer(i4) :: ncid" stream id of an open netcdf file where data should be written
5530 : !! can be obtained by an create_netcdf call
5531 :
5532 : !> \note Writes only data, where the data pointers of the structure V are assigned.
5533 : !! Writes only 1 to 4 dim arrays, integer, single or double precision.
5534 :
5535 : ! HISTORY
5536 : !> \author Luis Samaniego
5537 : !> \date Feb 2011
5538 : !> \author Stephan Thober
5539 : !> \date Dec 2011
5540 : !! - added comments and generalized
5541 : !> \author Matthias Cuntz
5542 : !> \date Jan 2012
5543 : !! - Info
5544 : !> \author Matthias Cuntz
5545 : !> \date Mar 2013
5546 : !! - removed Info
5547 :
5548 0 : subroutine write_static_netcdf(ncId)
5549 :
5550 : implicit none
5551 :
5552 : ! netcdf related variables
5553 : integer(i4), intent(in) :: ncId
5554 :
5555 : integer(i4) :: i
5556 :
5557 : ! write all static variables
5558 0 : do i = 1, nVars
5559 0 : if (V(i)%unlimited) cycle
5560 0 : if (.not. V(i)%wFlag) cycle
5561 0 : select case (V(i)%xtype)
5562 : case(NF90_BYTE)
5563 0 : select case (V(i)%nDims)
5564 : case (0)
5565 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G0_b))
5566 : case (1)
5567 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G1_b))
5568 : case (2)
5569 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G2_b))
5570 : case (3)
5571 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G3_b))
5572 : case (4)
5573 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G4_b))
5574 : end select
5575 : case (NF90_INT)
5576 0 : select case (V(i)%nDims)
5577 : case (0)
5578 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G0_i))
5579 : case (1)
5580 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G1_i))
5581 : case (2)
5582 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G2_i))
5583 : case (3)
5584 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G3_i))
5585 : case (4)
5586 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G4_i))
5587 : end select
5588 : case (NF90_FLOAT)
5589 0 : select case (V(i)%nDims)
5590 : case (0)
5591 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G0_f))
5592 : case (1)
5593 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G1_f))
5594 : case (2)
5595 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G2_f))
5596 : case (3)
5597 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G3_f))
5598 : case (4)
5599 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G4_f))
5600 : end select
5601 : case (NF90_DOUBLE)
5602 0 : select case (V(i)%nDims)
5603 : case (0)
5604 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G0_d))
5605 : case (1)
5606 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G1_d))
5607 : case (2)
5608 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G2_d))
5609 : case (3)
5610 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G3_d))
5611 : case (4)
5612 0 : call check(nf90_put_var(ncId, V(i)%varId, V(i)%G4_d))
5613 : end select
5614 : end select
5615 : end do
5616 :
5617 0 : end subroutine write_static_netcdf
5618 :
5619 : ! -----------------------------------------------------------------------------
5620 : ! PRIVATE PART
5621 : !
5622 :
5623 : ! -----------------------------------------------------------------------------
5624 :
5625 : ! private open netcdf function - returns file handle
5626 0 : function open_netcdf(f_name, create)
5627 : implicit none
5628 : ! input variables
5629 : character(len = *), intent(in) :: f_name
5630 : logical, intent(in) :: create ! flag indicates that file exists
5631 : ! output variables
5632 : integer(i4) :: open_netcdf
5633 : !
5634 0 : if (create) then
5635 : ! create file
5636 0 : call check(nf90_create(trim(f_name), NF90_NETCDF4, open_netcdf))
5637 : else
5638 : ! open file
5639 0 : call check(nf90_open(trim(f_name), NF90_WRITE, open_netcdf))
5640 : end if
5641 0 : end function open_netcdf
5642 :
5643 :
5644 : ! -----------------------------------------------------------------------------
5645 :
5646 : ! private error checking routine
5647 240 : subroutine check(status)
5648 :
5649 : implicit none
5650 :
5651 : integer(i4), intent(in) :: status
5652 :
5653 240 : if (status /= nf90_noerr) then
5654 0 : write(*, *) 'mo_ncwrite.check error: ', trim(nf90_strerror(status))
5655 0 : stop
5656 : end if
5657 :
5658 0 : end subroutine check
5659 :
5660 : ! -----------------------------------------------------------------------------
5661 :
5662 240 : end module mo_ncwrite
|