PartMC  2.3.0
netcdf.F90
Go to the documentation of this file.
1 ! Copyright (C) 2007-2010, 2012 Matthew West
2 ! Licensed under the GNU General Public License version 2 or (at your
3 ! option) any later version. See the file COPYING for details.
4 
5 !> \file
6 !> The pmc_netcdf module.
7 
8 !> Wrapper functions for NetCDF. These all take a NetCDF \c ncid in
9 !> data mode and return with it again in data mode. Shifting to define
10 !> mode is handled internally within each subroutine.
11 module pmc_netcdf
12 
13  use netcdf
14  use pmc_util
15  use pmc_rand
16 
17 contains
18 
19 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20 
21  !> Check the status of a NetCDF function call.
22  subroutine pmc_nc_check(status)
23 
24  !> Status return value.
25  integer, intent(in) :: status
26 
27  if (status /= nf90_noerr) then
28  call die_msg(291021908, nf90_strerror(status))
29  end if
30 
31  end subroutine pmc_nc_check
32 
33 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
34 
35  !> Check the status of a NetCDF function call and prints the given
36  !> error message on failure.
37  subroutine pmc_nc_check_msg(status, error_msg)
38 
39  !> Status return value.
40  integer, intent(in) :: status
41  !> Error message in case of failure.
42  character(len=*), intent(in) :: error_msg
43 
44  if (status /= nf90_noerr) then
45  call die_msg(701841139, trim(error_msg) &
46  // " : " // trim(nf90_strerror(status)))
47  end if
48 
49  end subroutine pmc_nc_check_msg
50 
51 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
52 
53  !> Open a NetCDF file for reading.
54  subroutine pmc_nc_open_read(filename, ncid)
55 
56  !> Filename of NetCDF file to open.
57  character(len=*), intent(in) :: filename
58  !> NetCDF file ID, in data mode.
59  integer, intent(out) :: ncid
60 
61  call pmc_nc_check_msg(nf90_open(filename, nf90_nowrite, ncid), &
62  "opening " // trim(filename) // " for reading")
63 
64  end subroutine pmc_nc_open_read
65 
66 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
67 
68  !> Open a NetCDF file for writing.
69  subroutine pmc_nc_open_write(filename, ncid)
70 
71  !> Filename of NetCDF file to open.
72  character(len=*), intent(in) :: filename
73  !> NetCDF file ID, in data mode, returns in data mode.
74  integer, intent(out) :: ncid
75 
76  call pmc_nc_check_msg(nf90_create(filename, nf90_clobber, ncid), &
77  "opening " // trim(filename) // " for writing")
78  call pmc_nc_check(nf90_enddef(ncid))
79 
80  end subroutine pmc_nc_open_write
81 
82 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
83 
84  !> Close a NetCDF file.
85  subroutine pmc_nc_close(ncid)
86 
87  !> NetCDF file ID, in data mode.
88  integer, intent(in) :: ncid
89 
90  call pmc_nc_check_msg(nf90_close(ncid), "closing NetCDF file")
91 
92  end subroutine pmc_nc_close
93 
94 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
95 
96  !> Write basic information to a NetCDF file.
97  subroutine pmc_nc_write_info(ncid, uuid, source, write_rank, write_n_proc)
98 
99  !> NetCDF file ID, in data mode.
100  integer, intent(in) :: ncid
101  !> UUID for this data set.
102  character(len=PMC_UUID_LEN), intent(in) :: uuid
103  !> Source name for this data.
104  character(len=*), intent(in) :: source
105  !> Rank to write into file.
106  integer, intent(in), optional :: write_rank
107  !> Number of processes to write into file.
108  integer, intent(in), optional :: write_n_proc
109 
110  character(len=(len_trim(source) + 100)) :: history
111  integer :: use_rank, use_n_proc
112 
113  call pmc_nc_check(nf90_redef(ncid))
114  call pmc_nc_check(nf90_put_att(ncid, nf90_global, "title", &
115  trim(source) // " output file"))
116  call pmc_nc_check(nf90_put_att(ncid, nf90_global, "source", source))
117  call pmc_nc_check(nf90_put_att(ncid, nf90_global, "UUID", uuid))
118  call iso8601_date_and_time(history)
119  history((len_trim(history)+1):) = (" created by " // trim(source))
120  call pmc_nc_check(nf90_put_att(ncid, nf90_global, "history", history))
121  call pmc_nc_check(nf90_put_att(ncid, nf90_global, "Conventions", "CF-1.4"))
122  call pmc_nc_check(nf90_enddef(ncid))
123 
124  if (present(write_rank)) then
125  use_rank = write_rank
126  else
127  use_rank = pmc_mpi_rank()
128  end if
129  if (present(write_n_proc)) then
130  use_n_proc = write_n_proc
131  else
132  use_n_proc = pmc_mpi_size()
133  end if
134 
135 #ifdef PMC_USE_MPI
136  call pmc_nc_write_integer(ncid, use_rank + 1, "process", &
137  description="the process number (starting from 1) " &
138  // "that output this data file")
139  call pmc_nc_write_integer(ncid, use_n_proc, "total_processes", &
140  description="total number of processes")
141 #endif
142 
143  end subroutine pmc_nc_write_info
144 
145 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
146 
147  !> Read a single real from a NetCDF file.
148  subroutine pmc_nc_read_real(ncid, var, name, must_be_present)
149 
150  !> NetCDF file ID, in data mode.
151  integer, intent(in) :: ncid
152  !> Data to write.
153  real(kind=dp), intent(out) :: var
154  !> Variable name in NetCDF file.
155  character(len=*), intent(in) :: name
156  !> Whether the variable must be present in the NetCDF file
157  !> (default .true.).
158  logical, optional, intent(in) :: must_be_present
159 
160  integer :: varid, status
161  logical :: use_must_be_present
162 
163  if (present(must_be_present)) then
164  use_must_be_present = must_be_present
165  else
166  use_must_be_present = .true.
167  end if
168  status = nf90_inq_varid(ncid, name, varid)
169  if ((.not. use_must_be_present) .and. (status == nf90_enotvar)) then
170  ! variable was not present, but that's ok
171  var = 0d0
172  return
173  end if
174  call pmc_nc_check_msg(status, "inquiring variable " // trim(name))
175  call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), &
176  "getting variable " // trim(name))
177 
178  end subroutine pmc_nc_read_real
179 
180 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
181 
182  !> Read a single integer from a NetCDF file.
183  subroutine pmc_nc_read_integer(ncid, var, name, must_be_present)
184 
185  !> NetCDF file ID, in data mode.
186  integer, intent(in) :: ncid
187  !> Data to write.
188  integer, intent(out) :: var
189  !> Variable name in NetCDF file.
190  character(len=*), intent(in) :: name
191  !> Whether the variable must be present in the NetCDF file
192  !> (default .true.).
193  logical, optional, intent(in) :: must_be_present
194 
195  integer :: varid, status
196  logical :: use_must_be_present
197 
198  if (present(must_be_present)) then
199  use_must_be_present = must_be_present
200  else
201  use_must_be_present = .true.
202  end if
203  status = nf90_inq_varid(ncid, name, varid)
204  if ((.not. use_must_be_present) .and. (status == nf90_enotvar)) then
205  ! variable was not present, but that's ok
206  var = 0
207  return
208  end if
209  call pmc_nc_check_msg(status, "inquiring variable " // trim(name))
210  call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), &
211  "getting variable " // trim(name))
212 
213  end subroutine pmc_nc_read_integer
214 
215 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
216 
217  !> Read a simple real array from a NetCDF file.
218  subroutine pmc_nc_read_real_1d(ncid, var, name, must_be_present)
219 
220  !> NetCDF file ID, in data mode.
221  integer, intent(in) :: ncid
222  !> Data to read, must be correctly sized.
223  real(kind=dp), intent(out) :: var(:)
224  !> Variable name in NetCDF file.
225  character(len=*), intent(in) :: name
226  !> Whether the variable must be present in the NetCDF file
227  !> (default .true.).
228  logical, optional, intent(in) :: must_be_present
229 
230  integer :: varid, status
231  logical :: use_must_be_present
232 
233  if (present(must_be_present)) then
234  use_must_be_present = must_be_present
235  else
236  use_must_be_present = .true.
237  end if
238  status = nf90_inq_varid(ncid, name, varid)
239  if ((.not. use_must_be_present) .and. (status == nf90_enotvar)) then
240  ! variable was not present, but that's ok
241  var = 0d0
242  return
243  end if
244  call pmc_nc_check_msg(status, "inquiring variable " // trim(name))
245  call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), &
246  "getting variable " // trim(name))
247 
248  end subroutine pmc_nc_read_real_1d
249 
250 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
251 
252  !> Read a simple integer array from a NetCDF file.
253  subroutine pmc_nc_read_integer_1d(ncid, var, name, must_be_present)
254 
255  !> NetCDF file ID, in data mode.
256  integer, intent(in) :: ncid
257  !> Data to read, must be correctly sized.
258  integer, intent(out) :: var(:)
259  !> Variable name in NetCDF file.
260  character(len=*), intent(in) :: name
261  !> Whether the variable must be present in the NetCDF file
262  !> (default .true.).
263  logical, optional, intent(in) :: must_be_present
264 
265  integer :: varid, status
266  logical :: use_must_be_present
267 
268  if (present(must_be_present)) then
269  use_must_be_present = must_be_present
270  else
271  use_must_be_present = .true.
272  end if
273  status = nf90_inq_varid(ncid, name, varid)
274  if ((.not. use_must_be_present) .and. (status == nf90_enotvar)) then
275  ! variable was not present, but that's ok
276  var = 0
277  return
278  end if
279  call pmc_nc_check_msg(status, "inquiring variable " // trim(name))
280  call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), &
281  "getting variable " // trim(name))
282 
283  end subroutine pmc_nc_read_integer_1d
284 
285 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
286 
287  !> Read a simple real 2D array from a NetCDF file.
288  subroutine pmc_nc_read_real_2d(ncid, var, name, must_be_present)
289 
290  !> NetCDF file ID, in data mode.
291  integer, intent(in) :: ncid
292  !> Data to read, must be correctly sized.
293  real(kind=dp), intent(out) :: var(:,:)
294  !> Variable name in NetCDF file.
295  character(len=*), intent(in) :: name
296  !> Whether the variable must be present in the NetCDF file
297  !> (default .true.).
298  logical, optional, intent(in) :: must_be_present
299 
300  integer :: varid, status
301  logical :: use_must_be_present
302 
303  if (present(must_be_present)) then
304  use_must_be_present = must_be_present
305  else
306  use_must_be_present = .true.
307  end if
308  status = nf90_inq_varid(ncid, name, varid)
309  if ((.not. use_must_be_present) .and. (status == nf90_enotvar)) then
310  ! variable was not present, but that's ok
311  var = 0d0
312  return
313  end if
314  call pmc_nc_check_msg(status, "inquiring variable " // trim(name))
315  call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), &
316  "getting variable " // trim(name))
317 
318  end subroutine pmc_nc_read_real_2d
319 
320 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
321 
322  !> Read a simple integer 2D array from a NetCDF file.
323  subroutine pmc_nc_read_integer_2d(ncid, var, name, must_be_present)
324 
325  !> NetCDF file ID, in data mode.
326  integer, intent(in) :: ncid
327  !> Data to read, must be correctly sized.
328  integer, intent(out) :: var(:,:)
329  !> Variable name in NetCDF file.
330  character(len=*), intent(in) :: name
331  !> Whether the variable must be present in the NetCDF file
332  !> (default .true.).
333  logical, optional, intent(in) :: must_be_present
334 
335  integer :: varid, status
336  logical :: use_must_be_present
337 
338  if (present(must_be_present)) then
339  use_must_be_present = must_be_present
340  else
341  use_must_be_present = .true.
342  end if
343  status = nf90_inq_varid(ncid, name, varid)
344  if ((.not. use_must_be_present) .and. (status == nf90_enotvar)) then
345  ! variable was not present, but that's ok
346  var = 0
347  return
348  end if
349  call pmc_nc_check_msg(status, "inquiring variable " // trim(name))
350  call pmc_nc_check_msg(nf90_get_var(ncid, varid, var), &
351  "getting variable " // trim(name))
352 
353  end subroutine pmc_nc_read_integer_2d
354 
355 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
356 
357  !> Write attributes for a variable to a NetCDF file.
358  subroutine pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, &
359  description)
360 
361  !> NetCDF file ID, in define mode.
362  integer, intent(in) :: ncid
363  !> Variable ID to write attributes for.
364  integer, intent(in) :: varid
365  !> Unit of variable.
366  character(len=*), optional, intent(in) :: unit
367  !> Long name of variable.
368  character(len=*), optional, intent(in) :: long_name
369  !> Standard name of variable.
370  character(len=*), optional, intent(in) :: standard_name
371  !> Description of variable.
372  character(len=*), optional, intent(in) :: description
373 
374  if (present(unit)) then
375  call pmc_nc_check(nf90_put_att(ncid, varid, "unit", unit))
376  end if
377  if (present(long_name)) then
378  call pmc_nc_check(nf90_put_att(ncid, varid, "long_name", long_name))
379  end if
380  if (present(standard_name)) then
381  call pmc_nc_check(nf90_put_att(ncid, varid, "standard_name", &
382  standard_name))
383  end if
384  if (present(description)) then
385  call pmc_nc_check(nf90_put_att(ncid, varid, "description", &
386  description))
387  end if
388 
389  end subroutine pmc_nc_write_atts
390 
391 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
392 
393  !> Write a single real to a NetCDF file.
394  subroutine pmc_nc_write_real(ncid, var, name, unit, long_name, &
395  standard_name, description)
396 
397  !> NetCDF file ID, in data mode.
398  integer, intent(in) :: ncid
399  !> Data to write.
400  real(kind=dp), intent(in) :: var
401  !> Variable name in NetCDF file.
402  character(len=*), intent(in) :: name
403  !> Unit of variable.
404  character(len=*), optional, intent(in) :: unit
405  !> Long name of variable.
406  character(len=*), optional, intent(in) :: long_name
407  !> Standard name of variable.
408  character(len=*), optional, intent(in) :: standard_name
409  !> Description of variable.
410  character(len=*), optional, intent(in) :: description
411 
412  integer :: varid, dimids(0)
413 
414  call pmc_nc_check(nf90_redef(ncid))
415  call pmc_nc_check(nf90_def_var(ncid, name, nf90_double, dimids, varid))
416  call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, &
417  description)
418  call pmc_nc_check(nf90_enddef(ncid))
419 
420  call pmc_nc_check(nf90_put_var(ncid, varid, var))
421 
422  end subroutine pmc_nc_write_real
423 
424 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
425 
426  !> Write a single integer to a NetCDF file.
427  subroutine pmc_nc_write_integer(ncid, var, name, unit, long_name, &
428  standard_name, description)
429 
430  !> NetCDF file ID, in data mode.
431  integer, intent(in) :: ncid
432  !> Data to write.
433  integer, intent(in) :: var
434  !> Variable name in NetCDF file.
435  character(len=*), intent(in) :: name
436  !> Unit of variable.
437  character(len=*), optional, intent(in) :: unit
438  !> Long name of variable.
439  character(len=*), optional, intent(in) :: long_name
440  !> Standard name of variable.
441  character(len=*), optional, intent(in) :: standard_name
442  !> Description of variable.
443  character(len=*), optional, intent(in) :: description
444 
445  integer :: varid, dimids(0)
446 
447  call pmc_nc_check(nf90_redef(ncid))
448  call pmc_nc_check(nf90_def_var(ncid, name, nf90_int, dimids, varid))
449  call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, &
450  description)
451  call pmc_nc_check(nf90_enddef(ncid))
452 
453  call pmc_nc_check(nf90_put_var(ncid, varid, var))
454 
455  end subroutine pmc_nc_write_integer
456 
457 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
458 
459  !> Create a dimension if necessary, or check its size if it already
460  !> exists. In any case return the \c dimid.
461  subroutine pmc_nc_ensure_dim(ncid, dim_name, dimid, dim_size, array_dim)
462 
463  !> NetCDF file ID, in data mode.
464  integer, intent(in) :: ncid
465  !> NetCDF dimension name for the variable.
466  character(len=*), intent(in) :: dim_name
467  !> NetCDF dimension ID.
468  integer, intent(out) :: dimid
469  !> Size of dimension.
470  integer, intent(in) :: dim_size
471  !> Dimension within data array that this NetCDF dim corresponds to.
472  integer, intent(in) :: array_dim
473 
474  integer :: status, check_dim_size
475  character(len=1000) :: check_name
476 
477  status = nf90_inq_dimid(ncid, dim_name, dimid)
478  if (status == nf90_noerr) then
479  call pmc_nc_check(nf90_inquire_dimension(ncid, dimid, check_name, &
480  check_dim_size))
481  call assert_msg(657263912, check_dim_size == dim_size, &
482  "dim " // trim(integer_to_string(array_dim)) // " size " &
483  // trim(integer_to_string(dim_size)) &
484  // " of data array does not match size " &
485  // trim(integer_to_string(dim_size)) // " of '" &
486  // trim(dim_name) // "' dim")
487  else
488  ! could not determine dimid
489  if (status /= nf90_ebaddim) then
490  ! the problem was not a missing dimension
491  call pmc_nc_check(status)
492  end if
493  ! the problem was a missing dimension, so make it
494  call pmc_nc_check(nf90_redef(ncid))
495  call pmc_nc_check(nf90_def_dim(ncid, dim_name, dim_size, dimid))
496  call pmc_nc_check(nf90_enddef(ncid))
497  end if
498 
499  end subroutine pmc_nc_ensure_dim
500 
501 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
502 
503  !> Write a simple real array to a NetCDF file.
504  subroutine pmc_nc_write_real_1d(ncid, var, name, dimids, dim_name, unit, &
505  long_name, standard_name, description)
506 
507  !> NetCDF file ID, in data mode.
508  integer, intent(in) :: ncid
509  !> Data to write.
510  real(kind=dp), intent(in) :: var(:)
511  !> Variable name in NetCDF file.
512  character(len=*), intent(in) :: name
513  !> NetCDF dimension IDs of the variable (either this or dim_name
514  !> must be present).
515  integer, optional, intent(in) :: dimids(1)
516  !> NetCDF dimension name for the variable (either this or dimids
517  !> must be present).
518  character(len=*), optional, intent(in) :: dim_name
519  !> Unit of variable.
520  character(len=*), optional, intent(in) :: unit
521  !> Long name of variable.
522  character(len=*), optional, intent(in) :: long_name
523  !> Standard name of variable.
524  character(len=*), optional, intent(in) :: standard_name
525  !> Description of variable.
526  character(len=*), optional, intent(in) :: description
527 
528  integer :: varid, start(1), count(1), use_dimids(1)
529 
530  if (present(dimids)) then
531  use_dimids = dimids
532  elseif (present(dim_name)) then
533  call pmc_nc_ensure_dim(ncid, dim_name, use_dimids(1), size(var), 1)
534  else
535  call die_msg(891890123, "either dimids or dim_name must be present")
536  end if
537  call pmc_nc_check(nf90_redef(ncid))
538  call pmc_nc_check(nf90_def_var(ncid, name, nf90_double, use_dimids, varid))
539  call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, &
540  description)
541  call pmc_nc_check(nf90_enddef(ncid))
542 
543  start = (/ 1 /)
544  count = (/ size(var, 1) /)
545  call pmc_nc_check(nf90_put_var(ncid, varid, var, &
546  start = start, count = count))
547 
548  end subroutine pmc_nc_write_real_1d
549 
550 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
551 
552  !> Write a simple integer array to a NetCDF file.
553  subroutine pmc_nc_write_integer_1d(ncid, var, name, dimids, dim_name, unit, &
554  long_name, standard_name, description)
555 
556  !> NetCDF file ID, in data mode.
557  integer, intent(in) :: ncid
558  !> Data to write.
559  integer, intent(in) :: var(:)
560  !> Variable name in NetCDF file.
561  character(len=*), intent(in) :: name
562  !> NetCDF dimension IDs of the variable (either this or dim_name
563  !> must be present).
564  integer, optional, intent(in) :: dimids(1)
565  !> NetCDF dimension name for the variable (either this or dimids
566  !> must be present).
567  character(len=*), optional, intent(in) :: dim_name
568  !> Unit of variable.
569  character(len=*), optional, intent(in) :: unit
570  !> Long name of variable.
571  character(len=*), optional, intent(in) :: long_name
572  !> Standard name of variable.
573  character(len=*), optional, intent(in) :: standard_name
574  !> Description of variable.
575  character(len=*), optional, intent(in) :: description
576 
577  integer :: varid, start(1), count(1), use_dimids(1)
578 
579  if (present(dimids)) then
580  use_dimids = dimids
581  elseif (present(dim_name)) then
582  call pmc_nc_ensure_dim(ncid, dim_name, use_dimids(1), size(var), 1)
583  else
584  call die_msg(464170526, "either dimids or dim_name must be present")
585  end if
586  call pmc_nc_check(nf90_redef(ncid))
587  call pmc_nc_check(nf90_def_var(ncid, name, nf90_int, use_dimids, varid))
588  call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, &
589  description)
590  call pmc_nc_check(nf90_enddef(ncid))
591 
592  start = (/ 1 /)
593  count = (/ size(var, 1) /)
594  call pmc_nc_check(nf90_put_var(ncid, varid, var, &
595  start = start, count = count))
596 
597  end subroutine pmc_nc_write_integer_1d
598 
599 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
600 
601  !> Write a simple real 2D array to a NetCDF file.
602  subroutine pmc_nc_write_real_2d(ncid, var, name, dimids, dim_name_1, &
603  dim_name_2, unit, long_name, standard_name, description)
604 
605  !> NetCDF file ID, in data mode.
606  integer, intent(in) :: ncid
607  !> Data to write.
608  real(kind=dp), intent(in) :: var(:,:)
609  !> Variable name in NetCDF file.
610  character(len=*), intent(in) :: name
611  !> NetCDF dimension IDs of the variable (either \c dimids or both
612  !> \c dim_name_1 and \c dim_name_2 must be present).
613  integer, optional, intent(in) :: dimids(2)
614  !> First NetCDF dimension name for the variable (either \c dimids
615  !> or both \c dim_name_1 and \c dim_name 2 must be present).
616  character(len=*), optional, intent(in) :: dim_name_1
617  !> Second NetCDF dimension name for the variable (either \c dimids
618  !> or both \c dim_name_1 and \c dim_name 2 must be present).
619  character(len=*), optional, intent(in) :: dim_name_2
620  !> Unit of variable.
621  character(len=*), optional, intent(in) :: unit
622  !> Long name of variable.
623  character(len=*), optional, intent(in) :: long_name
624  !> Standard name of variable.
625  character(len=*), optional, intent(in) :: standard_name
626  !> Description of variable.
627  character(len=*), optional, intent(in) :: description
628 
629  integer :: varid, start(2), count(2), use_dimids(2)
630 
631  if (present(dimids)) then
632  use_dimids = dimids
633  elseif (present(dim_name_1) .and. present(dim_name_2)) then
634  call pmc_nc_ensure_dim(ncid, dim_name_1, use_dimids(1), size(var, 1), 1)
635  call pmc_nc_ensure_dim(ncid, dim_name_2, use_dimids(2), size(var, 2), 2)
636  else
637  call die_msg(959111259, &
638  "either dimids or both dim_name_1 and dim_name_2 must be present")
639  end if
640  call pmc_nc_check(nf90_redef(ncid))
641  call pmc_nc_check(nf90_def_var(ncid, name, nf90_double, use_dimids, varid))
642  call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, &
643  description)
644  call pmc_nc_check(nf90_enddef(ncid))
645 
646  start = (/ 1, 1 /)
647  count = (/ size(var, 1), size(var, 2) /)
648  call pmc_nc_check(nf90_put_var(ncid, varid, var, &
649  start = start, count = count))
650 
651  end subroutine pmc_nc_write_real_2d
652 
653 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
654 
655  !> Write a simple integer 2D array to a NetCDF file.
656  subroutine pmc_nc_write_integer_2d(ncid, var, name, dimids, dim_name_1, &
657  dim_name_2, unit, long_name, standard_name, description)
658 
659  !> NetCDF file ID, in data mode.
660  integer, intent(in) :: ncid
661  !> Data to write.
662  integer, intent(in) :: var(:,:)
663  !> Variable name in NetCDF file.
664  character(len=*), intent(in) :: name
665  !> NetCDF dimension IDs of the variable (either \c dimids or both
666  !> \c dim_name_1 and \c dim_name_2 must be present).
667  integer, optional, intent(in) :: dimids(2)
668  !> First NetCDF dimension name for the variable (either \c dimids
669  !> or both \c dim_name_1 and \c dim_name 2 must be present).
670  character(len=*), optional, intent(in) :: dim_name_1
671  !> Second NetCDF dimension name for the variable (either \c dimids
672  !> or both \c dim_name_1 and \c dim_name 2 must be present).
673  character(len=*), optional, intent(in) :: dim_name_2
674  !> Unit of variable.
675  character(len=*), optional, intent(in) :: unit
676  !> Long name of variable.
677  character(len=*), optional, intent(in) :: long_name
678  !> Standard name of variable.
679  character(len=*), optional, intent(in) :: standard_name
680  !> Description of variable.
681  character(len=*), optional, intent(in) :: description
682 
683  integer :: varid, start(2), count(2), use_dimids(2)
684 
685  if (present(dimids)) then
686  use_dimids = dimids
687  elseif (present(dim_name_1) .and. present(dim_name_2)) then
688  call pmc_nc_ensure_dim(ncid, dim_name_1, use_dimids(1), size(var, 1), 1)
689  call pmc_nc_ensure_dim(ncid, dim_name_2, use_dimids(2), size(var, 2), 2)
690  else
691  call die_msg(669381383, &
692  "either dimids or both dim_name_1 and dim_name_2 must be present")
693  end if
694  call pmc_nc_check(nf90_redef(ncid))
695  call pmc_nc_check(nf90_def_var(ncid, name, nf90_int, use_dimids, varid))
696  call pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, &
697  description)
698  call pmc_nc_check(nf90_enddef(ncid))
699 
700  start = (/ 1, 1 /)
701  count = (/ size(var, 1), size(var, 2) /)
702  call pmc_nc_check(nf90_put_var(ncid, varid, var, &
703  start = start, count = count))
704 
705  end subroutine pmc_nc_write_integer_2d
706 
707 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
708 
709 end module pmc_netcdf
subroutine pmc_nc_write_real_1d(ncid, var, name, dimids, dim_name, unit, long_name, standard_name, description)
Write a simple real array to a NetCDF file.
Definition: netcdf.F90:504
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:133
subroutine iso8601_date_and_time(date_time)
Current date and time in ISO 8601 format.
Definition: util.F90:1206
subroutine pmc_nc_write_atts(ncid, varid, unit, long_name, standard_name, description)
Write attributes for a variable to a NetCDF file.
Definition: netcdf.F90:358
subroutine pmc_nc_check(status)
Check the status of a NetCDF function call.
Definition: netcdf.F90:22
subroutine pmc_nc_read_integer(ncid, var, name, must_be_present)
Read a single integer from a NetCDF file.
Definition: netcdf.F90:183
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:76
subroutine pmc_nc_read_integer_1d(ncid, var, name, must_be_present)
Read a simple integer array from a NetCDF file.
Definition: netcdf.F90:253
Random number generators.
Definition: rand.F90:9
integer function pmc_mpi_size()
Returns the total number of processes.
Definition: mpi.F90:133
subroutine pmc_nc_write_integer_1d(ncid, var, name, dimids, dim_name, unit, long_name, standard_name, description)
Write a simple integer array to a NetCDF file.
Definition: netcdf.F90:553
Common utility subroutines.
Definition: util.F90:9
subroutine pmc_nc_read_real_1d(ncid, var, name, must_be_present)
Read a simple real array from a NetCDF file.
Definition: netcdf.F90:218
subroutine pmc_nc_read_real_2d(ncid, var, name, must_be_present)
Read a simple real 2D array from a NetCDF file.
Definition: netcdf.F90:288
integer function pmc_mpi_rank()
Returns the rank of the current process.
Definition: mpi.F90:116
character(len=pmc_util_convert_string_len) function integer_to_string(val)
Convert an integer to a string format.
Definition: util.F90:743
subroutine pmc_nc_write_info(ncid, uuid, source, write_rank, write_n_proc)
Write basic information to a NetCDF file.
Definition: netcdf.F90:97
subroutine pmc_nc_write_real_2d(ncid, var, name, dimids, dim_name_1, dim_name_2, unit, long_name, standard_name, description)
Write a simple real 2D array to a NetCDF file.
Definition: netcdf.F90:602
subroutine pmc_nc_write_real(ncid, var, name, unit, long_name, standard_name, description)
Write a single real to a NetCDF file.
Definition: netcdf.F90:394
subroutine pmc_nc_close(ncid)
Close a NetCDF file.
Definition: netcdf.F90:85
subroutine pmc_nc_ensure_dim(ncid, dim_name, dimid, dim_size, array_dim)
Create a dimension if necessary, or check its size if it already exists. In any case return the dimid...
Definition: netcdf.F90:461
Wrapper functions for NetCDF. These all take a NetCDF ncid in data mode and return with it again in d...
Definition: netcdf.F90:11
subroutine pmc_nc_write_integer_2d(ncid, var, name, dimids, dim_name_1, dim_name_2, unit, long_name, standard_name, description)
Write a simple integer 2D array to a NetCDF file.
Definition: netcdf.F90:656
subroutine pmc_nc_open_read(filename, ncid)
Open a NetCDF file for reading.
Definition: netcdf.F90:54
subroutine pmc_nc_open_write(filename, ncid)
Open a NetCDF file for writing.
Definition: netcdf.F90:69
subroutine pmc_nc_write_integer(ncid, var, name, unit, long_name, standard_name, description)
Write a single integer to a NetCDF file.
Definition: netcdf.F90:427
subroutine pmc_nc_read_real(ncid, var, name, must_be_present)
Read a single real from a NetCDF file.
Definition: netcdf.F90:148
subroutine pmc_nc_read_integer_2d(ncid, var, name, must_be_present)
Read a simple integer 2D array from a NetCDF file.
Definition: netcdf.F90:323
subroutine pmc_nc_check_msg(status, error_msg)
Check the status of a NetCDF function call and prints the given error message on failure.
Definition: netcdf.F90:37