0.6.2-dev0
FORCES
FORtran lib for Comp. Env. Sys.
Loading...
Searching...
No Matches
mo_ncwrite.f90
Go to the documentation of this file.
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
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
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
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
317contains
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 subroutine close_netcdf(ncId)
352
353 implicit none
354
355 integer(i4), intent(in) :: ncid
356
357 ! close: save new netcdf dataset
358 call check(nf90_close(ncid))
359
360 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 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 real(sp), dimension(nAttDim) :: att_float
418 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 integer(i4), dimension(:), allocatable :: chunksizes ! Size of chunks in netcdf4 writing
425
426 largefile = .false.
427 if (present(lfs)) largefile = lfs
428 inetcdf4 = .true.
429 if (present(netcdf4)) inetcdf4 = netcdf4
430 deflate = 1
431 if (present(deflate_level)) deflate = deflate_level
432 ! 1 Create netcdf dataset: enter define mode -> get ncId
433 if (inetcdf4) then
434 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
435 else
436 if (largefile) then
437 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 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 do i = 1, ndims
446 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 do i = 1, nvars
452 v(i)%unlimited = .false.
453 v(i)%dimids = 0
454 v(i)%start = 1
455 v(i)%count = 1
456 do k = 1, v(i)%nDims
457 if (dnc(v(i)%dimTypes(k))%len == nf90_unlimited) v(i)%unlimited = .true.
458 v(i)%dimids(k) = dnc(v(i)%dimTypes(k))%dimId
459 end do
460 if (v(i)%unlimited) then
461 ! set counts for unlimited files (time is always the last dimension)
462 if (v(i)%nDims == 1) cycle
463 do k = 1, v(i)%nDims - 1
464 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 allocate(chunksizes(maxval(v(1 : nvars)%nDims)))
471 do i = 1, nvars
472 if (.not. v(i)%wFlag) cycle
473 if (inetcdf4) then
474 chunksizes(1 : v(i)%nDims) = dnc(v(i)%dimTypes(1 : v(i)%nDims))%len
475 chunksizes(v(i)%nDims) = 1
476 call check(nf90_def_var(ncid, v(i)%name, v(i)%xtype, v(i)%dimids(1 : v(i)%nDims), v(i)%varId, &
477 chunksizes = chunksizes(1 : v(i)%nDims), shuffle = .true., deflate_level = deflate))
478 else
479 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 do k = 1, v(i)%nAtt
482 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 read(v(i)%att(k)%values, '(a)') att_char(1)
486 call check(nf90_put_att(ncid, v(i)%varId, v(i)%att(k)%name, att_char(1)))
487 case (nf90_int)
488 read(v(i)%att(k)%values, *) (att_int(j), j = 1, v(i)%att(k)%nValues)
489 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 read(v(i)%att(k)%values, *) (att_float(j), j = 1, v(i)%att(k)%nValues)
492 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 read(v(i)%att(k)%values, *) (att_double(j), j = 1, v(i)%att(k)%nValues)
495 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 do k = 1, ngatt
502 if (nonull(gatt(k)%name)) then
503 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 call check(nf90_enddef(ncid))
509
510 deallocate(chunksizes)
511
512 end subroutine create_netcdf
513
514
515 ! ------------------------------------------------------------------
516
517 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 if (present(append)) then
548 if (append) then
549 iappend = .true.
550 else
551 iappend = .false.
552 end if
553 else
554 iappend = .false.
555 end if
556 largefile = .false.
557 if (present(lfs)) largefile = lfs
558 inetcdf4 = .false.
559 if (present(netcdf4)) inetcdf4 = netcdf4
560 deflate = 1
561 if (present(deflate_level)) deflate = deflate_level
562
563 ! dimension names
564 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
565
566 if (iappend) then
567 ! open file
568 call check(nf90_open(trim(filename), nf90_write, ncid))
569
570 ! inquire variables time and var
571 call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
572 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
573 call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
574 if (idim /= ndim + 1) stop "dump_netcdf_1d_sp: number of variable dimensions /= number of file variable dimensions."
575
576 ! inquire dimensions
577 do i = 1, ndim + 1
578 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
579 if (i < ndim + 1) then
580 if (trim(name) /= dnames(i)) stop "dump_netcdf_1d_sp: dimension name problem."
581 if (dims(i) /= size(arr, i)) stop "dump_netcdf_1d_sp: variable dimension /= file variable dimension."
582 else
583 if (trim(name) /= 'time') stop "dump_netcdf_1d_sp: time name problem."
584 end if
585 enddo
586
587 ! append
588 start(:) = 1
589 counter(:) = dims
590 counter(ndim + 1) = 1
591 do i = 1, 1
592 start(ndim + 1) = dims(ndim + 1) + i
593 call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
594 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
595 end do
596 else
597 ! open file
598 if (inetcdf4) then
599 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
600 else
601 if (largefile) then
602 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
603 else
604 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
605 end if
606 end if
607
608 ! define dims
609 dims(1 : ndim) = shape(arr)
610 do i = 1, ndim
611 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
612 end do
613 ! define dim time
614 dims(ndim + 1) = 1
615 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim + 1)))
616
617 ! define dim variables
618 do i = 1, ndim
619 if (inetcdf4) then
620 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
621 else
622 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 if (inetcdf4) then
627 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
628 else
629 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
630 end if
631
632 ! define variable
633 if (inetcdf4) then
634 chunksizes(1 : ndim) = dims(1 : ndim)
635 chunksizes(ndim + 1) = 1
636 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 2), &
637 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
638 else
639 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 2)))
640 end if
641
642 ! end define mode
643 call check(nf90_enddef(ncid))
644
645 ! write dimensions
646 do i = 1, ndim
647 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
648 end do
649
650 ! write time and variable
651 start(:) = 1
652 counter(:) = dims
653 counter(ndim + 1) = 1
654 do i = 1, 1
655 start(ndim + 1) = i
656 call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
657 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
658 end do
659 end if
660
661 ! close netcdf file
662 call check(nf90_close(ncid))
663
664 end subroutine dump_netcdf_1d_sp
665
666
667 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 if (present(append)) then
698 if (append) then
699 iappend = .true.
700 else
701 iappend = .false.
702 end if
703 else
704 iappend = .false.
705 end if
706 largefile = .false.
707 if (present(lfs)) largefile = lfs
708 inetcdf4 = .false.
709 if (present(netcdf4)) inetcdf4 = netcdf4
710 deflate = 1
711 if (present(deflate_level)) deflate = deflate_level
712
713 ! dimension names
714 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
715
716 if (iappend) then
717 ! open file
718 call check(nf90_open(trim(filename), nf90_write, ncid))
719
720 ! inquire variables time and var
721 call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
722 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
723 call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
724 if (idim /= ndim + 1) stop "dump_netcdf_2d_sp: number of variable dimensions /= number of file variable dimensions."
725
726 ! inquire dimensions
727 do i = 1, ndim + 1
728 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
729 if (i < ndim + 1) then
730 if (trim(name) /= dnames(i)) stop "dump_netcdf_2d_sp: dimension name problem."
731 if (dims(i) /= size(arr, i)) stop "dump_netcdf_2d_sp: variable dimension /= file variable dimension."
732 else
733 if (trim(name) /= 'time') stop "dump_netcdf_2d_sp: time name problem."
734 end if
735 enddo
736
737 ! append
738 start(:) = 1
739 counter(:) = dims
740 counter(ndim + 1) = 1
741 do i = 1, 1
742 start(ndim + 1) = dims(ndim + 1) + i
743 call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
744 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
745 end do
746 else
747 ! open file
748 if (inetcdf4) then
749 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
750 else
751 if (largefile) then
752 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
753 else
754 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
755 end if
756 end if
757
758 ! define dims
759 dims(1 : ndim) = shape(arr)
760 do i = 1, ndim
761 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
762 end do
763 ! define dim time
764 dims(ndim + 1) = 1
765 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim + 1)))
766
767 ! define dim variables
768 do i = 1, ndim
769 if (inetcdf4) then
770 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
771 else
772 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 if (inetcdf4) then
777 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
778 else
779 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
780 end if
781
782 ! define variable
783 if (inetcdf4) then
784 chunksizes(1 : ndim) = dims(1 : ndim)
785 chunksizes(ndim + 1) = 1
786 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 2), &
787 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
788 else
789 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 2)))
790 end if
791
792 ! end define mode
793 call check(nf90_enddef(ncid))
794
795 ! write dimensions
796 do i = 1, ndim
797 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
798 end do
799
800 ! write time and variable
801 start(:) = 1
802 counter(:) = dims
803 counter(ndim + 1) = 1
804 do i = 1, 1
805 start(ndim + 1) = i
806 call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
807 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
808 end do
809 end if
810
811 ! close netcdf file
812 call check(nf90_close(ncid))
813
814 end subroutine dump_netcdf_2d_sp
815
816
817 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 if (present(append)) then
848 if (append) then
849 iappend = .true.
850 else
851 iappend = .false.
852 end if
853 else
854 iappend = .false.
855 end if
856 largefile = .false.
857 if (present(lfs)) largefile = lfs
858 inetcdf4 = .false.
859 if (present(netcdf4)) inetcdf4 = netcdf4
860 deflate = 1
861 if (present(deflate_level)) deflate = deflate_level
862
863 ! dimension names
864 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
865
866 if (iappend) then
867 ! open file
868 call check(nf90_open(trim(filename), nf90_write, ncid))
869
870 ! inquire variables time and var
871 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
872 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
873 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
874 if (idim /= ndim) stop "dump_netcdf_3d_sp: number of variable dimensions /= number of file variable dimensions."
875
876 ! inquire dimensions
877 do i = 1, ndim
878 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
879 if (i < ndim) then
880 if (trim(name) /= dnames(i)) stop "dump_netcdf_3d_sp: dimension name problem."
881 if (dims(i) /= size(arr, i)) stop "dump_netcdf_3d_sp: variable dimension /= file variable dimension."
882 else
883 if (trim(name) /= 'time') stop "dump_netcdf_3d_sp: time name problem."
884 end if
885 enddo
886
887 ! append
888 start(:) = 1
889 counter(:) = dims
890 counter(ndim) = 1
891 do i = 1, size(arr, ndim)
892 start(ndim) = dims(ndim) + i
893 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
894 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
895 end do
896 else
897 ! open file
898 if (inetcdf4) then
899 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
900 else
901 if (largefile) then
902 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
903 else
904 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
905 end if
906 end if
907
908 ! define dims
909 dims = shape(arr)
910 do i = 1, ndim - 1
911 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
912 end do
913 ! define dim time
914 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
915
916 ! define dim variables
917 do i = 1, ndim - 1
918 if (inetcdf4) then
919 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
920 else
921 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 if (inetcdf4) then
926 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
927 else
928 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
929 end if
930
931 ! define variable
932 if (inetcdf4) then
933 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
934 chunksizes(ndim) = 1
935 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 1), &
936 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
937 else
938 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 1)))
939 end if
940
941 ! end define mode
942 call check(nf90_enddef(ncid))
943
944 ! write dimensions
945 do i = 1, ndim - 1
946 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
947 end do
948
949 ! write time and variable
950 start(:) = 1
951 counter(:) = dims
952 counter(ndim) = 1
953 do i = 1, dims(ndim)
954 start(ndim) = i
955 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
956 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 call check(nf90_close(ncid))
962
963 end subroutine dump_netcdf_3d_sp
964
965
966 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 if (present(append)) then
997 if (append) then
998 iappend = .true.
999 else
1000 iappend = .false.
1001 end if
1002 else
1003 iappend = .false.
1004 end if
1005 largefile = .false.
1006 if (present(lfs)) largefile = lfs
1007 inetcdf4 = .false.
1008 if (present(netcdf4)) inetcdf4 = netcdf4
1009 deflate = 1
1010 if (present(deflate_level)) deflate = deflate_level
1011
1012 ! dimension names
1013 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1014
1015 if (iappend) then
1016 ! open file
1017 call check(nf90_open(trim(filename), nf90_write, ncid))
1018
1019 ! inquire variables time and var
1020 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1021 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1022 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1023 if (idim /= ndim) stop "dump_netcdf_4d_sp: number of variable dimensions /= number of file variable dimensions."
1024
1025 ! inquire dimensions
1026 do i = 1, ndim
1027 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1028 if (i < ndim) then
1029 if (trim(name) /= dnames(i)) stop "dump_netcdf_4d_sp: dimension name problem."
1030 if (dims(i) /= size(arr, i)) stop "dump_netcdf_4d_sp: variable dimension /= file variable dimension."
1031 else
1032 if (trim(name) /= 'time') stop "dump_netcdf_4d_sp: time name problem."
1033 end if
1034 enddo
1035
1036 ! append
1037 start(:) = 1
1038 counter(:) = dims
1039 counter(ndim) = 1
1040 do i = 1, size(arr, ndim)
1041 start(ndim) = dims(ndim) + i
1042 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1043 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
1044 end do
1045 else
1046 ! open file
1047 if (inetcdf4) then
1048 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
1049 else
1050 if (largefile) then
1051 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
1052 else
1053 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
1054 end if
1055 end if
1056
1057 ! define dims
1058 dims = shape(arr)
1059 do i = 1, ndim - 1
1060 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1061 end do
1062 ! define dim time
1063 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
1064
1065 ! define dim variables
1066 do i = 1, ndim - 1
1067 if (inetcdf4) then
1068 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
1069 else
1070 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 if (inetcdf4) then
1075 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1076 else
1077 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1078 end if
1079
1080 ! define variable
1081 if (inetcdf4) then
1082 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1083 chunksizes(ndim) = 1
1084 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 1), &
1085 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1086 else
1087 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 1)))
1088 end if
1089
1090 ! end define mode
1091 call check(nf90_enddef(ncid))
1092
1093 ! write dimensions
1094 do i = 1, ndim - 1
1095 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1096 end do
1097
1098 ! write time and variable
1099 start(:) = 1
1100 counter(:) = dims
1101 counter(ndim) = 1
1102 do i = 1, dims(ndim)
1103 start(ndim) = i
1104 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
1105 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 call check(nf90_close(ncid))
1111
1112 end subroutine dump_netcdf_4d_sp
1113
1114
1115 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 if (present(append)) then
1146 if (append) then
1147 iappend = .true.
1148 else
1149 iappend = .false.
1150 end if
1151 else
1152 iappend = .false.
1153 end if
1154 largefile = .false.
1155 if (present(lfs)) largefile = lfs
1156 inetcdf4 = .false.
1157 if (present(netcdf4)) inetcdf4 = netcdf4
1158 deflate = 1
1159 if (present(deflate_level)) deflate = deflate_level
1160
1161 ! dimension names
1162 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1163
1164 if (iappend) then
1165 ! open file
1166 call check(nf90_open(trim(filename), nf90_write, ncid))
1167
1168 ! inquire variables time and var
1169 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1170 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1171 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1172 if (idim /= ndim) stop "dump_netcdf_5d_sp: number of variable dimensions /= number of file variable dimensions."
1173
1174 ! inquire dimensions
1175 do i = 1, ndim
1176 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1177 if (i < ndim) then
1178 if (trim(name) /= dnames(i)) stop "dump_netcdf_5d_sp: dimension name problem."
1179 if (dims(i) /= size(arr, i)) stop "dump_netcdf_5d_sp: variable dimension /= file variable dimension."
1180 else
1181 if (trim(name) /= 'time') stop "dump_netcdf_5d_sp: time name problem."
1182 end if
1183 enddo
1184
1185 ! append
1186 start(:) = 1
1187 counter(:) = dims
1188 counter(ndim) = 1
1189 do i = 1, size(arr, ndim)
1190 start(ndim) = dims(ndim) + i
1191 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1192 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
1193 end do
1194 else
1195 ! open file
1196 if (inetcdf4) then
1197 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
1198 else
1199 if (largefile) then
1200 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
1201 else
1202 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
1203 end if
1204 end if
1205
1206 ! define dims
1207 dims = shape(arr)
1208 do i = 1, ndim - 1
1209 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1210 end do
1211 ! define dim time
1212 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
1213
1214 ! define dim variables
1215 do i = 1, ndim - 1
1216 if (inetcdf4) then
1217 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
1218 else
1219 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 if (inetcdf4) then
1224 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1225 else
1226 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1227 end if
1228
1229 ! define variable
1230 if (inetcdf4) then
1231 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1232 chunksizes(ndim) = 1
1233 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 1), &
1234 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1235 else
1236 call check(nf90_def_var(ncid, 'var', nf90_float, dimid, varid(ndim + 1)))
1237 end if
1238
1239 ! end define mode
1240 call check(nf90_enddef(ncid))
1241
1242 ! write dimensions
1243 do i = 1, ndim - 1
1244 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1245 end do
1246
1247 ! write time and variable
1248 start(:) = 1
1249 counter(:) = dims
1250 counter(ndim) = 1
1251 do i = 1, dims(ndim)
1252 start(ndim) = i
1253 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
1254 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 call check(nf90_close(ncid))
1260
1261 end subroutine dump_netcdf_5d_sp
1262
1263
1264 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 if (present(append)) then
1295 if (append) then
1296 iappend = .true.
1297 else
1298 iappend = .false.
1299 end if
1300 else
1301 iappend = .false.
1302 end if
1303 largefile = .false.
1304 if (present(lfs)) largefile = lfs
1305 inetcdf4 = .false.
1306 if (present(netcdf4)) inetcdf4 = netcdf4
1307 deflate = 1
1308 if (present(deflate_level)) deflate = deflate_level
1309
1310 ! dimension names
1311 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1312
1313 if (iappend) then
1314 ! open file
1315 call check(nf90_open(trim(filename), nf90_write, ncid))
1316
1317 ! inquire variables time and var
1318 call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
1319 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
1320 call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
1321 if (idim /= ndim + 1) stop "dump_netcdf_1d_dp: number of variable dimensions /= number of file variable dimensions."
1322
1323 ! inquire dimensions
1324 do i = 1, ndim + 1
1325 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1326 if (i < ndim + 1) then
1327 if (trim(name) /= dnames(i)) stop "dump_netcdf_1d_dp: dimension name problem."
1328 if (dims(i) /= size(arr, i)) stop "dump_netcdf_1d_dp: variable dimension /= file variable dimension."
1329 else
1330 if (trim(name) /= 'time') stop "dump_netcdf_1d_dp: time name problem."
1331 end if
1332 enddo
1333
1334 ! append
1335 start(:) = 1
1336 counter(:) = dims
1337 counter(ndim + 1) = 1
1338 do i = 1, 1
1339 start(ndim + 1) = dims(ndim + 1) + i
1340 call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
1341 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
1342 end do
1343 else
1344 ! open file
1345 if (inetcdf4) then
1346 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
1347 else
1348 if (largefile) then
1349 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
1350 else
1351 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
1352 end if
1353 end if
1354
1355 ! define dims
1356 dims(1 : ndim) = shape(arr)
1357 do i = 1, ndim
1358 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1359 end do
1360 ! define dim time
1361 dims(ndim + 1) = 1
1362 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim + 1)))
1363
1364 ! define dim variables
1365 do i = 1, ndim
1366 if (inetcdf4) then
1367 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
1368 else
1369 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 if (inetcdf4) then
1374 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
1375 else
1376 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
1377 end if
1378
1379 ! define variable
1380 if (inetcdf4) then
1381 chunksizes(1 : ndim) = dims(1 : ndim)
1382 chunksizes(ndim + 1) = 1
1383 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 2), &
1384 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1385 else
1386 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 2)))
1387 end if
1388
1389 ! end define mode
1390 call check(nf90_enddef(ncid))
1391
1392 ! write dimensions
1393 do i = 1, ndim
1394 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1395 end do
1396
1397 ! write time and variable
1398 start(:) = 1
1399 counter(:) = dims
1400 counter(ndim + 1) = 1
1401 do i = 1, 1
1402 start(ndim + 1) = i
1403 call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
1404 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
1405 end do
1406 end if
1407
1408 ! close netcdf file
1409 call check(nf90_close(ncid))
1410
1411 end subroutine dump_netcdf_1d_dp
1412
1413
1414 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 if (present(append)) then
1445 if (append) then
1446 iappend = .true.
1447 else
1448 iappend = .false.
1449 end if
1450 else
1451 iappend = .false.
1452 end if
1453 largefile = .false.
1454 if (present(lfs)) largefile = lfs
1455 inetcdf4 = .false.
1456 if (present(netcdf4)) inetcdf4 = netcdf4
1457 deflate = 1
1458 if (present(deflate_level)) deflate = deflate_level
1459
1460 ! dimension names
1461 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1462
1463 if (iappend) then
1464 ! open file
1465 call check(nf90_open(trim(filename), nf90_write, ncid))
1466
1467 ! inquire variables time and var
1468 call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
1469 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
1470 call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
1471 if (idim /= ndim + 1) stop "dump_netcdf_2d_dp: number of variable dimensions /= number of file variable dimensions."
1472
1473 ! inquire dimensions
1474 do i = 1, ndim + 1
1475 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1476 if (i < ndim + 1) then
1477 if (trim(name) /= dnames(i)) stop "dump_netcdf_2d_dp: dimension name problem."
1478 if (dims(i) /= size(arr, i)) stop "dump_netcdf_2d_dp: variable dimension /= file variable dimension."
1479 else
1480 if (trim(name) /= 'time') stop "dump_netcdf_2d_dp: time name problem."
1481 end if
1482 enddo
1483
1484 ! append
1485 start(:) = 1
1486 counter(:) = dims
1487 counter(ndim + 1) = 1
1488 do i = 1, 1
1489 start(ndim + 1) = dims(ndim + 1) + i
1490 call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
1491 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
1492 end do
1493 else
1494 ! open file
1495 if (inetcdf4) then
1496 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
1497 else
1498 if (largefile) then
1499 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
1500 else
1501 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
1502 end if
1503 end if
1504
1505 ! define dims
1506 dims(1 : ndim) = shape(arr)
1507 do i = 1, ndim
1508 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1509 end do
1510 ! define dim time
1511 dims(ndim + 1) = 1
1512 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim + 1)))
1513
1514 ! define dim variables
1515 do i = 1, ndim
1516 if (inetcdf4) then
1517 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
1518 else
1519 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 if (inetcdf4) then
1524 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
1525 else
1526 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
1527 end if
1528
1529 ! define variable
1530 if (inetcdf4) then
1531 chunksizes(1 : ndim) = dims(1 : ndim)
1532 chunksizes(ndim + 1) = 1
1533 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 2), &
1534 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1535 else
1536 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 2)))
1537 end if
1538
1539 ! end define mode
1540 call check(nf90_enddef(ncid))
1541
1542 ! write dimensions
1543 do i = 1, ndim
1544 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1545 end do
1546
1547 ! write time and variable
1548 start(:) = 1
1549 counter(:) = dims
1550 counter(ndim + 1) = 1
1551 do i = 1, 1
1552 start(ndim + 1) = i
1553 call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
1554 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
1555 end do
1556 end if
1557
1558 ! close netcdf file
1559 call check(nf90_close(ncid))
1560
1561 end subroutine dump_netcdf_2d_dp
1562
1563
1564 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 if (present(append)) then
1595 if (append) then
1596 iappend = .true.
1597 else
1598 iappend = .false.
1599 end if
1600 else
1601 iappend = .false.
1602 end if
1603 largefile = .false.
1604 if (present(lfs)) largefile = lfs
1605 inetcdf4 = .false.
1606 if (present(netcdf4)) inetcdf4 = netcdf4
1607 deflate = 1
1608 if (present(deflate_level)) deflate = deflate_level
1609
1610 ! dimension names
1611 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1612
1613 if (iappend) then
1614 ! open file
1615 call check(nf90_open(trim(filename), nf90_write, ncid))
1616
1617 ! inquire variables time and var
1618 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1619 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1620 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1621 if (idim /= ndim) stop "dump_netcdf_3d_dp: number of variable dimensions /= number of file variable dimensions."
1622
1623 ! inquire dimensions
1624 do i = 1, ndim
1625 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1626 if (i < ndim) then
1627 if (trim(name) /= dnames(i)) stop "dump_netcdf_3d_dp: dimension name problem."
1628 if (dims(i) /= size(arr, i)) stop "dump_netcdf_3d_dp: variable dimension /= file variable dimension."
1629 else
1630 if (trim(name) /= 'time') stop "dump_netcdf_3d_dp: time name problem."
1631 end if
1632 enddo
1633
1634 ! append
1635 start(:) = 1
1636 counter(:) = dims
1637 counter(ndim) = 1
1638 do i = 1, size(arr, ndim)
1639 start(ndim) = dims(ndim) + i
1640 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1641 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
1642 end do
1643 else
1644 ! open file
1645 if (inetcdf4) then
1646 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
1647 ! call check(nf90_set_fill(ncid, NF90_NOFILL, old_fill_mode))
1648 else
1649 if (largefile) then
1650 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
1651 else
1652 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
1653 end if
1654 end if
1655
1656 ! define dims
1657 dims = shape(arr)
1658 do i = 1, ndim - 1
1659 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1660 end do
1661 ! define dim time
1662 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
1663
1664 ! define dim variables
1665 do i = 1, ndim - 1
1666 if (inetcdf4) then
1667 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
1668 else
1669 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 if (inetcdf4) then
1674 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1675 else
1676 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1677 end if
1678
1679 ! define variable
1680 if (inetcdf4) then
1681 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1682 chunksizes(ndim) = 1
1683 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 1), &
1684 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1685 else
1686 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 1)))
1687 end if
1688
1689 ! end define mode
1690 call check(nf90_enddef(ncid))
1691
1692 ! write dimensions
1693 do i = 1, ndim - 1
1694 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1695 end do
1696
1697 ! write time and variable
1698 start(:) = 1
1699 counter(:) = dims
1700 counter(ndim) = 1
1701 do i = 1, dims(ndim)
1702 start(ndim) = i
1703 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
1704 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 call check(nf90_close(ncid))
1710
1711 end subroutine dump_netcdf_3d_dp
1712
1713
1714 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 if (present(append)) then
1745 if (append) then
1746 iappend = .true.
1747 else
1748 iappend = .false.
1749 end if
1750 else
1751 iappend = .false.
1752 end if
1753 largefile = .false.
1754 if (present(lfs)) largefile = lfs
1755 inetcdf4 = .false.
1756 if (present(netcdf4)) inetcdf4 = netcdf4
1757 deflate = 1
1758 if (present(deflate_level)) deflate = deflate_level
1759
1760 ! dimension names
1761 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1762
1763 if (iappend) then
1764 ! open file
1765 call check(nf90_open(trim(filename), nf90_write, ncid))
1766
1767 ! inquire variables time and var
1768 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1769 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1770 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1771 if (idim /= ndim) stop "dump_netcdf_4d_dp: number of variable dimensions /= number of file variable dimensions."
1772
1773 ! inquire dimensions
1774 do i = 1, ndim
1775 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1776 if (i < ndim) then
1777 if (trim(name) /= dnames(i)) stop "dump_netcdf_4d_dp: dimension name problem."
1778 if (dims(i) /= size(arr, i)) stop "dump_netcdf_4d_dp: variable dimension /= file variable dimension."
1779 else
1780 if (trim(name) /= 'time') stop "dump_netcdf_4d_dp: time name problem."
1781 end if
1782 enddo
1783
1784 ! append
1785 start(:) = 1
1786 counter(:) = dims
1787 counter(ndim) = 1
1788 do i = 1, size(arr, ndim)
1789 start(ndim) = dims(ndim) + i
1790 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1791 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
1792 end do
1793 else
1794 ! open file
1795 if (inetcdf4) then
1796 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
1797 else
1798 if (largefile) then
1799 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
1800 else
1801 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
1802 end if
1803 end if
1804
1805 ! define dims
1806 dims = shape(arr)
1807 do i = 1, ndim - 1
1808 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1809 end do
1810 ! define dim time
1811 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
1812
1813 ! define dim variables
1814 do i = 1, ndim - 1
1815 if (inetcdf4) then
1816 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
1817 else
1818 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 if (inetcdf4) then
1823 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1824 else
1825 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1826 end if
1827
1828 ! define variable
1829 if (inetcdf4) then
1830 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1831 chunksizes(ndim) = 1
1832 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 1), &
1833 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1834 else
1835 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 1)))
1836 end if
1837
1838 ! end define mode
1839 call check(nf90_enddef(ncid))
1840
1841 ! write dimensions
1842 do i = 1, ndim - 1
1843 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1844 end do
1845
1846 ! write time and variable
1847 start(:) = 1
1848 counter(:) = dims
1849 counter(ndim) = 1
1850 do i = 1, dims(ndim)
1851 start(ndim) = i
1852 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
1853 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 call check(nf90_close(ncid))
1859
1860 end subroutine dump_netcdf_4d_dp
1861
1862
1863 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 if (present(append)) then
1894 if (append) then
1895 iappend = .true.
1896 else
1897 iappend = .false.
1898 end if
1899 else
1900 iappend = .false.
1901 end if
1902 largefile = .false.
1903 if (present(lfs)) largefile = lfs
1904 inetcdf4 = .false.
1905 if (present(netcdf4)) inetcdf4 = netcdf4
1906 deflate = 1
1907 if (present(deflate_level)) deflate = deflate_level
1908
1909 ! dimension names
1910 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
1911
1912 if (iappend) then
1913 ! open file
1914 call check(nf90_open(trim(filename), nf90_write, ncid))
1915
1916 ! inquire variables time and var
1917 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
1918 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
1919 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
1920 if (idim /= ndim) stop "dump_netcdf_5d_dp: number of variable dimensions /= number of file variable dimensions."
1921
1922 ! inquire dimensions
1923 do i = 1, ndim
1924 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
1925 if (i < ndim) then
1926 if (trim(name) /= dnames(i)) stop "dump_netcdf_5d_dp: dimension name problem."
1927 if (dims(i) /= size(arr, i)) stop "dump_netcdf_5d_dp: variable dimension /= file variable dimension."
1928 else
1929 if (trim(name) /= 'time') stop "dump_netcdf_5d_dp: time name problem."
1930 end if
1931 enddo
1932
1933 ! append
1934 start(:) = 1
1935 counter(:) = dims
1936 counter(ndim) = 1
1937 do i = 1, size(arr, ndim)
1938 start(ndim) = dims(ndim) + i
1939 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
1940 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
1941 end do
1942 else
1943 ! open file
1944 if (inetcdf4) then
1945 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
1946 else
1947 if (largefile) then
1948 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
1949 else
1950 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
1951 end if
1952 end if
1953
1954 ! define dims
1955 dims = shape(arr)
1956 do i = 1, ndim - 1
1957 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
1958 end do
1959 ! define dim time
1960 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
1961
1962 ! define dim variables
1963 do i = 1, ndim - 1
1964 if (inetcdf4) then
1965 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
1966 else
1967 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 if (inetcdf4) then
1972 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1973 else
1974 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
1975 end if
1976
1977 ! define variable
1978 if (inetcdf4) then
1979 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
1980 chunksizes(ndim) = 1
1981 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 1), &
1982 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
1983 else
1984 call check(nf90_def_var(ncid, 'var', nf90_double, dimid, varid(ndim + 1)))
1985 end if
1986
1987 ! end define mode
1988 call check(nf90_enddef(ncid))
1989
1990 ! write dimensions
1991 do i = 1, ndim - 1
1992 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
1993 end do
1994
1995 ! write time and variable
1996 start(:) = 1
1997 counter(:) = dims
1998 counter(ndim) = 1
1999 do i = 1, dims(ndim)
2000 start(ndim) = i
2001 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
2002 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 call check(nf90_close(ncid))
2008
2009 end subroutine dump_netcdf_5d_dp
2010
2011
2012 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 if (present(append)) then
2043 if (append) then
2044 iappend = .true.
2045 else
2046 iappend = .false.
2047 end if
2048 else
2049 iappend = .false.
2050 end if
2051 largefile = .false.
2052 if (present(lfs)) largefile = lfs
2053 inetcdf4 = .false.
2054 if (present(netcdf4)) inetcdf4 = netcdf4
2055 deflate = 1
2056 if (present(deflate_level)) deflate = deflate_level
2057
2058 ! dimension names
2059 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2060
2061 if (iappend) then
2062 ! open file
2063 call check(nf90_open(trim(filename), nf90_write, ncid))
2064
2065 ! inquire variables time and var
2066 call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
2067 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
2068 call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
2069 if (idim /= ndim + 1) stop "dump_netcdf_1d_i4: number of variable dimensions /= number of file variable dimensions."
2070
2071 ! inquire dimensions
2072 do i = 1, ndim + 1
2073 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2074 if (i < ndim + 1) then
2075 if (trim(name) /= dnames(i)) stop "dump_netcdf_1d_i4: dimension name problem."
2076 if (dims(i) /= size(arr, i)) stop "dump_netcdf_1d_i4: variable dimension /= file variable dimension."
2077 else
2078 if (trim(name) /= 'time') stop "dump_netcdf_1d_i4: time name problem."
2079 end if
2080 enddo
2081
2082 ! append
2083 start(:) = 1
2084 counter(:) = dims
2085 counter(ndim + 1) = 1
2086 do i = 1, 1
2087 start(ndim + 1) = dims(ndim + 1) + i
2088 call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
2089 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
2090 end do
2091 else
2092 ! open file
2093 if (inetcdf4) then
2094 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
2095 else
2096 if (largefile) then
2097 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
2098 else
2099 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
2100 end if
2101 end if
2102
2103 ! define dims
2104 dims(1 : ndim) = shape(arr)
2105 do i = 1, ndim
2106 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2107 end do
2108 ! define dim time
2109 dims(ndim + 1) = 1
2110 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim + 1)))
2111
2112 ! define dim variables
2113 do i = 1, ndim
2114 if (inetcdf4) then
2115 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
2116 else
2117 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 if (inetcdf4) then
2122 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
2123 else
2124 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
2125 end if
2126
2127 ! define variable
2128 if (inetcdf4) then
2129 chunksizes(1 : ndim) = dims(1 : ndim)
2130 chunksizes(ndim + 1) = 1
2131 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 2), &
2132 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2133 else
2134 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 2)))
2135 end if
2136
2137 ! end define mode
2138 call check(nf90_enddef(ncid))
2139
2140 ! write dimensions
2141 do i = 1, ndim
2142 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2143 end do
2144
2145 ! write time and variable
2146 start(:) = 1
2147 counter(:) = dims
2148 counter(ndim + 1) = 1
2149 do i = 1, 1
2150 start(ndim + 1) = i
2151 call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
2152 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
2153 end do
2154 end if
2155
2156 ! close netcdf file
2157 call check(nf90_close(ncid))
2158
2159 end subroutine dump_netcdf_1d_i4
2160
2161
2162 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 if (present(append)) then
2193 if (append) then
2194 iappend = .true.
2195 else
2196 iappend = .false.
2197 end if
2198 else
2199 iappend = .false.
2200 end if
2201 largefile = .false.
2202 if (present(lfs)) largefile = lfs
2203 inetcdf4 = .false.
2204 if (present(netcdf4)) inetcdf4 = netcdf4
2205 deflate = 1
2206 if (present(deflate_level)) deflate = deflate_level
2207
2208 ! dimension names
2209 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2210
2211 if (iappend) then
2212 ! open file
2213 call check(nf90_open(trim(filename), nf90_write, ncid))
2214
2215 ! inquire variables time and var
2216 call check(nf90_inq_varid(ncid, 'time', varid(ndim + 1)))
2217 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 2)))
2218 call check(nf90_inquire_variable(ncid, varid(ndim + 2), ndims = idim, dimids = dimid))
2219 if (idim /= ndim + 1) stop "dump_netcdf_2d_i4: number of variable dimensions /= number of file variable dimensions."
2220
2221 ! inquire dimensions
2222 do i = 1, ndim + 1
2223 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2224 if (i < ndim + 1) then
2225 if (trim(name) /= dnames(i)) stop "dump_netcdf_2d_i4: dimension name problem."
2226 if (dims(i) /= size(arr, i)) stop "dump_netcdf_2d_i4: variable dimension /= file variable dimension."
2227 else
2228 if (trim(name) /= 'time') stop "dump_netcdf_2d_i4: time name problem."
2229 end if
2230 enddo
2231
2232 ! append
2233 start(:) = 1
2234 counter(:) = dims
2235 counter(ndim + 1) = 1
2236 do i = 1, 1
2237 start(ndim + 1) = dims(ndim + 1) + i
2238 call check(nf90_put_var(ncid, varid(ndim + 1), (/dims(ndim + 1) + i/), (/dims(ndim + 1) + i/)))
2239 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
2240 end do
2241 else
2242 ! open file
2243 if (inetcdf4) then
2244 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
2245 else
2246 if (largefile) then
2247 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
2248 else
2249 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
2250 end if
2251 end if
2252
2253 ! define dims
2254 dims(1 : ndim) = shape(arr)
2255 do i = 1, ndim
2256 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2257 end do
2258 ! define dim time
2259 dims(ndim + 1) = 1
2260 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim + 1)))
2261
2262 ! define dim variables
2263 do i = 1, ndim
2264 if (inetcdf4) then
2265 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
2266 else
2267 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 if (inetcdf4) then
2272 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
2273 else
2274 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim + 1), varid(ndim + 1)))
2275 end if
2276
2277 ! define variable
2278 if (inetcdf4) then
2279 chunksizes(1 : ndim) = dims(1 : ndim)
2280 chunksizes(ndim + 1) = 1
2281 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 2), &
2282 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2283 else
2284 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 2)))
2285 end if
2286
2287 ! end define mode
2288 call check(nf90_enddef(ncid))
2289
2290 ! write dimensions
2291 do i = 1, ndim
2292 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2293 end do
2294
2295 ! write time and variable
2296 start(:) = 1
2297 counter(:) = dims
2298 counter(ndim + 1) = 1
2299 do i = 1, 1
2300 start(ndim + 1) = i
2301 call check(nf90_put_var(ncid, varid(ndim + 1), (/i/), (/i/)))
2302 call check(nf90_put_var(ncid, varid(ndim + 2), arr, start, counter))
2303 end do
2304 end if
2305
2306 ! close netcdf file
2307 call check(nf90_close(ncid))
2308
2309 end subroutine dump_netcdf_2d_i4
2310
2311
2312 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 if (present(append)) then
2343 if (append) then
2344 iappend = .true.
2345 else
2346 iappend = .false.
2347 end if
2348 else
2349 iappend = .false.
2350 end if
2351 largefile = .false.
2352 if (present(lfs)) largefile = lfs
2353 inetcdf4 = .false.
2354 if (present(netcdf4)) inetcdf4 = netcdf4
2355 deflate = 1
2356 if (present(deflate_level)) deflate = deflate_level
2357
2358 ! dimension names
2359 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2360
2361 if (iappend) then
2362 ! open file
2363 call check(nf90_open(trim(filename), nf90_write, ncid))
2364
2365 ! inquire variables time and var
2366 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
2367 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
2368 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
2369 if (idim /= ndim) stop "dump_netcdf_3d_i4: number of variable dimensions /= number of file variable dimensions."
2370
2371 ! inquire dimensions
2372 do i = 1, ndim
2373 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2374 if (i < ndim) then
2375 if (trim(name) /= dnames(i)) stop "dump_netcdf_3d_i4: dimension name problem."
2376 if (dims(i) /= size(arr, i)) stop "dump_netcdf_3d_i4: variable dimension /= file variable dimension."
2377 else
2378 if (trim(name) /= 'time') stop "dump_netcdf_3d_i4: time name problem."
2379 end if
2380 enddo
2381
2382 ! append
2383 start(:) = 1
2384 counter(:) = dims
2385 counter(ndim) = 1
2386 do i = 1, size(arr, ndim)
2387 start(ndim) = dims(ndim) + i
2388 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
2389 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, i), start, counter))
2390 end do
2391 else
2392 ! open file
2393 if (inetcdf4) then
2394 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
2395 else
2396 if (largefile) then
2397 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
2398 else
2399 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
2400 end if
2401 end if
2402
2403 ! define dims
2404 dims = shape(arr)
2405 do i = 1, ndim - 1
2406 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2407 end do
2408 ! define dim time
2409 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
2410
2411 ! define dim variables
2412 do i = 1, ndim - 1
2413 if (inetcdf4) then
2414 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
2415 else
2416 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 if (inetcdf4) then
2421 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
2422 else
2423 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
2424 end if
2425
2426 ! define variable
2427 if (inetcdf4) then
2428 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
2429 chunksizes(ndim) = 1
2430 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 1), &
2431 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2432 else
2433 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 1)))
2434 end if
2435
2436 ! end define mode
2437 call check(nf90_enddef(ncid))
2438
2439 ! write dimensions
2440 do i = 1, ndim - 1
2441 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2442 end do
2443
2444 ! write time and variable
2445 start(:) = 1
2446 counter(:) = dims
2447 counter(ndim) = 1
2448 do i = 1, dims(ndim)
2449 start(ndim) = i
2450 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
2451 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 call check(nf90_close(ncid))
2457
2458 end subroutine dump_netcdf_3d_i4
2459
2460
2461 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 if (present(append)) then
2492 if (append) then
2493 iappend = .true.
2494 else
2495 iappend = .false.
2496 end if
2497 else
2498 iappend = .false.
2499 end if
2500 largefile = .false.
2501 if (present(lfs)) largefile = lfs
2502 inetcdf4 = .false.
2503 if (present(netcdf4)) inetcdf4 = netcdf4
2504 deflate = 1
2505 if (present(deflate_level)) deflate = deflate_level
2506
2507 ! dimension names
2508 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2509
2510 if (iappend) then
2511 ! open file
2512 call check(nf90_open(trim(filename), nf90_write, ncid))
2513
2514 ! inquire variables time and var
2515 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
2516 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
2517 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
2518 if (idim /= ndim) stop "dump_netcdf_4d_i4: number of variable dimensions /= number of file variable dimensions."
2519
2520 ! inquire dimensions
2521 do i = 1, ndim
2522 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2523 if (i < ndim) then
2524 if (trim(name) /= dnames(i)) stop "dump_netcdf_4d_i4: dimension name problem."
2525 if (dims(i) /= size(arr, i)) stop "dump_netcdf_4d_i4: variable dimension /= file variable dimension."
2526 else
2527 if (trim(name) /= 'time') stop "dump_netcdf_4d_i4: time name problem."
2528 end if
2529 enddo
2530
2531 ! append
2532 start(:) = 1
2533 counter(:) = dims
2534 counter(ndim) = 1
2535 do i = 1, size(arr, ndim)
2536 start(ndim) = dims(ndim) + i
2537 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
2538 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, i), start, counter))
2539 end do
2540 else
2541 ! open file
2542 if (inetcdf4) then
2543 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
2544 else
2545 if (largefile) then
2546 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
2547 else
2548 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
2549 end if
2550 end if
2551
2552 ! define dims
2553 dims = shape(arr)
2554 do i = 1, ndim - 1
2555 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2556 end do
2557 ! define dim time
2558 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
2559
2560 ! define dim variables
2561 do i = 1, ndim - 1
2562 if (inetcdf4) then
2563 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
2564 else
2565 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 if (inetcdf4) then
2570 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
2571 else
2572 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
2573 end if
2574
2575 ! define variable
2576 if (inetcdf4) then
2577 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
2578 chunksizes(ndim) = 1
2579 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 1), &
2580 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2581 else
2582 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 1)))
2583 end if
2584
2585 ! end define mode
2586 call check(nf90_enddef(ncid))
2587
2588 ! write dimensions
2589 do i = 1, ndim - 1
2590 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2591 end do
2592
2593 ! write time and variable
2594 start(:) = 1
2595 counter(:) = dims
2596 counter(ndim) = 1
2597 do i = 1, dims(ndim)
2598 start(ndim) = i
2599 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
2600 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 call check(nf90_close(ncid))
2606
2607 end subroutine dump_netcdf_4d_i4
2608
2609
2610 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 if (present(append)) then
2641 if (append) then
2642 iappend = .true.
2643 else
2644 iappend = .false.
2645 end if
2646 else
2647 iappend = .false.
2648 end if
2649 largefile = .false.
2650 if (present(lfs)) largefile = lfs
2651 inetcdf4 = .false.
2652 if (present(netcdf4)) inetcdf4 = netcdf4
2653 deflate = 1
2654 if (present(deflate_level)) deflate = deflate_level
2655
2656 ! dimension names
2657 dnames(1 : 4) = (/ 'x', 'y', 'z', 'l' /)
2658
2659 if (iappend) then
2660 ! open file
2661 call check(nf90_open(trim(filename), nf90_write, ncid))
2662
2663 ! inquire variables time and var
2664 call check(nf90_inq_varid(ncid, 'time', varid(ndim)))
2665 call check(nf90_inq_varid(ncid, 'var', varid(ndim + 1)))
2666 call check(nf90_inquire_variable(ncid, varid(ndim + 1), ndims = idim, dimids = dimid))
2667 if (idim /= ndim) stop "dump_netcdf_5d_i4: number of variable dimensions /= number of file variable dimensions."
2668
2669 ! inquire dimensions
2670 do i = 1, ndim
2671 call check(nf90_inquire_dimension(ncid, dimid(i), name, dims(i)))
2672 if (i < ndim) then
2673 if (trim(name) /= dnames(i)) stop "dump_netcdf_5d_i4: dimension name problem."
2674 if (dims(i) /= size(arr, i)) stop "dump_netcdf_5d_i4: variable dimension /= file variable dimension."
2675 else
2676 if (trim(name) /= 'time') stop "dump_netcdf_5d_i4: time name problem."
2677 end if
2678 enddo
2679
2680 ! append
2681 start(:) = 1
2682 counter(:) = dims
2683 counter(ndim) = 1
2684 do i = 1, size(arr, ndim)
2685 start(ndim) = dims(ndim) + i
2686 call check(nf90_put_var(ncid, varid(ndim), (/dims(ndim) + i/), (/dims(ndim) + i/)))
2687 call check(nf90_put_var(ncid, varid(ndim + 1), arr(:, :, :, :, i), start, counter))
2688 end do
2689 else
2690 ! open file
2691 if (inetcdf4) then
2692 call check(nf90_create(trim(filename), nf90_netcdf4, ncid))
2693 else
2694 if (largefile) then
2695 call check(nf90_create(trim(filename), nf90_64bit_offset, ncid, chunksize = buffersize))
2696 else
2697 call check(nf90_create(trim(filename), nf90_clobber, ncid, chunksize = buffersize))
2698 end if
2699 end if
2700
2701 ! define dims
2702 dims = shape(arr)
2703 do i = 1, ndim - 1
2704 call check(nf90_def_dim(ncid, dnames(i), dims(i), dimid(i)))
2705 end do
2706 ! define dim time
2707 call check(nf90_def_dim(ncid, 'time', nf90_unlimited, dimid(ndim)))
2708
2709 ! define dim variables
2710 do i = 1, ndim - 1
2711 if (inetcdf4) then
2712 call check(nf90_def_var(ncid, dnames(i), nf90_int, dimid(i), varid(i)))
2713 else
2714 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 if (inetcdf4) then
2719 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
2720 else
2721 call check(nf90_def_var(ncid, 'time', nf90_int, dimid(ndim), varid(ndim)))
2722 end if
2723
2724 ! define variable
2725 if (inetcdf4) then
2726 chunksizes(1 : ndim - 1) = dims(1 : ndim - 1)
2727 chunksizes(ndim) = 1
2728 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 1), &
2729 chunksizes = chunksizes, shuffle = .true., deflate_level = deflate))
2730 else
2731 call check(nf90_def_var(ncid, 'var', nf90_int, dimid, varid(ndim + 1)))
2732 end if
2733
2734 ! end define mode
2735 call check(nf90_enddef(ncid))
2736
2737 ! write dimensions
2738 do i = 1, ndim - 1
2739 call check(nf90_put_var(ncid, varid(i), (/ (j, j = 1, dims(i)) /)))
2740 end do
2741
2742 ! write time and variable
2743 start(:) = 1
2744 counter(:) = dims
2745 counter(ndim) = 1
2746 do i = 1, dims(ndim)
2747 start(ndim) = i
2748 call check(nf90_put_var(ncid, varid(ndim), (/i/), (/i/)))
2749 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 call check(nf90_close(ncid))
2755
2756 end subroutine dump_netcdf_5d_i4
2757
2758
2759 ! ------------------------------------------------------------------
2760
2761
2762 subroutine var2nc_1d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
2763 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 integer(i4), dimension(:), allocatable :: chunksizes
2788 integer(i4), dimension(:), allocatable :: start ! start array for write
2789 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 integer(i4), dimension(:), allocatable :: dims
2796 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
2797 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
2798 integer(i4) :: i ! loop indices
2799 integer(i4), dimension(:), allocatable :: dummy_count
2800 integer(i4), dimension(1) :: dummy ! dummy read
2801 logical :: openfile ! tmp logical
2802 !
2803 ndim = size(dnames, 1)
2804 ! consistency checks
2805 d_unlimit = 0_i4
2806 if (present(dim_unlimited)) d_unlimit = dim_unlimited
2807 if ((size(dnames, 1) .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
2808 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
2809 stop '***ERROR see StdOut'
2810 end if
2811 if (size(dnames, 1) .gt. ndim_const + 1) then
2812 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
2813 stop '***ERROR see StdOut'
2814 end if
2815 allocate(chunksizes(ndim))
2816 allocate(start(ndim))
2817 allocate(counter(ndim))
2818 allocate(dims(ndim))
2819 allocate(dimid(ndim))
2820 allocate(varid(1 + ndim))
2821 allocate(dummy_count(ndim))
2822 ! initialize
2823 deflate = 1
2824 if (ndim .gt. ndim_const) then
2825 chunksizes = (/ size(arr, 1), 1 /)
2826 dims(1 : ndim - 1) = shape(arr)
2827 dims(ndim) = 1
2828 else
2829 chunksizes = (/ size(arr, 1) /)
2830 dims(1 : ndim_const) = shape(arr)
2831 end if
2832 start(:) = 1
2833 counter(:) = dims
2834 dummy = nf90_fill_int
2835 dummy_count = 1
2836 ! open the netcdf file
2837 if (present(ncid)) then
2838 if (ncid < 0_i4) then
2839 openfile = .true.
2840 else
2841 openfile = .false.
2842 f_handle = ncid
2843 end if
2844 else
2845 openfile = .true.
2846 end if
2847 if (openfile) then
2848 create_loc = .false.
2849 if (present(create)) create_loc = create
2850 f_handle = open_netcdf(f_name, create = create_loc)
2851 end if
2852 ! check whether variable exists
2853 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
2854 ! append
2855 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
2856 if (idim .ne. ndim) stop "var2nc_1d_i4: number of variable dimensions /= number of file variable dimensions."
2857 ! check unlimited dimension
2858 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
2859 if (u_dimid .eq. -1) stop 'var2nc_1d_i4: cannot append, no unlimited dimension defined'
2860 ! check for unlimited dimension
2861 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_1d_i4: unlimited dimension not specified correctly'
2862 if (present(nrec)) then
2863 start(d_unlimit) = nrec
2864 else
2865 ! get length of unlimited dimension
2866 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
2867 ! adapt start, that is find last written chunk
2868 do i = u_len, 1, -1
2869 if (dummy(1) /= nf90_fill_int) exit
2870 start(d_unlimit) = i
2871 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
2872 end do
2873 start(d_unlimit) = start(d_unlimit) + 1
2874 end if
2875 else
2876 ! define dimension
2877 do i = 1, ndim
2878 ! check whether dimension exists
2879 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
2880 ! create dimension
2881 if (i .eq. d_unlimit) then
2882 ! define unlimited dimension
2883 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
2884 else
2885 ! define limited dimension
2886 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 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
2893 !
2894 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
2895 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
2896 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
2897 if (present(attributes)) then
2898 do i = 1, size(attributes, dim = 1)
2899 if (trim(attributes(i, 1)) .eq. 'missing_value') then
2900 ! write number
2901 read(attributes(i, 2), '(I6)') dummy(1)
2902 call check(nf90_put_att(f_handle, varid(ndim + 1), &
2903 trim(attributes(i, 1)), dummy(1)))
2904 else
2905 ! write string
2906 call check(nf90_put_att(f_handle, varid(ndim + 1), &
2907 trim(attributes(i, 1)), trim(attributes(i, 2))))
2908 end if
2909 end do
2910 end if
2911 ! end definition
2912 call check(nf90_enddef(f_handle))
2913 end if
2914 ! inquire dimensions
2915 do i = 1, ndim_const
2916 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
2917 if (trim(dummy_name) .ne. dnames(i)) &
2918 stop "var2nc_1d_i4: dimension name problem."
2919 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
2920 stop "var2nc_1d_i4: variable dimension /= file variable dimension."
2921 enddo
2922 ! write time and variable
2923 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
2924 ! close netcdf_dataset
2925 if (present(ncid)) then
2926 if (ncid < 0_i4) ncid = f_handle
2927 else
2928 call close_netcdf(f_handle)
2929 end if
2930 !
2931 end subroutine var2nc_1d_i4
2932
2933 subroutine var2nc_1d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
2934 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 integer(i4), dimension(:), allocatable :: chunksizes
2959 integer(i4), dimension(:), allocatable :: start ! start array for write
2960 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 integer(i4), dimension(:), allocatable :: dims
2967 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
2968 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
2969 integer(i4) :: i ! loop indices
2970 integer(i4), dimension(:), allocatable :: dummy_count
2971 real(sp), dimension(1) :: dummy ! dummy read
2972 logical :: openfile ! tmp logical
2973 !
2974 ndim = size(dnames, 1)
2975 ! consistency checks
2976 d_unlimit = 0_i4
2977 if (present(dim_unlimited)) d_unlimit = dim_unlimited
2978 if ((size(dnames, 1) .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
2979 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
2980 stop '***ERROR see StdOut'
2981 end if
2982 if (size(dnames, 1) .gt. ndim_const + 1) then
2983 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
2984 stop '***ERROR see StdOut'
2985 end if
2986 allocate(chunksizes(ndim))
2987 allocate(start(ndim))
2988 allocate(counter(ndim))
2989 allocate(dims(ndim))
2990 allocate(dimid(ndim))
2991 allocate(varid(1 + ndim))
2992 allocate(dummy_count(ndim))
2993 ! initialize
2994 deflate = 1
2995 if (ndim .gt. ndim_const) then
2996 chunksizes = (/ size(arr, 1), 1 /)
2997 dims(1 : ndim - 1) = shape(arr)
2998 dims(ndim) = 1
2999 else
3000 chunksizes = (/ size(arr, 1) /)
3001 dims(1 : ndim_const) = shape(arr)
3002 end if
3003 start(:) = 1
3004 counter(:) = dims
3005 dummy_count = 1
3006 dummy = nf90_fill_float
3007 ! open the netcdf file
3008 if (present(ncid)) then
3009 if (ncid < 0_i4) then
3010 openfile = .true.
3011 else
3012 openfile = .false.
3013 f_handle = ncid
3014 end if
3015 else
3016 openfile = .true.
3017 end if
3018 if (openfile) then
3019 create_loc = .false.
3020 if (present(create)) create_loc = create
3021 f_handle = open_netcdf(f_name, create = create_loc)
3022 end if
3023 ! check whether variable exists
3024 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3025 ! append
3026 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3027 if (idim .ne. ndim) stop "var2nc_1d_sp: number of variable dimensions /= number of file variable dimensions."
3028 ! check unlimited dimension
3029 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
3030 if (u_dimid .eq. -1) stop 'var2nc_1d_sp: cannot append, no unlimited dimension defined'
3031 ! check for unlimited dimension
3032 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_1d_sp: unlimited dimension not specified correctly'
3033 if (present(nrec)) then
3034 start(d_unlimit) = nrec
3035 else
3036 ! get length of unlimited dimension
3037 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3038 ! adapt start, that is find last written chunk
3039 do i = u_len, 1, -1
3040 if (ne(dummy(1), nf90_fill_float)) exit
3041 start(d_unlimit) = i
3042 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3043 end do
3044 start(d_unlimit) = start(d_unlimit) + 1
3045 end if
3046 else
3047 ! define dimension
3048 do i = 1, ndim
3049 ! check whether dimension exists
3050 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3051 ! create dimension
3052 if (i .eq. d_unlimit) then
3053 ! define unlimited dimension
3054 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
3055 else
3056 ! define limited dimension
3057 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 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3064 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
3065 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
3066 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
3067 if (present(attributes)) then
3068 do i = 1, size(attributes, dim = 1)
3069 if (trim(attributes(i, 1)) .eq. 'missing_value') then
3070 ! write number
3071 read(attributes(i, 2), '(F10.2)') dummy(1)
3072 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3073 trim(attributes(i, 1)), dummy(1)))
3074 else
3075 ! write string
3076 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3077 trim(attributes(i, 1)), trim(attributes(i, 2))))
3078 end if
3079 end do
3080 end if
3081 ! end definition
3082 call check(nf90_enddef(f_handle))
3083 end if
3084 ! inquire dimensions
3085 do i = 1, ndim_const
3086 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3087 if (trim(dummy_name) .ne. dnames(i)) &
3088 stop "var2nc_1d_sp: dimension name problem."
3089 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3090 stop "var2nc_1d_sp: variable dimension /= file variable dimension."
3091 enddo
3092 ! write time and variable
3093 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3094 ! close netcdf_dataset
3095 if (present(ncid)) then
3096 if (ncid < 0_i4) ncid = f_handle
3097 else
3098 call close_netcdf(f_handle)
3099 end if
3100 !
3101 end subroutine var2nc_1d_sp
3102
3103 subroutine var2nc_1d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
3104 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 integer(i4), dimension(:), allocatable :: chunksizes
3129 integer(i4), dimension(:), allocatable :: start ! start array for write
3130 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 integer(i4), dimension(:), allocatable :: dims
3137 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3138 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3139 integer(i4) :: i ! loop indices
3140 integer(i4), dimension(:), allocatable :: dummy_count
3141 real(dp), dimension(1) :: dummy ! dummy read
3142 logical :: openfile ! tmp logical
3143 !
3144 ndim = size(dnames, 1)
3145 ! consistency checks
3146 d_unlimit = 0_i4
3147 if (present(dim_unlimited)) d_unlimit = dim_unlimited
3148 if ((size(dnames, 1) .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3149 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3150 stop '***ERROR see StdOut'
3151 end if
3152 if (size(dnames, 1) .gt. ndim_const + 1) then
3153 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3154 stop '***ERROR see StdOut'
3155 end if
3156 allocate(chunksizes(ndim))
3157 allocate(start(ndim))
3158 allocate(counter(ndim))
3159 allocate(dims(ndim))
3160 allocate(dimid(ndim))
3161 allocate(varid(1 + ndim))
3162 allocate(dummy_count(ndim))
3163 ! initialize
3164 deflate = 1
3165 if (ndim .gt. ndim_const) then
3166 chunksizes = (/ size(arr, 1), 1 /)
3167 dims(1 : ndim - 1) = shape(arr)
3168 dims(ndim) = 1
3169 else
3170 chunksizes = (/ size(arr, 1) /)
3171 dims(1 : ndim_const) = shape(arr)
3172 end if
3173 start(:) = 1
3174 counter(:) = dims
3175 dummy_count = 1
3176 dummy = nf90_fill_double
3177 ! open the netcdf file
3178 if (present(ncid)) then
3179 if (ncid < 0_i4) then
3180 openfile = .true.
3181 else
3182 openfile = .false.
3183 f_handle = ncid
3184 end if
3185 else
3186 openfile = .true.
3187 end if
3188 if (openfile) then
3189 create_loc = .false.
3190 if (present(create)) create_loc = create
3191 f_handle = open_netcdf(f_name, create = create_loc)
3192 end if
3193 ! check whether variable exists
3194 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3195 ! append
3196 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3197 if (idim .ne. ndim) stop "var2nc_1d_dp: number of variable dimensions /= number of file variable dimensions."
3198 ! check unlimited dimension
3199 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
3200 if (u_dimid .eq. -1) stop 'var2nc_1d_dp: cannot append, no unlimited dimension defined'
3201 ! check for unlimited dimension
3202 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_1d_dp: unlimited dimension not specified correctly'
3203 if (present(nrec)) then
3204 start(d_unlimit) = nrec
3205 else
3206 ! get length of unlimited dimension
3207 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3208 ! adapt start, that is find last written chunk
3209 do i = u_len, 1, -1
3210 if (ne(dummy(1), nf90_fill_double)) exit
3211 start(d_unlimit) = i
3212 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3213 end do
3214 start(d_unlimit) = start(d_unlimit) + 1
3215 end if
3216 else
3217 ! define dimension
3218 do i = 1, ndim
3219 ! check whether dimension exists
3220 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3221 ! create dimension
3222 if (i .eq. d_unlimit) then
3223 ! define unlimited dimension
3224 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
3225 else
3226 ! define limited dimension
3227 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 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3234 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
3235 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
3236 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
3237 if (present(attributes)) then
3238 do i = 1, size(attributes, dim = 1)
3239 if (trim(attributes(i, 1)) .eq. 'missing_value') then
3240 ! write number
3241 read(attributes(i, 2), '(F10.2)') dummy(1)
3242 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3243 trim(attributes(i, 1)), dummy(1)))
3244 else
3245 ! write string
3246 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3247 trim(attributes(i, 1)), trim(attributes(i, 2))))
3248 end if
3249 end do
3250 end if
3251 ! end definition
3252 call check(nf90_enddef(f_handle))
3253 end if
3254 ! inquire dimensions
3255 do i = 1, ndim_const
3256 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3257 if (trim(dummy_name) .ne. dnames(i)) &
3258 stop "var2nc_1d_dp: dimension name problem."
3259 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3260 stop "var2nc_1d_dp: variable dimension /= file variable dimension."
3261 enddo
3262 ! write time and variable
3263 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3264 ! close netcdf_dataset
3265 if (present(ncid)) then
3266 if (ncid < 0_i4) ncid = f_handle
3267 else
3268 call close_netcdf(f_handle)
3269 end if
3270 !
3271 end subroutine var2nc_1d_dp
3272
3273 subroutine var2nc_2d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
3274 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 integer(i4), dimension(:), allocatable :: chunksizes
3299 integer(i4), dimension(:), allocatable :: start ! start array for write
3300 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 integer(i4), dimension(:), allocatable :: dims
3307 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3308 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3309 integer(i4) :: i ! loop indices
3310 integer(i4), dimension(:), allocatable :: dummy_count
3311 integer(i4), dimension(1) :: dummy ! dummy read
3312 logical :: openfile ! tmp logical
3313 !
3314 ndim = size(dnames, 1)
3315 ! consistency checks
3316 d_unlimit = 0_i4
3317 if (present(dim_unlimited)) d_unlimit = dim_unlimited
3318 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3319 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3320 stop '***ERROR see StdOut'
3321 end if
3322 if (ndim .gt. ndim_const + 1) then
3323 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3324 stop '***ERROR see StdOut'
3325 end if
3326 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
3327 (d_unlimit .lt. 0_i4)) then
3328 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
3329 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
3330 stop '***ERROR see StdOut'
3331 end if
3332 !
3333 allocate(chunksizes(ndim))
3334 allocate(start(ndim))
3335 allocate(counter(ndim))
3336 allocate(dims(ndim))
3337 allocate(dimid(ndim))
3338 allocate(varid(1 + ndim))
3339 allocate(dummy_count(ndim))
3340 ! initialize
3341 deflate = 1
3342 if (ndim .gt. ndim_const) then
3343 chunksizes = (/ size(arr, 1), size(arr, 2), 1 /)
3344 dims(1 : ndim - 1) = shape(arr)
3345 dims(ndim) = 1
3346 else
3347 chunksizes = (/ size(arr, 1), size(arr, 2) /)
3348 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
3349 dims(1 : ndim_const) = shape(arr)
3350 end if
3351 start(:) = 1_i4
3352 counter(:) = dims
3353 dummy_count = 1_i4
3354 dummy = nf90_fill_int
3355 ! open the netcdf file
3356 if (present(ncid)) then
3357 if (ncid < 0_i4) then
3358 openfile = .true.
3359 else
3360 openfile = .false.
3361 f_handle = ncid
3362 end if
3363 else
3364 openfile = .true.
3365 end if
3366 if (openfile) then
3367 create_loc = .false.
3368 if (present(create)) create_loc = create
3369 f_handle = open_netcdf(f_name, create = create_loc)
3370 end if
3371 ! check whether variable exists
3372 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3373 ! append
3374 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3375 ! consistency checks
3376 if (idim .ne. ndim) stop "var2nc_2d_i4: number of variable dimensions /= number of file variable dimensions."
3377 ! check unlimited dimension
3378 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
3379 if (u_dimid .eq. -1) stop 'var2nc_2d_i4: cannot append, no unlimited dimension defined'
3380 ! check for unlimited dimension
3381 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_2d_i4: unlimited dimension not specified correctly'
3382 if (present(nrec)) then
3383 start(d_unlimit) = nrec
3384 else
3385 ! get length of unlimited dimension
3386 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3387 ! adapt start, that is find last written chunk
3388 do i = u_len, 1, -1
3389 if (dummy(1) /= nf90_fill_int) exit
3390 start(d_unlimit) = i
3391 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3392 end do
3393 start(d_unlimit) = start(d_unlimit) + 1
3394 end if
3395 else
3396 ! define dimensions
3397 do i = 1, ndim
3398 ! check whether dimension exists
3399 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3400 ! create dimension
3401 if (i .eq. d_unlimit) then
3402 ! define unlimited dimension
3403 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
3404 else
3405 ! define limited dimension
3406 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 call check(nf90_def_var(f_handle, v_name, nf90_int, dimid, varid(ndim + 1), &
3412 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3413 ! add attributes
3414 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
3415 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
3416 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
3417 if (present(attributes)) then
3418 do i = 1, size(attributes, dim = 1)
3419 if (trim(attributes(i, 1)) .eq. 'missing_value') then
3420 ! write number
3421 read(attributes(i, 2), '(I6)') dummy(1)
3422 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3423 trim(attributes(i, 1)), dummy(1)))
3424 else
3425 ! write string
3426 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3427 trim(attributes(i, 1)), trim(attributes(i, 2))))
3428 end if
3429 end do
3430 end if
3431 ! end definition
3432 call check(nf90_enddef(f_handle))
3433 end if
3434 ! check dimensions before writing
3435 do i = 1, ndim_const
3436 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3437 if (trim(dummy_name) .ne. dnames(i)) &
3438 stop "var2nc_2d_i4: dimension name problem."
3439 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3440 stop "var2nc_2d_i4: variable dimension /= file variable dimension."
3441 end do
3442 ! write variable
3443 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3444 ! close netcdf_dataset
3445 if (present(ncid)) then
3446 if (ncid < 0_i4) ncid = f_handle
3447 else
3448 call close_netcdf(f_handle)
3449 end if
3450 !
3451 end subroutine var2nc_2d_i4
3452
3453 subroutine var2nc_2d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
3454 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 integer(i4), dimension(:), allocatable :: chunksizes
3479 integer(i4), dimension(:), allocatable :: start ! start array for write
3480 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 integer(i4), dimension(:), allocatable :: dims
3487 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3488 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3489 integer(i4) :: i ! loop indices
3490 integer(i4), dimension(:), allocatable :: dummy_count
3491 real(sp), dimension(1) :: dummy ! dummy read
3492 logical :: openfile ! tmp logical
3493 !
3494 ndim = size(dnames, 1)
3495 ! consistency checks
3496 d_unlimit = 0_i4
3497 if (present(dim_unlimited)) d_unlimit = dim_unlimited
3498 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3499 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3500 stop '***ERROR see StdOut'
3501 end if
3502 if (ndim .gt. ndim_const + 1) then
3503 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3504 stop '***ERROR see StdOut'
3505 end if
3506 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
3507 (d_unlimit .lt. 0_i4)) then
3508 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
3509 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
3510 stop '***ERROR see StdOut'
3511 end if
3512 !
3513 allocate(chunksizes(ndim))
3514 allocate(start(ndim))
3515 allocate(counter(ndim))
3516 allocate(dims(ndim))
3517 allocate(dimid(ndim))
3518 allocate(varid(1 + ndim))
3519 allocate(dummy_count(ndim))
3520 ! initialize
3521 deflate = 1
3522 if (ndim .gt. ndim_const) then
3523 chunksizes = (/ size(arr, 1), size(arr, 2), 1 /)
3524 dims(1 : ndim - 1) = shape(arr)
3525 dims(ndim) = 1
3526 else
3527 chunksizes = (/ size(arr, 1), size(arr, 2) /)
3528 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
3529 dims(1 : ndim_const) = shape(arr)
3530 end if
3531 start(:) = 1_i4
3532 counter(:) = dims
3533 dummy_count = 1_i4
3534 dummy = nf90_fill_float
3535 ! open the netcdf file
3536 if (present(ncid)) then
3537 if (ncid < 0_i4) then
3538 openfile = .true.
3539 else
3540 openfile = .false.
3541 f_handle = ncid
3542 end if
3543 else
3544 openfile = .true.
3545 end if
3546 if (openfile) then
3547 create_loc = .false.
3548 if (present(create)) create_loc = create
3549 f_handle = open_netcdf(f_name, create = create_loc)
3550 end if
3551 ! check whether variable exists
3552 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3553 ! append
3554 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3555 ! consistency checks
3556 if (idim .ne. ndim) stop "var2nc_2d_sp: number of variable dimensions /= number of file variable dimensions."
3557 ! check unlimited dimension
3558 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
3559 if (u_dimid .eq. -1) stop 'var2nc_2d_sp: cannot append, no unlimited dimension defined'
3560 ! check for unlimited dimension
3561 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_2d_sp: unlimited dimension not specified correctly'
3562 if (present(nrec)) then
3563 start(d_unlimit) = nrec
3564 else
3565 ! get length of unlimited dimension
3566 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3567 ! adapt start, that is find last written chunk
3568 do i = u_len, 1, -1
3569 if (ne(dummy(1), nf90_fill_float)) exit
3570 start(d_unlimit) = i
3571 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3572 end do
3573 start(d_unlimit) = start(d_unlimit) + 1
3574 end if
3575 else
3576 ! define dimensions
3577 do i = 1, ndim
3578 ! check whether dimension exists
3579 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3580 ! create dimension
3581 if (i .eq. d_unlimit) then
3582 ! define unlimited dimension
3583 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
3584 else
3585 ! define limited dimension
3586 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 call check(nf90_def_var(f_handle, v_name, nf90_float, dimid, varid(ndim + 1), &
3592 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3593 ! add attributes
3594 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
3595 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
3596 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
3597 if (present(attributes)) then
3598 do i = 1, size(attributes, dim = 1)
3599 if (trim(attributes(i, 1)) .eq. 'missing_value') then
3600 ! write number
3601 read(attributes(i, 2), '(F10.2)') dummy(1)
3602 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3603 trim(attributes(i, 1)), dummy(1)))
3604 else
3605 ! write string
3606 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3607 trim(attributes(i, 1)), trim(attributes(i, 2))))
3608 end if
3609 end do
3610 end if
3611 ! end definition
3612 call check(nf90_enddef(f_handle))
3613 end if
3614 ! check dimensions before writing
3615 do i = 1, ndim_const
3616 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3617 if (trim(dummy_name) .ne. dnames(i)) &
3618 stop "var2nc_2d_sp: dimension name problem."
3619 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3620 stop "var2nc_2d_sp: variable dimension /= file variable dimension."
3621 end do
3622 ! write variable
3623 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3624 ! close netcdf_dataset
3625 if (present(ncid)) then
3626 if (ncid < 0_i4) ncid = f_handle
3627 else
3628 call close_netcdf(f_handle)
3629 end if
3630 !
3631 end subroutine var2nc_2d_sp
3632
3633 subroutine var2nc_2d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
3634 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 integer(i4), dimension(:), allocatable :: chunksizes
3659 integer(i4), dimension(:), allocatable :: start ! start array for write
3660 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 integer(i4), dimension(:), allocatable :: dims
3667 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3668 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3669 integer(i4) :: i ! loop indices
3670 integer(i4), dimension(:), allocatable :: dummy_count
3671 real(dp), dimension(1) :: dummy ! dummy read
3672 logical :: openfile ! tmp logical
3673 !
3674 ndim = size(dnames, 1)
3675 ! consistency checks
3676 d_unlimit = 0_i4
3677 if (present(dim_unlimited)) d_unlimit = dim_unlimited
3678 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3679 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3680 stop '***ERROR see StdOut'
3681 end if
3682 if (ndim .gt. ndim_const + 1) then
3683 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3684 stop '***ERROR see StdOut'
3685 end if
3686 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
3687 (d_unlimit .lt. 0_i4)) then
3688 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
3689 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
3690 stop '***ERROR see StdOut'
3691 end if
3692 !
3693 allocate(chunksizes(ndim))
3694 allocate(start(ndim))
3695 allocate(counter(ndim))
3696 allocate(dims(ndim))
3697 allocate(dimid(ndim))
3698 allocate(varid(1 + ndim))
3699 allocate(dummy_count(ndim))
3700 ! initialize
3701 deflate = 1
3702 if (ndim .gt. ndim_const) then
3703 chunksizes = (/ size(arr, 1), size(arr, 2), 1 /)
3704 dims(1 : ndim - 1) = shape(arr)
3705 dims(ndim) = 1
3706 else
3707 chunksizes = (/ size(arr, 1), size(arr, 2) /)
3708 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
3709 dims(1 : ndim_const) = shape(arr)
3710 end if
3711 start(:) = 1_i4
3712 counter(:) = dims
3713 dummy_count = 1
3714 dummy = nf90_fill_double
3715 ! open the netcdf file
3716 if (present(ncid)) then
3717 if (ncid < 0_i4) then
3718 openfile = .true.
3719 else
3720 openfile = .false.
3721 f_handle = ncid
3722 end if
3723 else
3724 openfile = .true.
3725 end if
3726 if (openfile) then
3727 create_loc = .false.
3728 if (present(create)) create_loc = create
3729 f_handle = open_netcdf(f_name, create = create_loc)
3730 end if
3731 ! check whether variable exists
3732 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3733 ! append
3734 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3735 ! consistency checks
3736 if (idim .ne. ndim) stop "var2nc_2d_dp: number of variable dimensions /= number of file variable dimensions."
3737 ! check unlimited dimension
3738 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
3739 if (u_dimid .eq. -1) stop 'var2nc_2d_dp: cannot append, no unlimited dimension defined'
3740 ! check for unlimited dimension
3741 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_2d_dp: unlimited dimension not specified correctly'
3742 if (present(nrec)) then
3743 start(d_unlimit) = nrec
3744 else
3745 ! get length of unlimited dimension
3746 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3747 ! adapt start, that is find last written chunk
3748 do i = u_len, 1, -1
3749 if (ne(dummy(1), nf90_fill_double)) exit
3750 start(d_unlimit) = i
3751 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3752 end do
3753 start(d_unlimit) = start(d_unlimit) + 1
3754 end if
3755 else
3756 ! define dimensions
3757 do i = 1, ndim
3758 ! check whether dimension exists
3759 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3760 ! create dimension
3761 if (i .eq. d_unlimit) then
3762 ! define unlimited dimension
3763 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
3764 else
3765 ! define limited dimension
3766 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 call check(nf90_def_var(f_handle, v_name, nf90_double, dimid, varid(ndim + 1), &
3772 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3773 ! add attributes
3774 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
3775 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
3776 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
3777 if (present(attributes)) then
3778 do i = 1, size(attributes, dim = 1)
3779 if (trim(attributes(i, 1)) .eq. 'missing_value') then
3780 ! write number
3781 read(attributes(i, 2), '(F10.2)') dummy(1)
3782 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3783 trim(attributes(i, 1)), dummy(1)))
3784 else
3785 ! write string
3786 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3787 trim(attributes(i, 1)), trim(attributes(i, 2))))
3788 end if
3789 end do
3790 end if
3791 ! end definition
3792 call check(nf90_enddef(f_handle))
3793 end if
3794 ! check dimensions before writing
3795 do i = 1, ndim_const
3796 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3797 if (trim(dummy_name) .ne. dnames(i)) &
3798 stop "var2nc_2d_dp: dimension name problem."
3799 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3800 stop "var2nc_2d_dp: variable dimension /= file variable dimension."
3801 end do
3802 ! write variable
3803 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3804 ! close netcdf_dataset
3805 if (present(ncid)) then
3806 if (ncid < 0_i4) ncid = f_handle
3807 else
3808 call close_netcdf(f_handle)
3809 end if
3810 !
3811 end subroutine var2nc_2d_dp
3812
3813 subroutine var2nc_3d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
3814 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 integer(i4), dimension(:), allocatable :: chunksizes
3839 integer(i4), dimension(:), allocatable :: start ! start array for write
3840 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 integer(i4), dimension(:), allocatable :: dims
3847 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
3848 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
3849 integer(i4) :: i ! loop indices
3850 integer(i4), dimension(:), allocatable :: dummy_count
3851 integer(i4), dimension(1) :: dummy ! dummy read
3852 logical :: openfile ! tmp logical
3853 !
3854 ndim = size(dnames, 1)
3855 ! consistency checks
3856 d_unlimit = 0_i4
3857 if (present(dim_unlimited)) d_unlimit = dim_unlimited
3858 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
3859 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
3860 stop '***ERROR see StdOut'
3861 end if
3862 if (ndim .gt. ndim_const + 1) then
3863 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
3864 stop '***ERROR see StdOut'
3865 end if
3866 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
3867 (d_unlimit .lt. 0_i4)) then
3868 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
3869 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
3870 stop '***ERROR see StdOut'
3871 end if
3872 !
3873 allocate(chunksizes(ndim))
3874 allocate(start(ndim))
3875 allocate(counter(ndim))
3876 allocate(dims(ndim))
3877 allocate(dimid(ndim))
3878 allocate(varid(1 + ndim))
3879 allocate(dummy_count(ndim))
3880 ! initialize
3881 deflate = 1
3882 if (ndim .gt. ndim_const) then
3883 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), 1 /)
3884 dims(1 : ndim - 1) = shape(arr)
3885 dims(ndim) = 1
3886 else
3887 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3) /)
3888 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
3889 dims(1 : ndim_const) = shape(arr)
3890 end if
3891 start(:) = 1_i4
3892 counter(:) = dims
3893 dummy_count = 1_i4
3894 dummy = nf90_fill_int
3895 ! open the netcdf file
3896 if (present(ncid)) then
3897 if (ncid < 0_i4) then
3898 openfile = .true.
3899 else
3900 openfile = .false.
3901 f_handle = ncid
3902 end if
3903 else
3904 openfile = .true.
3905 end if
3906 if (openfile) then
3907 create_loc = .false.
3908 if (present(create)) create_loc = create
3909 f_handle = open_netcdf(f_name, create = create_loc)
3910 end if
3911 ! check whether variable exists
3912 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
3913 ! append
3914 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
3915 ! consistency checks
3916 if (idim .ne. ndim) stop "var2nc_3d_i4: number of variable dimensions /= number of file variable dimensions."
3917 ! check unlimited dimension
3918 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
3919 if (u_dimid .eq. -1) stop 'var2nc_3d_i4: cannot append, no unlimited dimension defined'
3920 ! check for unlimited dimension
3921 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_3d_i4: unlimited dimension not specified correctly'
3922 if (present(nrec)) then
3923 start(d_unlimit) = nrec
3924 else
3925 ! get length of unlimited dimension
3926 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
3927 ! adapt start, that is find last written chunk
3928 do i = u_len, 1, -1
3929 if (dummy(1) /= nf90_fill_int) exit
3930 start(d_unlimit) = i
3931 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
3932 end do
3933 start(d_unlimit) = start(d_unlimit) + 1
3934 end if
3935 else
3936 ! define dimensions
3937 do i = 1, ndim
3938 ! check whether dimension exists
3939 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
3940 ! create dimension
3941 if (i .eq. d_unlimit) then
3942 ! define unlimited dimension
3943 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
3944 else
3945 ! define limited dimension
3946 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 call check(nf90_def_var(f_handle, v_name, nf90_int, dimid, varid(ndim + 1), &
3952 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
3953 ! add attributes
3954 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
3955 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
3956 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
3957 if (present(attributes)) then
3958 do i = 1, size(attributes, dim = 1)
3959 if (trim(attributes(i, 1)) .eq. 'missing_value') then
3960 ! write number
3961 read(attributes(i, 2), '(I6)') dummy(1)
3962 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3963 trim(attributes(i, 1)), dummy(1)))
3964 else
3965 ! write string
3966 call check(nf90_put_att(f_handle, varid(ndim + 1), &
3967 trim(attributes(i, 1)), trim(attributes(i, 2))))
3968 end if
3969 end do
3970 end if
3971 ! end definition
3972 call check(nf90_enddef(f_handle))
3973 end if
3974 ! check dimensions before writing
3975 do i = 1, ndim_const
3976 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
3977 if (trim(dummy_name) .ne. dnames(i)) &
3978 stop "var2nc_3d_i4: dimension name problem."
3979 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
3980 stop "var2nc_3d_i4: variable dimension /= file variable dimension."
3981 end do
3982 ! write variable
3983 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
3984 ! close netcdf_dataset
3985 if (present(ncid)) then
3986 if (ncid < 0_i4) ncid = f_handle
3987 else
3988 call close_netcdf(f_handle)
3989 end if
3990 !
3991 end subroutine var2nc_3d_i4
3992
3993 subroutine var2nc_3d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
3994 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 integer(i4), dimension(:), allocatable :: chunksizes
4019 integer(i4), dimension(:), allocatable :: start ! start array for write
4020 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 integer(i4), dimension(:), allocatable :: dims
4027 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4028 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4029 integer(i4) :: i ! loop indices
4030 integer(i4), dimension(:), allocatable :: dummy_count
4031 real(sp), dimension(1) :: dummy ! dummy read
4032 logical :: openfile ! tmp logical
4033 !
4034 ndim = size(dnames, 1)
4035 ! consistency checks
4036 d_unlimit = 0_i4
4037 if (present(dim_unlimited)) d_unlimit = dim_unlimited
4038 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4039 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4040 stop '***ERROR see StdOut'
4041 end if
4042 if (ndim .gt. ndim_const + 1) then
4043 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4044 stop '***ERROR see StdOut'
4045 end if
4046 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4047 (d_unlimit .lt. 0_i4)) then
4048 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4049 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4050 stop '***ERROR see StdOut'
4051 end if
4052 !
4053 allocate(chunksizes(ndim))
4054 allocate(start(ndim))
4055 allocate(counter(ndim))
4056 allocate(dims(ndim))
4057 allocate(dimid(ndim))
4058 allocate(varid(1 + ndim))
4059 allocate(dummy_count(ndim))
4060 ! initialize
4061 deflate = 1
4062 ! set chunk sizes and dimension names
4063 if (ndim .gt. ndim_const) then
4064 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), 1 /)
4065 dims(1 : ndim - 1) = shape(arr)
4066 dims(ndim) = 1
4067 else
4068 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3) /)
4069 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4070 dims(1 : ndim_const) = shape(arr)
4071 end if
4072 start(:) = 1_i4
4073 counter(:) = dims
4074 dummy_count = 1_i4
4075 dummy = nf90_fill_float
4076 ! open the netcdf file
4077 if (present(ncid)) then
4078 if (ncid < 0_i4) then
4079 openfile = .true.
4080 else
4081 openfile = .false.
4082 f_handle = ncid
4083 end if
4084 else
4085 openfile = .true.
4086 end if
4087 if (openfile) then
4088 create_loc = .false.
4089 if (present(create)) create_loc = create
4090 f_handle = open_netcdf(f_name, create = create_loc)
4091 end if
4092 ! check whether variable exists
4093 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4094 ! append
4095 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4096 ! consistency checks
4097 if (idim .ne. ndim) stop "var2nc_3d_sp: number of variable dimensions /= number of file variable dimensions."
4098 ! check unlimited dimension
4099 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
4100 if (u_dimid .eq. -1) stop 'var2nc_3d_sp: cannot append, no unlimited dimension defined'
4101 ! check for unlimited dimension
4102 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_3d_sp: unlimited dimension not specified correctly'
4103 if (present(nrec)) then
4104 start(d_unlimit) = nrec
4105 else
4106 ! get length of unlimited dimension
4107 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4108 ! adapt start, that is find last written chunk
4109 do i = u_len, 1, -1
4110 if (ne(dummy(1), nf90_fill_float)) exit
4111 start(d_unlimit) = i
4112 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4113 end do
4114 start(d_unlimit) = start(d_unlimit) + 1
4115 end if
4116 else
4117 ! define dimensions
4118 do i = 1, ndim
4119 ! check whether dimension exists
4120 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4121 ! create dimension
4122 if (i .eq. d_unlimit) then
4123 ! define unlimited dimension
4124 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
4125 else
4126 ! define limited dimension
4127 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 call check(nf90_def_var(f_handle, v_name, nf90_float, dimid, varid(ndim + 1), &
4133 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4134 ! add attributes
4135 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
4136 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
4137 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
4138 if (present(attributes)) then
4139 do i = 1, size(attributes, dim = 1)
4140 if (trim(attributes(i, 1)) .eq. 'missing_value') then
4141 ! write number
4142 read(attributes(i, 2), '(F10.2)') dummy(1)
4143 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4144 trim(attributes(i, 1)), dummy(1)))
4145 else
4146 ! write string
4147 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4148 trim(attributes(i, 1)), trim(attributes(i, 2))))
4149 end if
4150 end do
4151 end if
4152 ! end definition
4153 call check(nf90_enddef(f_handle))
4154 end if
4155 ! check dimensions before writing
4156 do i = 1, ndim_const
4157 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4158 if (trim(dummy_name) .ne. dnames(i)) &
4159 stop "var2nc_3d_sp: dimension name problem."
4160 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4161 stop "var2nc_3d_sp: variable dimension /= file variable dimension."
4162 end do
4163 ! write variable
4164 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4165 ! close netcdf_dataset
4166 if (present(ncid)) then
4167 if (ncid < 0_i4) ncid = f_handle
4168 else
4169 call close_netcdf(f_handle)
4170 end if
4171 !
4172 end subroutine var2nc_3d_sp
4173
4174 subroutine var2nc_3d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
4175 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 integer(i4), dimension(:), allocatable :: chunksizes
4200 integer(i4), dimension(:), allocatable :: start ! start array for write
4201 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 integer(i4), dimension(:), allocatable :: dims
4208 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4209 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4210 integer(i4) :: i ! loop indices
4211 integer(i4), dimension(:), allocatable :: dummy_count
4212 real(dp), dimension(1) :: dummy ! dummy read
4213 logical :: openfile ! tmp logical
4214 !
4215 ndim = size(dnames, 1)
4216 ! consistency checks
4217 d_unlimit = 0_i4
4218 if (present(dim_unlimited)) d_unlimit = dim_unlimited
4219 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4220 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4221 stop '***ERROR see StdOut'
4222 end if
4223 if (ndim .gt. ndim_const + 1) then
4224 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4225 stop '***ERROR see StdOut'
4226 end if
4227 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4228 (d_unlimit .lt. 0_i4)) then
4229 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4230 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4231 stop '***ERROR see StdOut'
4232 end if
4233 !
4234 allocate(chunksizes(ndim))
4235 allocate(start(ndim))
4236 allocate(counter(ndim))
4237 allocate(dims(ndim))
4238 allocate(dimid(ndim))
4239 allocate(varid(1 + ndim))
4240 allocate(dummy_count(ndim))
4241 ! initialize
4242 deflate = 1
4243 if (ndim .gt. ndim_const) then
4244 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), 1 /)
4245 dims(1 : ndim - 1) = shape(arr)
4246 dims(ndim) = 1
4247 else
4248 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3) /)
4249 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4250 dims(1 : ndim_const) = shape(arr)
4251 end if
4252 start(:) = 1_i4
4253 counter(:) = dims
4254 dummy_count = 1
4255 dummy = nf90_fill_double
4256 ! open the netcdf file
4257 if (present(ncid)) then
4258 if (ncid < 0_i4) then
4259 openfile = .true.
4260 else
4261 openfile = .false.
4262 f_handle = ncid
4263 end if
4264 else
4265 openfile = .true.
4266 end if
4267 if (openfile) then
4268 create_loc = .false.
4269 if (present(create)) create_loc = create
4270 f_handle = open_netcdf(f_name, create = create_loc)
4271 end if
4272 ! check whether variable exists
4273 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4274 ! append
4275 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4276 ! consistency checks
4277 if (idim .ne. ndim) stop "var2nc_3d_dp: number of variable dimensions /= number of file variable dimensions."
4278 ! check unlimited dimension
4279 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
4280 if (u_dimid .eq. -1) stop 'var2nc_3d_dp: cannot append, no unlimited dimension defined'
4281 ! check for unlimited dimension
4282 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_3d_dp: unlimited dimension not specified correctly'
4283 if (present(nrec)) then
4284 start(d_unlimit) = nrec
4285 else
4286 ! get length of unlimited dimension
4287 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4288 ! adapt start, that is find last written chunk
4289 do i = u_len, 1, -1
4290 if (ne(dummy(1), nf90_fill_double)) exit
4291 start(d_unlimit) = i
4292 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4293 end do
4294 start(d_unlimit) = start(d_unlimit) + 1
4295 end if
4296 else
4297 ! define dimensions
4298 do i = 1, ndim
4299 ! check whether dimension exists
4300 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4301 ! create dimension
4302 if (i .eq. d_unlimit) then
4303 ! define unlimited dimension
4304 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
4305 else
4306 ! define limited dimension
4307 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 call check(nf90_def_var(f_handle, v_name, nf90_double, dimid, varid(ndim + 1), &
4313 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4314 ! add attributes
4315 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
4316 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
4317 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
4318 if (present(attributes)) then
4319 do i = 1, size(attributes, dim = 1)
4320 if (trim(attributes(i, 1)) .eq. 'missing_value') then
4321 ! write number
4322 read(attributes(i, 2), '(F10.2)') dummy(1)
4323 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4324 trim(attributes(i, 1)), dummy(1)))
4325 else
4326 ! write string
4327 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4328 trim(attributes(i, 1)), trim(attributes(i, 2))))
4329 end if
4330 end do
4331 end if
4332 ! end definition
4333 call check(nf90_enddef(f_handle))
4334 end if
4335 ! check dimensions before writing
4336 do i = 1, ndim_const
4337 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4338 if (trim(dummy_name) .ne. dnames(i)) &
4339 stop "var2nc_3d_dp: dimension name problem."
4340 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4341 stop "var2nc_3d_dp: variable dimension /= file variable dimension."
4342 end do
4343 ! write variable
4344 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4345 ! close netcdf_dataset
4346 if (present(ncid)) then
4347 if (ncid < 0_i4) ncid = f_handle
4348 else
4349 call close_netcdf(f_handle)
4350 end if
4351 !
4352 end subroutine var2nc_3d_dp
4353
4354 subroutine var2nc_4d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
4355 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 integer(i4), dimension(:), allocatable :: chunksizes
4380 integer(i4), dimension(:), allocatable :: start ! start array for write
4381 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 integer(i4), dimension(:), allocatable :: dims
4388 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4389 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4390 integer(i4) :: i ! loop indices
4391 integer(i4), dimension(:), allocatable :: dummy_count
4392 integer(i4), dimension(1) :: dummy ! dummy read
4393 logical :: openfile ! tmp logical
4394 !
4395 ndim = size(dnames, 1)
4396 ! consistency checks
4397 d_unlimit = 0_i4
4398 if (present(dim_unlimited)) d_unlimit = dim_unlimited
4399 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4400 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4401 stop '***ERROR see StdOut'
4402 end if
4403 if (ndim .gt. ndim_const + 1) then
4404 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4405 stop '***ERROR see StdOut'
4406 end if
4407 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4408 (d_unlimit .lt. 0_i4)) then
4409 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4410 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4411 stop '***ERROR see StdOut'
4412 end if
4413 !
4414 allocate(chunksizes(ndim))
4415 allocate(start(ndim))
4416 allocate(counter(ndim))
4417 allocate(dims(ndim))
4418 allocate(dimid(ndim))
4419 allocate(varid(1 + ndim))
4420 allocate(dummy_count(ndim))
4421 ! initialize
4422 deflate = 1
4423 if (ndim .gt. ndim_const) then
4424 chunksizes = (/ size(arr, 1), size(arr, 2), &
4425 size(arr, 3), size(arr, 4), 1 /)
4426 dims(1 : ndim - 1) = shape(arr)
4427 dims(ndim) = 1
4428 else
4429 chunksizes = (/ size(arr, 1), size(arr, 2), &
4430 size(arr, 3), size(arr, 4) /)
4431 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4432 dims(1 : ndim_const) = shape(arr)
4433 end if
4434 start(:) = 1_i4
4435 counter(:) = dims
4436 dummy_count = 1_i4
4437 dummy = nf90_fill_int
4438 ! open the netcdf file
4439 if (present(ncid)) then
4440 if (ncid < 0_i4) then
4441 openfile = .true.
4442 else
4443 openfile = .false.
4444 f_handle = ncid
4445 end if
4446 else
4447 openfile = .true.
4448 end if
4449 if (openfile) then
4450 create_loc = .false.
4451 if (present(create)) create_loc = create
4452 f_handle = open_netcdf(f_name, create = create_loc)
4453 end if
4454 ! check whether variable exists
4455 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4456 ! append
4457 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4458 ! consistency checks
4459 if (idim .ne. ndim) stop "var2nc_4d_i4: number of variable dimensions /= number of file variable dimensions."
4460 ! check unlimited dimension
4461 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
4462 if (u_dimid .eq. -1) stop 'var2nc_4d_i4: cannot append, no unlimited dimension defined'
4463 ! check for unlimited dimension
4464 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_4d_sp: unlimited dimension not specified correctly'
4465 if (present(nrec)) then
4466 start(d_unlimit) = nrec
4467 else
4468 ! get length of unlimited dimension
4469 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4470 ! adapt start, that is find last written chunk
4471 do i = u_len, 1, -1
4472 if (dummy(1) /= nf90_fill_int) exit
4473 start(d_unlimit) = i
4474 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4475 end do
4476 start(d_unlimit) = start(d_unlimit) + 1
4477 end if
4478 else
4479 ! define dimensions
4480 do i = 1, ndim
4481 ! check whether dimension exists
4482 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4483 ! create dimension
4484 if (i .eq. d_unlimit) then
4485 ! define unlimited dimension
4486 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
4487 else
4488 ! define limited dimension
4489 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 call check(nf90_def_var(f_handle, v_name, nf90_int, dimid, varid(ndim + 1), &
4495 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4496 ! add attributes
4497 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
4498 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
4499 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
4500 if (present(attributes)) then
4501 do i = 1, size(attributes, dim = 1)
4502 if (trim(attributes(i, 1)) .eq. 'missing_value') then
4503 ! write number
4504 read(attributes(i, 2), '(I6)') dummy(1)
4505 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4506 trim(attributes(i, 1)), dummy(1)))
4507 else
4508 ! write string
4509 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4510 trim(attributes(i, 1)), trim(attributes(i, 2))))
4511 end if
4512 end do
4513 end if
4514 ! end definition
4515 call check(nf90_enddef(f_handle))
4516 end if
4517 ! check dimensions before writing
4518 do i = 1, ndim_const
4519 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4520 if (trim(dummy_name) .ne. dnames(i)) &
4521 stop "var2nc_4d_i4: dimension name problem."
4522 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4523 stop "var2nc_4d_i4: variable dimension /= file variable dimension."
4524 end do
4525 ! write variable
4526 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4527 ! close netcdf_dataset
4528 if (present(ncid)) then
4529 if (ncid < 0_i4) ncid = f_handle
4530 else
4531 call close_netcdf(f_handle)
4532 end if
4533 !
4534 end subroutine var2nc_4d_i4
4535
4536 subroutine var2nc_4d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
4537 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 integer(i4), dimension(:), allocatable :: chunksizes
4562 integer(i4), dimension(:), allocatable :: start ! start array for write
4563 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 integer(i4), dimension(:), allocatable :: dims
4570 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4571 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4572 integer(i4) :: i ! loop indices
4573 integer(i4), dimension(:), allocatable :: dummy_count
4574 real(sp), dimension(1) :: dummy ! dummy read
4575 logical :: openfile ! tmp logical
4576 !
4577 ndim = size(dnames, 1)
4578 ! consistency checks
4579 d_unlimit = 0_i4
4580 if (present(dim_unlimited)) d_unlimit = dim_unlimited
4581 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4582 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4583 stop '***ERROR see StdOut'
4584 end if
4585 if (ndim .gt. ndim_const + 1) then
4586 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4587 stop '***ERROR see StdOut'
4588 end if
4589 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4590 (d_unlimit .lt. 0_i4)) then
4591 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4592 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4593 stop '***ERROR see StdOut'
4594 end if
4595 !
4596 allocate(chunksizes(ndim))
4597 allocate(start(ndim))
4598 allocate(counter(ndim))
4599 allocate(dims(ndim))
4600 allocate(dimid(ndim))
4601 allocate(varid(1 + ndim))
4602 allocate(dummy_count(ndim))
4603 ! initialize
4604 deflate = 1
4605 if (ndim .gt. ndim_const) then
4606 chunksizes = (/ size(arr, 1), size(arr, 2), &
4607 size(arr, 3), size(arr, 4), 1 /)
4608 dims(1 : ndim - 1) = shape(arr)
4609 dims(ndim) = 1
4610 else
4611 chunksizes = (/ size(arr, 1), size(arr, 2), &
4612 size(arr, 3), size(arr, 4) /)
4613 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4614 dims(1 : ndim_const) = shape(arr)
4615 end if
4616 start(:) = 1_i4
4617 counter(:) = dims
4618 dummy_count = 1_i4
4619 dummy = nf90_fill_float
4620 ! open the netcdf file
4621 if (present(ncid)) then
4622 if (ncid < 0_i4) then
4623 openfile = .true.
4624 else
4625 openfile = .false.
4626 f_handle = ncid
4627 end if
4628 else
4629 openfile = .true.
4630 end if
4631 if (openfile) then
4632 create_loc = .false.
4633 if (present(create)) create_loc = create
4634 f_handle = open_netcdf(f_name, create = create_loc)
4635 end if
4636 ! check whether variable exists
4637 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4638 ! append
4639 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4640 ! consistency checks
4641 if (idim .ne. ndim) stop "var2nc_4d_sp: number of variable dimensions /= number of file variable dimensions."
4642 ! check unlimited dimension
4643 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
4644 if (u_dimid .eq. -1) stop 'var2nc_4d_sp: cannot append, no unlimited dimension defined'
4645 ! check for unlimited dimension
4646 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_4d_sp: unlimited dimension not specified correctly'
4647 if (present(nrec)) then
4648 start(d_unlimit) = nrec
4649 else
4650 ! get length of unlimited dimension
4651 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4652 ! adapt start, that is find last written chunk
4653 do i = u_len, 1, -1
4654 if (ne(dummy(1), nf90_fill_float)) exit
4655 start(d_unlimit) = i
4656 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4657 end do
4658 start(d_unlimit) = start(d_unlimit) + 1
4659 end if
4660 else
4661 ! define dimensions
4662 do i = 1, ndim
4663 ! check whether dimension exists
4664 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4665 ! create dimension
4666 if (i .eq. d_unlimit) then
4667 ! define unlimited dimension
4668 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
4669 else
4670 ! define limited dimension
4671 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 call check(nf90_def_var(f_handle, v_name, nf90_float, dimid, varid(ndim + 1), &
4677 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4678 ! add attributes
4679 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
4680 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
4681 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
4682 if (present(attributes)) then
4683 do i = 1, size(attributes, dim = 1)
4684 if (trim(attributes(i, 1)) .eq. 'missing_value') then
4685 ! write number
4686 read(attributes(i, 2), '(F10.2)') dummy(1)
4687 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4688 trim(attributes(i, 1)), dummy(1)))
4689 else
4690 ! write string
4691 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4692 trim(attributes(i, 1)), trim(attributes(i, 2))))
4693 end if
4694 end do
4695 end if
4696 ! end definition
4697 call check(nf90_enddef(f_handle))
4698 end if
4699 ! check dimensions before writing
4700 do i = 1, ndim_const
4701 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4702 if (trim(dummy_name) .ne. dnames(i)) &
4703 stop "var2nc_4d_sp: dimension name problem."
4704 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4705 stop "var2nc_4d_sp: variable dimension /= file variable dimension."
4706 end do
4707 ! write variable
4708 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4709 ! close netcdf_dataset
4710 if (present(ncid)) then
4711 if (ncid < 0_i4) ncid = f_handle
4712 else
4713 call close_netcdf(f_handle)
4714 end if
4715 !
4716 end subroutine var2nc_4d_sp
4717
4718 subroutine var2nc_4d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
4719 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 integer(i4), dimension(:), allocatable :: chunksizes
4744 integer(i4), dimension(:), allocatable :: start ! start array for write
4745 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 integer(i4), dimension(:), allocatable :: dims
4752 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4753 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4754 integer(i4) :: i ! loop indices
4755 integer(i4), dimension(:), allocatable :: dummy_count
4756 real(dp), dimension(1) :: dummy ! dummy read
4757 logical :: openfile ! tmp logical
4758 !
4759 ndim = size(dnames, 1)
4760 ! consistency checks
4761 d_unlimit = 0_i4
4762 if (present(dim_unlimited)) d_unlimit = dim_unlimited
4763 if ((ndim .eq. ndim_const + 1) .and. (d_unlimit .ne. ndim_const + 1)) then
4764 print *, '***ERROR one more dimension name specified than dimension of array, but the last one is not unlimited'
4765 stop '***ERROR see StdOut'
4766 end if
4767 if (ndim .gt. ndim_const + 1) then
4768 print *, '***ERROR too many dimension name specified, should be atmost ndim_const + 1'
4769 stop '***ERROR see StdOut'
4770 end if
4771 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4772 (d_unlimit .lt. 0_i4)) then
4773 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4774 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4775 stop '***ERROR see StdOut'
4776 end if
4777 !
4778 allocate(chunksizes(ndim))
4779 allocate(start(ndim))
4780 allocate(counter(ndim))
4781 allocate(dims(ndim))
4782 allocate(dimid(ndim))
4783 allocate(varid(1 + ndim))
4784 allocate(dummy_count(ndim))
4785 ! Initialize
4786 deflate = 1
4787 if (ndim .gt. ndim_const) then
4788 chunksizes = (/ size(arr, 1), size(arr, 2), &
4789 size(arr, 3), size(arr, 4), 1 /)
4790 dims(1 : ndim - 1) = shape(arr)
4791 dims(ndim) = 1
4792 else
4793 chunksizes = (/ size(arr, 1), size(arr, 2), &
4794 size(arr, 3), size(arr, 4) /)
4795 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4796 dims(1 : ndim_const) = shape(arr)
4797 end if
4798 start(:) = 1_i4
4799 counter(:) = dims
4800 dummy_count = 1
4801 dummy = nf90_fill_double
4802 ! open the netcdf file
4803 if (present(ncid)) then
4804 if (ncid < 0_i4) then
4805 openfile = .true.
4806 else
4807 openfile = .false.
4808 f_handle = ncid
4809 end if
4810 else
4811 openfile = .true.
4812 end if
4813 if (openfile) then
4814 create_loc = .false.
4815 if (present(create)) create_loc = create
4816 f_handle = open_netcdf(f_name, create = create_loc)
4817 end if
4818 ! check whether variable exists
4819 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4820 ! append
4821 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4822 ! consistency checks
4823 if (idim .ne. ndim) stop "var2nc_4d_dp: number of variable dimensions /= number of file variable dimensions."
4824 ! check unlimited dimension
4825 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
4826 if (u_dimid .eq. -1) stop 'var2nc_4d_dp: cannot append, no unlimited dimension defined'
4827 ! check for unlimited dimension
4828 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_4d_dp: unlimited dimension not specified correctly'
4829 if (present(nrec)) then
4830 start(d_unlimit) = nrec
4831 else
4832 ! get length of unlimited dimension
4833 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
4834 ! adapt start, that is find last written chunk
4835 do i = u_len, 1, -1
4836 if (ne(dummy(1), nf90_fill_double)) exit
4837 start(d_unlimit) = i
4838 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
4839 end do
4840 start(d_unlimit) = start(d_unlimit) + 1
4841 end if
4842 else
4843 ! define dimensions
4844 do i = 1, ndim
4845 ! check whether dimension exists
4846 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
4847 ! create dimension
4848 if (i .eq. d_unlimit) then
4849 ! define unlimited dimension
4850 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
4851 else
4852 ! define limited dimension
4853 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 call check(nf90_def_var(f_handle, v_name, nf90_double, dimid, varid(ndim + 1), &
4859 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
4860 ! add attributes
4861 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
4862 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
4863 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
4864 if (present(attributes)) then
4865 do i = 1, size(attributes, dim = 1)
4866 if (trim(attributes(i, 1)) .eq. 'missing_value') then
4867 ! write number
4868 read(attributes(i, 2), '(F10.2)') dummy(1)
4869 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4870 trim(attributes(i, 1)), dummy(1)))
4871 else
4872 ! write string
4873 call check(nf90_put_att(f_handle, varid(ndim + 1), &
4874 trim(attributes(i, 1)), trim(attributes(i, 2))))
4875 end if
4876 end do
4877 end if
4878 ! end definition
4879 call check(nf90_enddef(f_handle))
4880 end if
4881 ! check dimensions before writing
4882 do i = 1, ndim_const
4883 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
4884 if (trim(dummy_name) .ne. dnames(i)) &
4885 stop "var2nc_4d_dp: dimension name problem."
4886 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
4887 stop "var2nc_4d_dp: variable dimension /= file variable dimension."
4888 end do
4889 ! write variable
4890 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
4891 ! close netcdf_dataset
4892 if (present(ncid)) then
4893 if (ncid < 0_i4) ncid = f_handle
4894 else
4895 call close_netcdf(f_handle)
4896 end if
4897 !
4898 end subroutine var2nc_4d_dp
4899
4900 subroutine var2nc_5d_i4(f_name, arr, dnames, v_name, dim_unlimited, &
4901 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 integer(i4), dimension(:), allocatable :: chunksizes
4926 integer(i4), dimension(:), allocatable :: start ! start array for write
4927 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 integer(i4), dimension(:), allocatable :: dims
4934 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
4935 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
4936 integer(i4) :: i ! loop indices
4937 integer(i4), dimension(:), allocatable :: dummy_count
4938 integer(i4), dimension(1) :: dummy ! dummy read
4939 logical :: openfile ! tmp logical
4940 !
4941 ndim = size(dnames, 1)
4942 d_unlimit = 0_i4
4943 if (present(dim_unlimited)) d_unlimit = dim_unlimited
4944 ! consistency checks
4945 if (ndim .gt. ndim_const) then
4946 print *, '***ERROR more than five dimension names given'
4947 stop '***ERROR see StdOut'
4948 end if
4949 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
4950 (d_unlimit .lt. 0_i4)) then
4951 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
4952 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
4953 stop '***ERROR see StdOut'
4954 end if
4955 !
4956 allocate(chunksizes(ndim))
4957 allocate(start(ndim))
4958 allocate(counter(ndim))
4959 allocate(dims(ndim))
4960 allocate(dimid(ndim))
4961 allocate(varid(1 + ndim))
4962 allocate(dummy_count(ndim))
4963 ! initialize
4964 deflate = 1
4965 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), size(arr, 4), size(arr, 5) /)
4966 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
4967 dims(1 : ndim) = shape(arr)
4968 start(:) = 1_i4
4969 counter(:) = dims
4970 dummy_count = 1_i4
4971 dummy = nf90_fill_int
4972 d_unlimit = 0_i4
4973 if (present(dim_unlimited)) d_unlimit = dim_unlimited
4974 ! open the netcdf file
4975 if (present(ncid)) then
4976 if (ncid < 0_i4) then
4977 openfile = .true.
4978 else
4979 openfile = .false.
4980 f_handle = ncid
4981 end if
4982 else
4983 openfile = .true.
4984 end if
4985 if (openfile) then
4986 create_loc = .false.
4987 if (present(create)) create_loc = create
4988 f_handle = open_netcdf(f_name, create = create_loc)
4989 end if
4990 ! check whether variable exists
4991 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
4992 ! append
4993 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
4994 ! consistency checks
4995 if (idim .ne. ndim) stop "var2nc_5d_i4: number of variable dimensions /= number of file variable dimensions."
4996 ! check unlimited dimension
4997 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
4998 if (u_dimid .eq. -1) stop 'var2nc_5d_i4: cannot append, no unlimited dimension defined'
4999 ! check for unlimited dimension
5000 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_5d_sp: unlimited dimension not specified correctly'
5001 if (present(nrec)) then
5002 start(d_unlimit) = nrec
5003 else
5004 ! get length of unlimited dimension
5005 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
5006 ! adapt start, that is find last written chunk
5007 do i = u_len, 1, -1
5008 if (dummy(1) /= nf90_fill_int) exit
5009 start(d_unlimit) = i
5010 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
5011 end do
5012 start(d_unlimit) = start(d_unlimit) + 1
5013 end if
5014 else
5015 ! define dimensions
5016 do i = 1, ndim
5017 ! check whether dimension exists
5018 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
5019 ! create dimension
5020 if (i .eq. d_unlimit) then
5021 ! define unlimited dimension
5022 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
5023 else
5024 ! define limited dimension
5025 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 call check(nf90_def_var(f_handle, v_name, nf90_int, dimid, varid(ndim + 1), &
5031 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
5032 ! add attributes
5033 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
5034 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
5035 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
5036 if (present(attributes)) then
5037 do i = 1, size(attributes, dim = 1)
5038 if (trim(attributes(i, 1)) .eq. 'missing_value') then
5039 ! write number
5040 read(attributes(i, 2), '(I6)') dummy(1)
5041 call check(nf90_put_att(f_handle, varid(ndim + 1), &
5042 trim(attributes(i, 1)), dummy(1)))
5043 else
5044 ! write string
5045 call check(nf90_put_att(f_handle, varid(ndim + 1), &
5046 trim(attributes(i, 1)), trim(attributes(i, 2))))
5047 end if
5048 end do
5049 end if
5050 ! end definition
5051 call check(nf90_enddef(f_handle))
5052 end if
5053 ! check dimensions before writing
5054 do i = 1, ndim_const
5055 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
5056 if (trim(dummy_name) .ne. dnames(i)) &
5057 stop "var2nc_5d_i4: dimension name problem."
5058 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
5059 stop "var2nc_5d_i4: variable dimension /= file variable dimension."
5060 end do
5061 ! write variable
5062 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
5063 ! close netcdf_dataset
5064 if (present(ncid)) then
5065 if (ncid < 0_i4) ncid = f_handle
5066 else
5067 call close_netcdf(f_handle)
5068 end if
5069 !
5070 end subroutine var2nc_5d_i4
5071
5072 subroutine var2nc_5d_sp(f_name, arr, dnames, v_name, dim_unlimited, &
5073 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 integer(i4), dimension(:), allocatable :: chunksizes
5098 integer(i4), dimension(:), allocatable :: start ! start array for write
5099 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 integer(i4), dimension(:), allocatable :: dims
5106 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
5107 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
5108 integer(i4) :: i ! loop indices
5109 integer(i4), dimension(:), allocatable :: dummy_count
5110 real(sp), dimension(1) :: dummy ! dummy read
5111 logical :: openfile ! tmp logical
5112 !
5113 ndim = size(dnames, 1)
5114 d_unlimit = 0_i4
5115 if (present(dim_unlimited)) d_unlimit = dim_unlimited
5116 ! consistency checks
5117 if (ndim .gt. ndim_const) then
5118 print *, '***ERROR more than five dimension names given'
5119 stop '***ERROR see StdOut'
5120 end if
5121 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
5122 (d_unlimit .lt. 0_i4)) then
5123 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
5124 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
5125 stop '***ERROR see StdOut'
5126 end if
5127 !
5128 allocate(chunksizes(ndim))
5129 allocate(start(ndim))
5130 allocate(counter(ndim))
5131 allocate(dims(ndim))
5132 allocate(dimid(ndim))
5133 allocate(varid(1 + ndim))
5134 allocate(dummy_count(ndim))
5135 ! initialize
5136 deflate = 1
5137 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), size(arr, 4), size(arr, 5) /)
5138 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
5139 dims(1 : ndim) = shape(arr)
5140 start(:) = 1_i4
5141 counter(:) = dims
5142 dummy_count = 1_i4
5143 dummy = nf90_fill_float
5144 d_unlimit = 0_i4
5145 if (present(dim_unlimited)) d_unlimit = dim_unlimited
5146 ! open the netcdf file
5147 if (present(ncid)) then
5148 if (ncid < 0_i4) then
5149 openfile = .true.
5150 else
5151 openfile = .false.
5152 f_handle = ncid
5153 end if
5154 else
5155 openfile = .true.
5156 end if
5157 if (openfile) then
5158 create_loc = .false.
5159 if (present(create)) create_loc = create
5160 f_handle = open_netcdf(f_name, create = create_loc)
5161 end if
5162 ! check whether variable exists
5163 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
5164 ! append
5165 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
5166 ! consistency checks
5167 if (idim .ne. ndim) stop "var2nc_5d_sp: number of variable dimensions /= number of file variable dimensions."
5168 ! check unlimited dimension
5169 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
5170 if (u_dimid .eq. -1) stop 'var2nc_5d_sp: cannot append, no unlimited dimension defined'
5171 ! check for unlimited dimension
5172 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_5d_sp: unlimited dimension not specified correctly'
5173 if (present(nrec)) then
5174 start(d_unlimit) = nrec
5175 else
5176 ! get length of unlimited dimension
5177 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
5178 ! adapt start, that is find last written chunk
5179 do i = u_len, 1, -1
5180 if (ne(dummy(1), nf90_fill_float)) exit
5181 start(d_unlimit) = i
5182 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
5183 end do
5184 start(d_unlimit) = start(d_unlimit) + 1
5185 end if
5186 else
5187 ! define dimensions
5188 do i = 1, ndim
5189 ! check whether dimension exists
5190 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
5191 ! create dimension
5192 if (i .eq. d_unlimit) then
5193 ! define unlimited dimension
5194 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
5195 else
5196 ! define limited dimension
5197 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 call check(nf90_def_var(f_handle, v_name, nf90_float, dimid, varid(ndim + 1), &
5203 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
5204 ! add attributes
5205 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
5206 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
5207 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
5208 if (present(attributes)) then
5209 do i = 1, size(attributes, dim = 1)
5210 if (trim(attributes(i, 1)) .eq. 'missing_value') then
5211 ! write number
5212 read(attributes(i, 2), '(F10.2)') dummy(1)
5213 call check(nf90_put_att(f_handle, varid(ndim + 1), &
5214 trim(attributes(i, 1)), dummy(1)))
5215 else
5216 ! write string
5217 call check(nf90_put_att(f_handle, varid(ndim + 1), &
5218 trim(attributes(i, 1)), trim(attributes(i, 2))))
5219 end if
5220 end do
5221 end if
5222 ! end definition
5223 call check(nf90_enddef(f_handle))
5224 end if
5225 ! check dimensions before writing
5226 do i = 1, ndim_const
5227 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
5228 if (trim(dummy_name) .ne. dnames(i)) &
5229 stop "var2nc_5d_sp: dimension name problem."
5230 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
5231 stop "var2nc_5d_sp: variable dimension /= file variable dimension."
5232 end do
5233 ! write variable
5234 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
5235 ! close netcdf_dataset
5236 if (present(ncid)) then
5237 if (ncid < 0_i4) ncid = f_handle
5238 else
5239 call close_netcdf(f_handle)
5240 end if
5241 !
5242 end subroutine var2nc_5d_sp
5243
5244 subroutine var2nc_5d_dp(f_name, arr, dnames, v_name, dim_unlimited, &
5245 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 integer(i4), dimension(:), allocatable :: chunksizes
5270 integer(i4), dimension(:), allocatable :: start ! start array for write
5271 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 integer(i4), dimension(:), allocatable :: dims
5278 integer(i4), dimension(:), allocatable :: dimid ! netcdf IDs of each dimension
5279 integer(i4), dimension(:), allocatable :: varid ! dimension variables and var id
5280 integer(i4) :: i ! loop indices
5281 integer(i4), dimension(:), allocatable :: dummy_count
5282 real(dp), dimension(1) :: dummy ! dummy read
5283 logical :: openfile ! tmp logical
5284 !
5285 ndim = size(dnames, 1)
5286 d_unlimit = 0_i4
5287 if (present(dim_unlimited)) d_unlimit = dim_unlimited
5288 ! consistency checks
5289 if (ndim .gt. ndim_const) then
5290 print *, '***ERROR more than five dimension names given'
5291 stop '***ERROR see StdOut'
5292 end if
5293 if (((ndim .eq. ndim_const) .and. (d_unlimit .gt. ndim_const)) .or. &
5294 (d_unlimit .lt. 0_i4)) then
5295 print*, '***ERROR unlimited dimension out of bounds, must be positive but not greater than number of given dimensions'
5296 print*, '***Dims: ', ndim, ndim_const, d_unlimit, ndim_const, d_unlimit
5297 stop '***ERROR see StdOut'
5298 end if
5299 !
5300 allocate(chunksizes(ndim))
5301 allocate(start(ndim))
5302 allocate(counter(ndim))
5303 allocate(dims(ndim))
5304 allocate(dimid(ndim))
5305 allocate(varid(1 + ndim))
5306 allocate(dummy_count(ndim))
5307 ! initialize
5308 deflate = 1
5309 chunksizes = (/ size(arr, 1), size(arr, 2), size(arr, 3), size(arr, 4), size(arr, 5) /)
5310 if (d_unlimit .gt. 0) chunksizes(d_unlimit) = 1
5311 dims(1 : ndim) = shape(arr)
5312 start(:) = 1_i4
5313 counter(:) = dims
5314 dummy_count = 1
5315 dummy = nf90_fill_double
5316 d_unlimit = 0_i4
5317 if (present(dim_unlimited)) d_unlimit = dim_unlimited
5318 ! open the netcdf file
5319 if (present(ncid)) then
5320 if (ncid < 0_i4) then
5321 openfile = .true.
5322 else
5323 openfile = .false.
5324 f_handle = ncid
5325 end if
5326 else
5327 openfile = .true.
5328 end if
5329 if (openfile) then
5330 create_loc = .false.
5331 if (present(create)) create_loc = create
5332 f_handle = open_netcdf(f_name, create = create_loc)
5333 end if
5334 ! check whether variable exists
5335 if (nf90_noerr .eq. nf90_inq_varid(f_handle, v_name, varid(ndim + 1))) then
5336 ! append
5337 call check(nf90_inquire_variable(f_handle, varid(ndim + 1), ndims = idim, dimids = dimid))
5338 ! consistency checks
5339 if (idim .ne. ndim) stop "var2nc_5d_dp: number of variable dimensions /= number of file variable dimensions."
5340 ! check unlimited dimension
5341 call check(nf90_inquire(f_handle, unlimiteddimid = u_dimid))
5342 if (u_dimid .eq. -1) stop 'var2nc_5d_dp: cannot append, no unlimited dimension defined'
5343 ! check for unlimited dimension
5344 if (dimid(d_unlimit) .ne. u_dimid) stop 'var2nc_5d_dp: unlimited dimension not specified correctly'
5345 if (present(nrec)) then
5346 start(d_unlimit) = nrec
5347 else
5348 ! get length of unlimited dimension
5349 call check(nf90_inquire_dimension(f_handle, u_dimid, len = u_len))
5350 ! adapt start, that is find last written chunk
5351 do i = u_len, 1, -1
5352 if (ne(dummy(1), nf90_fill_double)) exit
5353 start(d_unlimit) = i
5354 call check(nf90_get_var(f_handle, varid(ndim + 1), dummy, start, dummy_count))
5355 end do
5356 start(d_unlimit) = start(d_unlimit) + 1
5357 end if
5358 else
5359 ! define dimensions
5360 do i = 1, ndim
5361 ! check whether dimension exists
5362 if (nf90_noerr .ne. nf90_inq_dimid(f_handle, dnames(i), dimid(i))) then
5363 ! create dimension
5364 if (i .eq. d_unlimit) then
5365 ! define unlimited dimension
5366 call check(nf90_def_dim(f_handle, trim(dnames(i)), nf90_unlimited, dimid(i)))
5367 else
5368 ! define limited dimension
5369 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 call check(nf90_def_var(f_handle, v_name, nf90_double, dimid, varid(ndim + 1), &
5375 chunksizes = chunksizes(:), shuffle = .true., deflate_level = deflate))
5376 ! add attributes
5377 if (present(long_name)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'long_name', long_name))
5378 if (present(units)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'units', units))
5379 if (present(missing_value)) call check(nf90_put_att(f_handle, varid(ndim + 1), 'missing_value', missing_value))
5380 if (present(attributes)) then
5381 do i = 1, size(attributes, dim = 1)
5382 if (trim(attributes(i, 1)) .eq. 'missing_value') then
5383 ! write number
5384 read(attributes(i, 2), '(F10.2)') dummy(1)
5385 call check(nf90_put_att(f_handle, varid(ndim + 1), &
5386 trim(attributes(i, 1)), dummy(1)))
5387 else
5388 ! write string
5389 call check(nf90_put_att(f_handle, varid(ndim + 1), &
5390 trim(attributes(i, 1)), trim(attributes(i, 2))))
5391 end if
5392 end do
5393 end if
5394 ! end definition
5395 call check(nf90_enddef(f_handle))
5396 end if
5397 ! check dimensions before writing
5398 do i = 1, ndim_const
5399 call check(nf90_inquire_dimension(f_handle, dimid(i), dummy_name, dims(i)))
5400 if (trim(dummy_name) .ne. dnames(i)) &
5401 stop "var2nc_5d_dp: dimension name problem."
5402 if ((dims(i) .ne. size(arr, i)) .and. (d_unlimit .ne. i)) &
5403 stop "var2nc_5d_dp: variable dimension /= file variable dimension."
5404 end do
5405 ! write variable
5406 call check(nf90_put_var(f_handle, varid(ndim + 1), arr, start, counter))
5407 ! close netcdf_dataset
5408 if (present(ncid)) then
5409 if (ncid < 0_i4) ncid = f_handle
5410 else
5411 call close_netcdf(f_handle)
5412 end if
5413 !
5414 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 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 do i = 1, nvars
5462 if (.not. v(i)%unlimited) cycle
5463 if (.not. v(i)%wFlag) cycle
5464 v(i)%start (v(i)%nDims) = irec
5465 select case (v(i)%xtype)
5466 case(nf90_byte)
5467 select case (v(i)%nDims)
5468 case (0)
5469 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G0_b, v(i)%start))
5470 case (1)
5471 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G1_b, v(i)%start, v(i)%count))
5472 case (2)
5473 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G2_b, v(i)%start, v(i)%count))
5474 case (3)
5475 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G3_b, v(i)%start, v(i)%count))
5476 case (4)
5477 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 select case (v(i)%nDims - 1)
5481 case (0)
5482 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G0_i, v(i)%start))
5483 case (1)
5484 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G1_i, v(i)%start, v(i)%count))
5485 case (2)
5486 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G2_i, v(i)%start, v(i)%count))
5487 case (3)
5488 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G3_i, v(i)%start, v(i)%count))
5489 case (4)
5490 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 select case (v(i)%nDims - 1)
5494 case (0)
5495 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G0_f, v(i)%start))
5496 case (1)
5497 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G1_f, v(i)%start, v(i)%count))
5498 case (2)
5499 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G2_f, v(i)%start, v(i)%count))
5500 case (3)
5501 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G3_f, v(i)%start, v(i)%count))
5502 case (4)
5503 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 select case (v(i)%nDims - 1)
5507 case (0)
5508 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G0_d, v(i)%start))
5509 case (1)
5510 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G1_d, v(i)%start, v(i)%count))
5511 case (2)
5512 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G2_d, v(i)%start, v(i)%count))
5513 case (3)
5514 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G3_d, v(i)%start, v(i)%count))
5515 case (4)
5516 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 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 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 do i = 1, nvars
5559 if (v(i)%unlimited) cycle
5560 if (.not. v(i)%wFlag) cycle
5561 select case (v(i)%xtype)
5562 case(nf90_byte)
5563 select case (v(i)%nDims)
5564 case (0)
5565 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G0_b))
5566 case (1)
5567 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G1_b))
5568 case (2)
5569 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G2_b))
5570 case (3)
5571 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G3_b))
5572 case (4)
5573 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G4_b))
5574 end select
5575 case (nf90_int)
5576 select case (v(i)%nDims)
5577 case (0)
5578 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G0_i))
5579 case (1)
5580 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G1_i))
5581 case (2)
5582 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G2_i))
5583 case (3)
5584 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G3_i))
5585 case (4)
5586 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G4_i))
5587 end select
5588 case (nf90_float)
5589 select case (v(i)%nDims)
5590 case (0)
5591 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G0_f))
5592 case (1)
5593 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G1_f))
5594 case (2)
5595 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G2_f))
5596 case (3)
5597 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G3_f))
5598 case (4)
5599 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G4_f))
5600 end select
5601 case (nf90_double)
5602 select case (v(i)%nDims)
5603 case (0)
5604 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G0_d))
5605 case (1)
5606 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G1_d))
5607 case (2)
5608 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G2_d))
5609 case (3)
5610 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G3_d))
5611 case (4)
5612 call check(nf90_put_var(ncid, v(i)%varId, v(i)%G4_d))
5613 end select
5614 end select
5615 end do
5616
5617 end subroutine write_static_netcdf
5618
5619 ! -----------------------------------------------------------------------------
5620 ! PRIVATE PART
5621 !
5622
5623 ! -----------------------------------------------------------------------------
5624
5625 ! private open netcdf function - returns file handle
5626 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 if (create) then
5635 ! create file
5636 call check(nf90_create(trim(f_name), nf90_netcdf4, open_netcdf))
5637 else
5638 ! open file
5639 call check(nf90_open(trim(f_name), nf90_write, open_netcdf))
5640 end if
5641 end function open_netcdf
5642
5643
5644 ! -----------------------------------------------------------------------------
5645
5646 ! private error checking routine
5647 subroutine check(status)
5648
5649 implicit none
5650
5651 integer(i4), intent(in) :: status
5652
5653 if (status /= nf90_noerr) then
5654 write(*, *) 'mo_ncwrite.check error: ', trim(nf90_strerror(status))
5655 stop
5656 end if
5657
5658 end subroutine check
5659
5660 ! -----------------------------------------------------------------------------
5661
5662end module mo_ncwrite
Variable simple write in netcdf.
Extended dump_netcdf for multiple variables.
Comparison of real values for inequality.
Definition mo_utils.F90:289
Define number representations.
Definition mo_kind.F90:17
integer, parameter sp
Single Precision Real Kind.
Definition mo_kind.F90:44
integer, parameter i4
4 Byte Integer Kind
Definition mo_kind.F90:40
integer, parameter i1
1 Byte Integer Kind
Definition mo_kind.F90:36
integer, parameter dp
Double Precision Real Kind.
Definition mo_kind.F90:46
Writing netcdf files.
integer(i4), parameter, public nmaxatt
nr. max attributes
integer(i4), public ndims
nr. dimensions
integer(i4), parameter, public nmaxdim
nr. max dimensions
integer(i4), parameter, public maxlen
nr. string length
subroutine, public write_static_netcdf(ncid)
static writer
subroutine, public write_dynamic_netcdf(ncid, irec)
dynamic writer
integer(i4), parameter, public nattdim
dim array of attribute values
subroutine, public close_netcdf(ncid)
Closes netcdf file stream.
integer(i4), parameter, public ngatt
nr. global attributes
type(variable), dimension(:), allocatable, public v
variable list, THIS STRUCTURE WILL BE WRITTEN IN THE FILE
type(dims), dimension(:), allocatable, public dnc
dimensions list
integer(i4), public nvars
nr. variables
type(attribute), dimension(ngatt), public gatt
global attributes for netcdf
subroutine, public create_netcdf(filename, ncid, lfs, netcdf4, deflate_level)
Open and write on new netcdf file.
String utilities.
logical function, public nonull(str)
Checks if string was already used.
General utilities for the CHS library.
Definition mo_utils.F90:20
NetCDF attribute.
NetCDF dims.
NetCDF variable.