Soil Water Balance (SWB2)
Loading...
Searching...
No Matches
netcdf4_support.F90
Go to the documentation of this file.
1!> @file
2!! Contain a single module, @ref netcdf4_support, which
3!! provides support for use of netCDF files as input or output.
4!!
5!! Supports use of netCDF files as input for time-varying,
6!! gridded meteorlogic data, or output for any SWB-generated variable.
7!!
8!! from the C API:
9!! The @c nc_get_vars_l type family of functions read a subsampled (strided)
10!! array section of values from a netCDF variable of an open netCDF dataset.
11!! The subsampled array section is specified by giving a corner,
12!! a vector of edge lengths, and a stride vector. The values are read
13!! with the last dimension of the netCDF variable varying fastest.
14!! ^^^^ ^^^^^^^ ^^^^^^^
15!!
16!! from the Fortran 90 API:
17!! The values to be read are associated with the netCDF variable by
18!! assuming that the first dimension of the netCDF variable
19!! ^^^^^
20!! varies fastest in the Fortran 90 interface.
21!! ^^^^^^ ^^^^^^^
22
23!> Provide support for use of netCDF files as input for time-varying,
24!! gridded meteorlogic data, or output for any SWB-generated variable.
26
27 use iso_c_binding
29 use exceptions
30 use logfiles
32 use fstring
35 use datetime
36
37 use version_control, only : swb_version, git_commit_hash_string, &
38 git_branch_string, compile_date, compile_time, &
39 compilation_timestamp
40
41 use grid
42! use typesizes
44
45 implicit none
46
47 private
48
50
51 integer(c_int), public :: nc_readonly = 0
52 integer(c_int), public :: nc_readwrite = 1
53
54 ! from netcdf.h:
55
56 ! #define NC_NAT 0
57 ! #define NC_BYTE 1
58 ! #define NC_CHAR 2
59 ! #define NC_SHORT 3
60 ! #define NC_INT 4
61 ! #define NC_LONG NC_INT
62 ! #define NC_FLOAT 5
63 ! #define NC_DOUBLE 6
64 ! #define NC_UBYTE 7
65 ! #define NC_USHORT 8
66 ! #define NC_UINT 9
67 ! #define NC_INT64 10
68 ! #define NC_UINT64 11
69 ! #define NC_STRING 12
70
71 integer(c_int), parameter :: nc_nat = 0
72 integer(c_int), parameter :: nc_byte = 1
73 integer(c_int), parameter :: nc_char = 2
74 integer(c_int), parameter :: nc_short = 3
75 integer(c_int), parameter :: nc_int = 4
76 integer(c_int), parameter :: nc_long = nc_int
77 integer(c_int), parameter :: nc_float = 5
78 integer(c_int), parameter :: nc_double = 6
79 integer(c_int), parameter :: nc_ubyte = 7
80 integer(c_int), parameter :: nc_ushort = 8
81 integer(c_int), parameter :: nc_uint = 9
82 integer(c_int), parameter :: nc_int64 = 10
83 integer(c_int), parameter :: nc_uint64 = 11
84 integer(c_int), parameter :: nc_string = 12
85
86 integer(c_int), parameter :: nc_fill_char = 0
87 integer(c_int), parameter :: nc_fill_byte = -127
88 integer(c_int), parameter :: nc_fill_short = -32767
89 integer(c_int), parameter :: nc_fill_int = -2147483647
90 integer(c_int), parameter :: nc_na_int = -9999
91
92 real(c_float), parameter :: nc_fill_float = -9999.0_c_float
93 real(c_double), parameter :: nc_fill_double = -9.9e-20_c_double
94! real(c_float), parameter :: NC_FILL_FLOAT = -( HUGE( 0_c_float ) - 1.0_c_float )
95! real(c_double), parameter :: NC_FILL_DOUBLE = -( HUGE( 0_c_double ) - 1.0_c_double )
96
97 ! mode flags for opening and creating datasets
98 integer(c_int), parameter :: nc_nowrite = 0
99 integer(c_int), parameter :: nc_write = 1
100 integer(c_int), parameter :: nc_clobber = 0
101 integer(c_int), parameter :: nc_noclobber = 4
102 integer(c_int), parameter :: nc_fill = 0
103 integer(c_int), parameter :: nc_nofill = 256
104 integer(c_int), parameter :: nc_lock = 1024
105 integer(c_int), parameter :: nc_share = 2048
106 integer(c_int), parameter :: nc_strict_nc3 = 8
107 integer(c_int), parameter :: nc_64bit_offset = 512
108 integer(c_int), parameter :: nc_sizehint_default = 0
109 integer(c_int), parameter :: nc_align_chunk = -1
110 integer(c_int), parameter :: nc_format_classic = 1
111 integer(c_int), parameter :: nc_format_64bit = 2
112 integer(c_int), parameter :: nc_format_netcdf4 = 3
113 integer(c_int), parameter :: nc_format_netcdf4_classic = 4
114
115 ! implementation limits (warning! should be the same as c interface)
116 integer(c_int), parameter :: nc_max_dims = 1024
117 integer(c_int), parameter :: nc_max_attrs = 8192
118 integer(c_int), parameter :: nc_max_vars = 8192
119 integer(c_int), parameter :: nc_max_name = 256
120
121 integer (c_int), parameter :: nc_shuffle_yes = 1
122 integer (c_int), parameter :: nc_shuffle_no = 0
123 integer (c_int), parameter :: nc_deflate_yes = 1
124 integer (c_int), parameter :: nc_deflate_no = 0
125
126 integer(c_int), parameter :: nc_netcdf4 = 4096
127 integer(c_int), parameter :: nc_classic_model = 256
128
129
130 integer(c_int), parameter :: nc_unlimited = 0
131 integer(c_int), parameter :: nc_global = -1
132
133 !> @TODO: implement a more flexible way of tracking
134 !! variable IDs; presently the code can break if
135 !! lat and lon are omitted, but time_bnds is included;
136 !! this is because if the lat and lon variables are
137 !! not defined, NC_TIME_BNDS may be 4 or 5 or some other value.
138 integer (c_int), public, parameter :: nc_time = 0
139 integer (c_int), public, parameter :: nc_y = 1
140 integer (c_int), public, parameter :: nc_x = 2
141 integer (c_int), public, parameter :: nc_z = 3
142 integer (c_int), public, parameter :: nc_aux = 3
143 integer (c_int), public, parameter :: nc_crs = 4
144 integer (c_int), public, parameter :: nc_lat = 5
145 integer (c_int), public, parameter :: nc_lon = 6
146 integer (c_int), public :: nc_time_bnds = 7
147
148 integer (c_int), parameter :: nc_first = 0
149 integer (c_int), parameter :: nc_last = 1
150 integer (c_int), parameter :: nc_by = 2
151
152 integer (c_int), public, parameter :: nc_left = 0
153 integer (c_int), public, parameter :: nc_right = 1
154 integer (c_int), public, parameter :: nc_top = 0
155 integer (c_int), public, parameter :: nc_bottom = 1
156
157 integer (c_int), parameter :: column = 1
158 integer (c_int), parameter :: row = 2
159
160 integer (c_int), parameter :: leap_year = 0
161 integer (c_int), parameter :: noleap_year = 1
162 integer (c_int), parameter :: year_is_360_days = 2
163
164 character (len=25), dimension(4), parameter :: netcdf_format_string = &
165 ["NC_FORMAT_CLASSIC ", &
166 "NC_FORMAT_64BIT ", &
167 "NC_FORMAT_NETCDF4 ", &
168 "NC_FORMAT_NETCDF4_CLASSIC" ]
169
170 character (len=6), dimension(0:6), parameter :: netcdf_data_type = &
171 ["nat ", &
172 "byte ", &
173 "char ", &
174 "short ", &
175 "int ", &
176 "float ", &
177 "double" ]
178
180 character (len=64) :: sdimensionname
181 integer (c_int) :: inc_dimid = nc_na_int
182 integer (c_size_t) :: inc_dimsize
183 logical (c_bool) :: lunlimited = false
184 end type t_netcdf_dimension
185
187 character (len=64) :: sattributename
188 character (len=256), dimension(:), allocatable :: sattvalue
189 integer (c_short), dimension(:), allocatable :: i2attvalue
190 integer (c_int), dimension(:), allocatable :: iattvalue
191 real (c_float), dimension(:), allocatable :: rattvalue
192 real (c_double), dimension(:), allocatable :: dpattvalue
193 integer (c_int) :: inc_atttype
194 integer (c_size_t) :: inc_attsize
195 end type t_netcdf_attribute
196
198 character (len=64) :: svariablename
199 integer (c_int) :: inc_varid = nc_na_int
200 integer (c_int) :: inc_vartype
201 integer (c_int) :: inumberofdimensions
202 integer (c_int), dimension(0:3) :: inc_dimid = nc_na_int
203 integer (c_int) :: inumberofattributes
204 type (t_netcdf_attribute), dimension(:), pointer :: pnc_att => null()
205 end type t_netcdf_variable
206
208 integer (c_int) :: incid
209 character (len=256) :: sfilename
210 integer (c_int) :: ifileformat
211 integer (c_int) :: inumberofdimensions
212 integer (c_int) :: inumberofvariables
213 integer (c_int) :: inumberofattributes
214 integer (c_int) :: inc3_unlimiteddimensionnumber
215 integer (c_int) :: ioriginjd = nc_na_int
216 integer (c_int) :: ifirstdayjd = nc_na_int
217 integer (c_int) :: ilastdayjd = nc_na_int
218 integer (c_int) :: ioriginmonth
219 integer (c_int) :: ioriginday
220 integer (c_int) :: ioriginyear
221 integer (c_int) :: ioriginhh
222 integer (c_int) :: ioriginmm
223 integer (c_int) :: ioriginss
224 integer (c_int) :: lleapyeartreatment = leap_year
225 integer (c_size_t), dimension(0:3) :: istart
226 integer (c_size_t), dimension(0:3) :: icount
227 integer (c_size_t), dimension(0:3) :: istride = 1
228 integer (c_size_t), dimension(0:1) :: icolbounds
229 integer (c_size_t), dimension(0:1) :: irowbounds
230 integer (c_int) :: inx
231 integer (c_int) :: iny
232 character (len=3) :: svariableorder = "tyx"
233 real (c_double), dimension(0:1) :: rx
234 real (c_double), dimension(0:1) :: ry
235 real (c_double) :: rcoordinatetolerance = 0.0_c_double ! set this to be > 0.0 to allow some 'slop' when comparing coordinates
236 logical (c_bool) :: lx_increaseswithindex = true
237 logical (c_bool) :: ly_increaseswithindex = false
238 logical (c_bool) :: lallowautomaticdataflipping = true
239
240 real (c_double), dimension(0:1) :: dpfirstandlasttimevalues
241 character (len=64), dimension(0:3) :: svarname = ["time","y ","x ","z "]
242 integer (c_int), dimension(0:3) :: ivarid = nc_na_int
243 integer (c_int), dimension(0:3) :: ivarindex = nc_na_int
244 integer (c_int), dimension(0:3) :: ivartype = nc_na_int
245 character (len=64), dimension(0:3) :: svarunits = "NA"
246 integer (c_int), dimension(0:3, 0:3) :: ivar_dimid = nc_na_int
247 real (c_double), dimension(0:3) :: rscalefactor = 1.0_c_double
248 real (c_double), dimension(0:3) :: raddoffset = 0.0_c_double
249 integer (c_int), dimension(0:2) :: irowiter
250 integer (c_int), dimension(0:2) :: icoliter
251 logical (c_bool) :: lfliphorizontal = false
252 logical (c_bool) :: lflipvertical = false
253
254 real (c_double), allocatable, dimension(:) :: rx_coords
255 real (c_double), allocatable, dimension(:) :: ry_coords
256 real (c_double) :: rx_coord_addoffset = 0.0_c_double
257 real (c_double) :: ry_coord_addoffset = 0.0_c_double
258 real (c_double), allocatable, dimension(:) :: rdatetimevalues
259 real (c_double) :: rgridcellsizex
260 real (c_double) :: rgridcellsizey
261
262 type (t_netcdf_dimension), dimension(:), pointer :: pnc_dim => null()
263 type (t_netcdf_variable), dimension(:), pointer :: pnc_var => null()
264 type (t_netcdf_attribute), dimension(:), pointer :: pnc_att => null()
265 end type t_netcdf4_file
266
267!
268! For a netCDF file to be read successfully, the reader must have a way to
269! tie coordinate values to index values. By default the code assumes that coordinates
270! decrease while the indices increase (i.e. read the file in as rows from top to bottom).
271!
272! If this is not the case, the data/coordinates must be 'flipped' relative to one another.
273!
274! DEFAULT ASSUMPTION REGARDING VERTICAL COORDINATES
275!
276! /\
277! coordinates | |
278! increase | |
279! in upward | |
280! direction | |
281! | |
282! | | column index increases in downward direction
283! | |
284! | |
285! \/
286!
287
289 public :: t_netcdf4_file
290
299 public :: netcdf_dump_cdl
300 public :: netcdf_open_file
301 public :: netcdf_close_file
312
313contains
314
315!----------------------------------------------------------------------
316
317function netcdf_date_within_range( NCFILE, iJulianDay) result( lWithinRange )
318
319 type (t_netcdf4_file ) :: ncfile
320 integer (c_int) :: ijulianday
321 logical (c_bool) :: lwithinrange
322
323 if ( ijulianday >= ncfile%iFirstDayJD &
324 .and. ijulianday <= ncfile%iLastDayJD ) then
325
326 lwithinrange = true
327
328 else
329
330 lwithinrange = false
331
332 endif
333
334end function netcdf_date_within_range
335
336!----------------------------------------------------------------------
337
338!> We need two functions to convert from index to timeval, and timeval to JD;
339!> note that timeval refers to the number of days from the origin
340!> of the netCDF file
341
342!> return the day value (number of days since origin
343function nf_julian_day_to_index(NCFILE, rJulianDay) result (iIndex)
344
345 type (t_netcdf4_file) :: ncfile
346 real (c_double) :: rjulianday
347 integer (c_int) :: iindex
348
349 iindex = aint(rjulianday) - ncfile%iFirstDayJD
350
351end function nf_julian_day_to_index
352
353!----------------------------------------------------------------------
354
355function nf_index_to_dayvalue(NCFILE, iIndex) result(rDayValue)
356
357 type (t_netcdf4_file) :: ncfile
358 integer (c_int) :: iindex
359 real (c_double) :: rdayvalue
360
361 call assert(iindex >= lbound(ncfile%rDateTimeValues, 1) &
362 .and. iindex <= ubound(ncfile%rDateTimeValues, 1), &
363 "Dimension out of bounds", __file__, __line__)
364 rdayvalue = ncfile%rDateTimeValues(iindex)
365
366end function nf_index_to_dayvalue
367
368!----------------------------------------------------------------------
369
370function nf_dayvalue_to_julian_day(NCFILE, rDayValue) result(rJulianDay)
371
372 type (t_netcdf4_file) :: ncfile
373 real (c_double) :: rdayvalue
374 real (c_double) :: rjulianday
375
376 rjulianday = real(ncfile%iOriginJD, c_double) &
377 + real(ncfile%iOriginHH, c_double) / 24_c_double &
378 + real(ncfile%iOriginMM, c_double) / 1440_c_double &
379 + real(ncfile%iOriginSS, c_double) / 86400_c_double &
380 + rdayvalue
381
382end function nf_dayvalue_to_julian_day
383
384!----------------------------------------------------------------------
385
386function nf_julian_day_to_index_adj( NCFILE, rJulianDay ) result(iStart)
387
388 type (t_netcdf4_file ) :: ncfile
389 real (c_double) :: rjulianday
390 integer (c_size_t) :: istart
391
392 ! [ LOCALS ]
393 integer (c_int) :: imindiff, idiff
394 integer (c_int) :: icandidateindex, ilastcandidate
395 integer (c_int) :: iinitialcandidateindex
396 integer (c_int) :: itestindex
397 real (c_double) :: rtestjd
398 integer (c_int) :: iindexlower, iindexupper, iindex
399 logical (c_bool) :: lchanged
400
401 istart = -9999
402 imindiff = ibigval
403 !> First guess at what the appropriate index value should be.
404 !> Current JD minus the Origin JD is a good guess.
405 icandidateindex = nf_julian_day_to_index(ncfile, rjulianday)
406
407 call assert(icandidateindex >=0, "Problem finding the index number of the time " &
408 //"variable in netCDF file "//dquote(ncfile%sFilename), __file__, __line__)
409
410 iinitialcandidateindex = icandidateindex
411
412 do
413
414 !> calculate the range of *INDEX* values to search over
415 iindexlower = max( lbound(ncfile%rDateTimeValues, 1), icandidateindex - 1)
416 iindexupper = min( ubound(ncfile%rDateTimeValues, 1), icandidateindex + 1)
417
418 lchanged = false
419
420 do iindex=iindexlower,iindexupper
421
422 rtestjd = nf_dayvalue_to_julian_day(ncfile=ncfile, &
423 rdayvalue=ncfile%rDateTimeValues(iindex))
424
425 itestindex = aint(rtestjd) - ncfile%iFirstDayJD
426 idiff = abs(itestindex - iinitialcandidateindex)
427
428 if (idiff < imindiff ) then
429
430 imindiff = idiff
431 icandidateindex = iindex
432 lchanged = true
433
434 endif
435
436 enddo
437
438 if (.not. lchanged ) exit
439
440 enddo
441
442 if (imindiff == 0) istart = icandidateindex
443
445
446!----------------------------------------------------------------------
447
448function nf_return_varid( NCFILE, iVarIndex) result(iVarID)
449
450 type (t_netcdf4_file ) :: ncfile
451 integer (c_int) :: ivarindex
452 integer (c_int) :: ivarid
453
454 type (t_netcdf_variable), pointer :: pnc_var
455
456 pnc_var => ncfile%pNC_VAR(ivarindex)
457
458 ivarid = pnc_var%iNC_VarID
459
460end function nf_return_varid
461
462!----------------------------------------------------------------------
463
464function nf_return_dimid( NCFILE, iDimIndex) result(iDimID)
465
466 type (t_netcdf4_file ) :: ncfile
467 integer (c_int) :: idimindex
468 integer (c_int) :: idimid
469
470 type (t_netcdf_dimension), pointer :: pnc_dim
471
472 pnc_dim => ncfile%pNC_DIM(idimindex)
473
474 idimid = pnc_dim%iNC_DimID
475
476end function nf_return_dimid
477
478!----------------------------------------------------------------------
479
480function nf_return_varindex( NCFILE, iVarID) result(iVarIndex)
481
482 type (t_netcdf4_file ) :: ncfile
483 integer (c_int) :: ivarid
484 integer (c_int) :: ivarindex
485
486 type (t_netcdf_variable), pointer :: pnc_var
487 integer (c_int) :: iindex
488 logical (c_bool) :: lfound
489
490 lfound = false
491
492 do iindex=0, ncfile%iNumberOfVariables - 1
493
494 pnc_var => ncfile%pNC_VAR(iindex)
495
496 if (pnc_var%iNC_VarID == ivarid) then
497 lfound = true
498 exit
499 endif
500
501 enddo
502
503 call assert(lfound, "INTERNAL PROGRAMMING ERROR - No matching variable " &
504 //"ID found: was looking for Variable ID: "//trim(ascharacter(ivarid)), &
505 __file__, __line__)
506
507 ivarindex = iindex
508
509end function nf_return_varindex
510
511!----------------------------------------------------------------------
512
513function nf_return_attvalue( NCFILE, iVarIndex, sAttName) result(sAttValue)
514
515 type (t_netcdf4_file ) :: ncfile
516 integer (c_int) :: ivarindex
517 character (len=*) :: sattname
518 character (len=256) :: sattvalue
519
520 type (t_netcdf_attribute), dimension(:), pointer :: pnc_att
521 integer (c_int) :: iindex, iindex2
522 logical (c_bool) :: lfound
523
524 if (ivarindex < 0) then
525
526 pnc_att => ncfile%pNC_ATT
527
528 else
529
530 call assert(ivarindex >= lbound(ncfile%pNC_VAR,1) &
531 .and. ivarindex <= ubound(ncfile%pNC_VAR,1), &
532 "Index out of bounds referencing NCFILE%pNC_VAR" &
533 //"~Offending index value: "//trim(ascharacter(ivarindex)), &
534 __file__, __line__)
535
536 pnc_att => ncfile%pNC_VAR(ivarindex)%pNC_ATT
537
538 endif
539
540 lfound = false
541
542 do iindex=lbound(pnc_att,1), ubound(pnc_att,1)
543
544 if ( sattname .strequal. pnc_att(iindex)%sAttributeName ) then
545 lfound = true
546 exit
547 endif
548
549 enddo
550
551 call assert(lfound, "INTERNAL PROGRAMMING ERROR - No matching attribute " &
552 //"name found: was looking for attribute with name: "//dquote(sattname), &
553 __file__, __line__)
554
555 sattvalue = ""
556 do iindex2=0, ubound(pnc_att(iindex)%sAttValue,1)
557 sattvalue = sattvalue//" "//trim(pnc_att(iindex)%sAttValue(iindex))
558 enddo
559
560
561end function nf_return_attvalue
562
563!----------------------------------------------------------------------
564
565function nf_return_dimindex( NCFILE, iDimID) result(iDimIndex)
566
567 type (t_netcdf4_file ) :: ncfile
568 integer (c_int) :: idimid
569 integer (c_int) :: idimindex
570
571 type (t_netcdf_dimension), pointer :: pnc_dim
572 integer (c_int) :: iindex
573 logical (c_bool) :: lfound
574
575 lfound = false
576
577 do iindex=0, ncfile%iNumberOfDimensions - 1
578
579 pnc_dim => ncfile%pNC_DIM(iindex)
580
581 if (pnc_dim%iNC_DimID == idimid) then
582 lfound = true
583 exit
584 endif
585
586 enddo
587
588 call assert(lfound, "INTERNAL PROGRAMMING ERROR - No matching dimension " &
589 //"ID found: was looking for Dimension ID: "//trim(ascharacter(idimid)), &
590 __file__, __line__)
591
592 idimindex = iindex
593
594end function nf_return_dimindex
595
596!----------------------------------------------------------------------
597
598function nf_return_dimsize( NCFILE, iDimID) result(iDimSize)
599
600 type (t_netcdf4_file ) :: ncfile
601 integer (c_int) :: idimid
602 integer (c_size_t) :: idimsize
603
604 type (t_netcdf_dimension), pointer :: pnc_dim
605 integer (c_int) :: iindex
606 logical (c_bool) :: lfound
607
608 lfound = false
609
610 do iindex=0, ncfile%iNumberOfDimensions - 1
611
612 pnc_dim => ncfile%pNC_DIM(iindex)
613
614 if (pnc_dim%iNC_DimID == idimid) then
615 lfound = true
616 exit
617 endif
618
619 enddo
620
621 call assert(lfound, "INTERNAL PROGRAMMING ERROR - No matching dimension " &
622 //"ID found: was looking for Dimension ID: "//trim(ascharacter(idimid)), &
623 __file__, __line__)
624
625 idimsize = pnc_dim%iNC_DimSize
626
627end function nf_return_dimsize
628
629!--------------------------------------------------------------------------------------------------
630
631subroutine nf_guess_z_variable_name(NCFILE)
632
633 type (T_NETCDF4_FILE ) :: NCFILE
634
635 ! [ LOCALS ]
636 integer (c_int) :: iIndex
637 integer (c_int) :: iCount
638 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
639
640 do iindex=lbound(ncfile%pNC_VAR,1),ubound(ncfile%pNC_VAR,1)
641
642 pnc_var => ncfile%pNC_VAR(iindex)
643
644 if ( ( pnc_var%sVariableName .strapprox. 'time') &
645 .or. ( pnc_var%sVariableName .strapprox. 'x') &
646 .or. ( pnc_var%sVariableName .strapprox. 'y') &
647 .or. ( pnc_var%sVariableName .strapprox. 'time_bnds') &
648 .or. ( pnc_var%sVariableName .strapprox. 'lat') &
649 .or. ( pnc_var%sVariableName .strapprox. 'lon') ) cycle
650
651 ncfile%sVarName(nc_z) = pnc_var%sVariableName
652 exit
653
654 enddo
655
656end subroutine nf_guess_z_variable_name
657
658!--------------------------------------------------------------------------------------------------
659
660subroutine netcdf_open_and_prepare_for_merging( NCFILE, sFilename, guess_z_var_name )
661
662 type (t_netcdf4_file ), intent(inout) :: ncfile
663 character (len=*), intent(in) :: sfilename
664 logical (c_bool), intent(in), optional :: guess_z_var_name
665
666 ! [ LOCALS ]
667 type (t_netcdf_variable), pointer :: pnc_var
668 type (t_netcdf_dimension), pointer :: pnc_dim
669 logical (c_bool) :: lfileopen
670 integer (c_int), dimension(2) :: icolrow_ll, icolrow_ur, icolrow_lr, icolrow_ul
671 integer (c_int) :: icolmin, icolmax, irowmin, irowmax
672 integer (c_int) :: iindex
673 logical (c_bool) :: guess_z_var_name_l
674
675 if (present( guess_z_var_name) ) then
676 guess_z_var_name_l = guess_z_var_name
677 else
678 guess_z_var_name_l = false
679 endif
680
681 call nf_open_file(ncfile=ncfile, sfilename=sfilename)
682
683 call nf_populate_dimension_struct( ncfile )
684
685 call nf_populate_variable_struct( ncfile )
686
687 if (guess_z_var_name_l) call nf_guess_z_variable_name(ncfile)
688
689 call nf_get_variable_id_and_type( ncfile, strict_asserts=true )
690
691 ! OK. We only want to attempt to call functions that
692 ! process the time variable if a time variable actually exists!!
693 if ( ncfile%iVarID(nc_time) >= 0 ) then
694
695 ncfile%dpFirstAndLastTimeValues = nf_get_first_and_last(ncfile=ncfile, &
696 ivarindex=ncfile%iVarIndex(nc_time) )
697
698 !> look for and process the "days since MM-DD-YYYY" attribute
699 call nf_get_time_units(ncfile=ncfile)
700
701 call nf_calculate_time_range(ncfile)
702
703 !> retrieve the time values as included in the netCDF file
704 call nf_get_time_vals(ncfile)
705
706 endif
707
708 !> retrieve the X and Y coordinates from the netCDF file...
709 call nf_get_x_and_y(ncfile)
710
711 !> define the entire grid area as the AOI
712 ncfile%iColBounds(nc_left) = lbound(ncfile%rX_Coords,1)
713 ncfile%iColBounds(nc_right) = ubound(ncfile%rX_Coords,1)
714
715 ncfile%iRowBounds(nc_top) = lbound(ncfile%rY_Coords,1)
716 ncfile%iRowBounds(nc_bottom) = ubound(ncfile%rY_Coords,1)
717
718 !> based on the subset of the netCDF file as determined above, set the
719 !> start, count, and stride parameters for use in all further data
720 !> retrievals
721 call nf_set_start_count_stride(ncfile)
722
723 !> establish the bounds to iterate over; this can enable horiz or vert flipping
724 call nf_set_iteration_bounds(ncfile)
725
726 !> now that we have (possibly) created a subset, need to get the
727 !> **NATIVE** coordinate bounds so that the intermediate grid file
728 !> can be created
730
732
733!----------------------------------------------------------------------
734
735subroutine netcdf_open_and_prepare_as_input(NCFILE, sFilename, &
736 lFlipHorizontal, lFlipVertical, &
737 lAllowAutomaticDataFlipping, &
738 rX_Coord_AddOffset, rY_Coord_AddOffset, &
739 sVariableOrder, sVarName_x, &
740 sVarName_y, sVarName_z, sVarName_time, &
741 rCoordinateTolerance, &
742 tGridBounds, iLU)
743
744 type (t_netcdf4_file ) :: ncfile
745 character (len=*) :: sfilename
746 logical (c_bool), optional :: lfliphorizontal
747 logical (c_bool), optional :: lflipvertical
748 logical (c_bool), optional :: lallowautomaticdataflipping
749 character (len=*), optional :: svariableorder
750 real (c_double), optional :: rx_coord_addoffset
751 real (c_double), optional :: ry_coord_addoffset
752 character (len=*), optional :: svarname_x
753 character (len=*), optional :: svarname_y
754 character (len=*), optional :: svarname_z
755 character (len=*), optional :: svarname_time
756 real (c_double), optional :: rcoordinatetolerance
757 type (grid_bounds_t), optional :: tgridbounds
758 integer (c_int), optional :: ilu
759
760 ! [ LOCALS ]
761 type (t_netcdf_variable), pointer :: pnc_var
762 type (t_netcdf_dimension), pointer :: pnc_dim
763 logical (c_bool) :: lfileopen
764 integer (c_int), dimension(2) :: icolrow_ll, icolrow_ur, icolrow_lr, icolrow_ul
765 integer (c_int) :: icolmin, icolmax, irowmin, irowmax
766 integer (c_int) :: iindex
767
768 call nf_open_file(ncfile=ncfile, sfilename=sfilename)
769
770 call nf_populate_dimension_struct( ncfile )
771 call nf_populate_variable_struct( ncfile )
772
773 if (present(lfliphorizontal) ) ncfile%lFlipHorizontal = lfliphorizontal
774 if (present(lflipvertical) ) ncfile%lFlipVertical = lflipvertical
775 if (present( lallowautomaticdataflipping) ) &
776 ncfile%lAllowAutomaticDataFlipping = lallowautomaticdataflipping
777 if (present(rx_coord_addoffset)) ncfile%rX_Coord_AddOffset = rx_coord_addoffset
778 if (present(ry_coord_addoffset)) ncfile%rY_Coord_AddOffset = ry_coord_addoffset
779
780 if (present(rcoordinatetolerance)) ncfile%rCoordinateTolerance = rcoordinatetolerance
781
782 if (present(svariableorder) ) ncfile%sVariableOrder = svariableorder
783
784 if( present(ilu) ) then
785 inquire (unit=ilu, opened=lfileopen)
786 if ( lfileopen ) call netcdf_dump_cdl( ncfile, ilu)
787 endif
788
789 if (present(svarname_x) ) then
790 ncfile%sVarName(nc_x) = svarname_x
791 else
792 ncfile%sVarName(nc_x) = "x"
793 endif
794
795 if (present(svarname_y) ) then
796 ncfile%sVarName(nc_y) = svarname_y
797 else
798 ncfile%sVarName(nc_y) = "y"
799 endif
800
801 if (present(svarname_z) ) then
802 ncfile%sVarName(nc_z) = svarname_z
803 else
804 ncfile%sVarName(nc_z) = "prcp"
805 endif
806
807 if (present(svarname_time) ) then
808 ncfile%sVarName(nc_time) = svarname_time
809 else
810 ncfile%sVarName(nc_time) = "time"
811 endif
812
813 call nf_get_variable_id_and_type( ncfile )
814
815 ! OK. We only want to attempt to call functions that
816 ! process the time variable if a time variable actually exists!!
817 if ( ncfile%iVarID(nc_time) >= 0 ) then
818
819 ncfile%dpFirstAndLastTimeValues = nf_get_first_and_last(ncfile=ncfile, &
820 ivarindex=ncfile%iVarIndex(nc_time) )
821
822 !> look for and process the "days since MM-D-YYYY" attribute
823 call nf_get_time_units(ncfile=ncfile)
824
825 call nf_calculate_time_range(ncfile)
826
827 !> retrieve the time values as included in the netCDF file
828 call nf_get_time_vals(ncfile)
829
830 endif
831
832 call nf_get_xyz_units(ncfile=ncfile)
833
834 !> establish scale_factor and add_offset values, if present
835 call nf_get_scale_and_offset(ncfile=ncfile)
836
837 !> retrieve the X and Y coordinates from the netCDF file...
838 call nf_get_x_and_y(ncfile)
839
840 if (present(tgridbounds) ) then
841
842 !> define a subset of the grid as the AOI
843 !> need all four corner points since it is likely that
844 !> the AOI rectangle is rotated relative to the base
845 !> projection
846
847 icolrow_ll = netcdf_coord_to_col_row(ncfile=ncfile, &
848 rx=tgridbounds%rXll, &
849 ry=tgridbounds%rYll)
850
851 icolrow_lr = netcdf_coord_to_col_row(ncfile=ncfile, &
852 rx=tgridbounds%rXlr, &
853 ry=tgridbounds%rYlr)
854
855 icolrow_ul = netcdf_coord_to_col_row(ncfile=ncfile, &
856 rx=tgridbounds%rXul, &
857 ry=tgridbounds%rYul)
858
859 icolrow_ur = netcdf_coord_to_col_row(ncfile=ncfile, &
860 rx=tgridbounds%rXur, &
861 ry=tgridbounds%rYur)
862
863#ifdef DEBUG_PRINT
864 write(*, fmt="(a)") "subroutine 'netcdf_open_and_prepare_as_input'"
865 write(*, fmt="(a,a,i6)") "Find correspondence between project bounds (in native projection) and row, col of dataset | ", &
866 trim(__file__), __line__
867 write(*, fmt="(a)") " column row X Y"
868 write(*, fmt="(a,i6,i6,a,f14.3,f14.3)") "LL: ", icolrow_ll(column), icolrow_ll(row), " <==> ", tgridbounds%rXll, tgridbounds%rYll
869 write(*, fmt="(a,i6,i6,a,f14.3,f14.3)") "LR: ", icolrow_lr(column), icolrow_lr(row), " <==> ", tgridbounds%rXlr, tgridbounds%rYlr
870 write(*, fmt="(a,i6,i6,a,f14.3,f14.3)") "UL: ", icolrow_ul(column), icolrow_ul(row), " <==> ", tgridbounds%rXul, tgridbounds%rYul
871 write(*, fmt="(a,i6,i6,a,f14.3,f14.3)") "UR: ", icolrow_ur(column), icolrow_ur(row), " <==> ", tgridbounds%rXur, tgridbounds%rYur
872#endif
873
874 ncfile%iColBounds(nc_left) = &
875 max( min( icolrow_ul(column), icolrow_ur(column), icolrow_ll(column), icolrow_lr(column) ) - 4, &
876 lbound(ncfile%rX_Coords,1) )
877
878 ncfile%iColBounds(nc_right) = &
879 min( max( icolrow_ul(column), icolrow_ur(column), icolrow_ll(column), icolrow_lr(column) ) + 4, &
880 ubound(ncfile%rX_Coords,1) )
881
882
883 ncfile%iRowBounds(nc_top) = &
884 max( min( icolrow_ul(row), icolrow_ur(row), icolrow_ll(row), icolrow_lr(row) ) - 4, &
885 lbound(ncfile%rY_Coords,1) )
886
887 ncfile%iRowBounds(nc_bottom) = &
888 min( max( icolrow_ul(row), icolrow_ur(row), icolrow_ll(row), icolrow_lr(row) ) + 4, &
889 ubound(ncfile%rY_Coords,1) )
890
891 else
892
893 !> define the entire grid area as the AOI
894 ncfile%iColBounds(nc_left) = lbound(ncfile%rX_Coords,1)
895 ncfile%iColBounds(nc_right) = ubound(ncfile%rX_Coords,1)
896
897 ncfile%iRowBounds(nc_top) = lbound(ncfile%rY_Coords,1)
898 ncfile%iRowBounds(nc_bottom) = ubound(ncfile%rY_Coords,1)
899
900 endif
901
902 !> based on the subset of the netCDF file as determined above, set the
903 !> start, count, and stride parameters for use in all further data
904 !> retrievals
905 call nf_set_start_count_stride(ncfile)
906
907 !> establish the bounds to iterate over; this can enable horiz or vert flipping
908 call nf_set_iteration_bounds(ncfile)
909
910 !> now that we have (possibly) created a subset, need to get the
911 !> **NATIVE** coordinate bounds so that the intermediate grid file
912 !> can be created
914
916
917!----------------------------------------------------------------------
918
919subroutine netcdf_open_and_prepare_as_output_archive(NCFILE, NCFILE_ARCHIVE, &
920 iOriginMonth, iOriginDay, iOriginYear, iStartYear, iEndYear)
921
922 type (t_netcdf4_file ) :: ncfile
923 type (t_netcdf4_file ) :: ncfile_archive
924 integer (c_int) :: ioriginmonth
925 integer (c_int) :: ioriginday
926 integer (c_int) :: ioriginyear
927 integer (c_int) :: istartyear
928 integer (c_int) :: iendyear
929
930 ! [ LOCALS ]
931 type (t_netcdf_variable), pointer :: pnc_var
932 type (t_netcdf_dimension), pointer :: pnc_dim
933 integer (c_int) :: iindex
934 integer (c_int) :: inumcols, inumrows
935 integer (c_int) :: imincol, imaxcol
936 integer (c_int) :: iminrow, imaxrow
937 real (c_double), dimension(:), allocatable :: rx, ry
938 character (len=10) :: sorigintext
939 character (len=256) :: sfilename
940
941 write(sorigintext, fmt="(i4.4,'-',i2.2,'-',i2.2)") ioriginyear, &
942 ioriginmonth, ioriginday
943
944 imaxrow = maxval(ncfile%iRowBounds)
945 iminrow = minval(ncfile%iRowBounds)
946 imaxcol = maxval(ncfile%iColBounds)
947 imincol = minval(ncfile%iColBounds)
948
949 inumrows = imaxrow - iminrow + 1
950 inumcols = imaxcol - imincol + 1
951
952 allocate(rx(inumcols))
953 allocate(ry(inumrows))
954 rx = ncfile%rX_Coords(imincol:imaxcol)
955 ry = ncfile%rY_Coords(iminrow:imaxrow)
956
957 sfilename = trim(ncfile%sVarName(nc_z))//"_"//trim(ascharacter(istartyear)) &
958 //"_"//trim(ascharacter(iendyear))//"__" &
959 //trim(ascharacter(inumrows)) &
960 //"_by_"//trim(ascharacter(inumcols))//".nc"
961
962 call nf_create(ncfile=ncfile_archive, sfilename=trim(sfilename) )
963
964 !> set dimension values in the NCFILE struct
965 call nf_set_standard_dimensions(ncfile=ncfile_archive, &
966 inx=inumcols, &
967 iny=inumrows)
968
969 ncfile_archive%sVarUnits(nc_x) = ncfile%sVarUnits(nc_x)
970 ncfile_archive%sVarUnits(nc_y) = ncfile%sVarUnits(nc_y)
971 ncfile_archive%sVarUnits(nc_z) = ncfile%sVarUnits(nc_z)
972
973 !> transfer dimension values to netCDF file
974 call nf_define_dimensions( ncfile=ncfile_archive )
975
976 !> set variable values in the NCFILE struct
977 call nf_set_standard_variables(ncfile=ncfile_archive, &
978 svarname_z = trim(ncfile%sVarName(nc_z)) )
979
980 !> transfer variable values to netCDF file
981 call nf_define_variables(ncfile=ncfile_archive)
982
983 call nf_get_variable_id_and_type( ncfile=ncfile_archive )
984
985 call nf_set_standard_attributes(ncfile=ncfile_archive, &
986 sorigintext=sorigintext)
987
988 call nf_set_global_attributes(ncfile=ncfile_archive, &
989 sdatatype=trim(ncfile%sVarName(nc_z)), &
990 ssourcefile=trim(ncfile%sFilename))
991
992 call nf_put_attributes(ncfile=ncfile_archive)
993
994 !> enable a low level of data compression for the
995 !> variable of interest
996 call nf_define_deflate(ncfile=ncfile_archive, &
997 ivarid=ncfile_archive%iVarID(nc_z), &
998 ishuffle=nc_shuffle_yes, &
999 ideflate=nc_deflate_yes, &
1000 ideflate_level=2 )
1001
1002 call nf_enddef(ncfile=ncfile_archive)
1003
1004 call nf_put_x_and_y(ncfile=ncfile_archive, &
1005 dpx=ncfile%rX_Coords(imincol:imaxcol), &
1006 dpy=ncfile%rY_Coords(iminrow:imaxrow) )
1007! dpX=rX, &
1008! dpY=rY )
1009
1010! call netcdf_close_file(NCFILE_ARCHIVE)
1011
1013
1014
1015
1016subroutine netcdf_open_and_prepare_as_output( NCFILE, sVariableName, sVariableUnits, &
1017 iNX, iNY, fX, fY, StartDate, EndDate, PROJ4_string, history_list, executable_name, &
1018 dpLat, dpLon, fValidMin, fValidMax, write_time_bounds, filename_prefix, &
1019 filename_modifier)
1020
1021 type (t_netcdf4_file ), pointer, intent(inout) :: ncfile
1022 character (len=*), intent(in) :: svariablename
1023 character (len=*), intent(in) :: svariableunits
1024 integer (c_int), intent(in) :: iny
1025 real (c_double), intent(in) :: fx(:)
1026 integer (c_int), intent(in) :: inx
1027 real (c_double), intent(in) :: fy(:)
1028 type (datetime_t), intent(in) :: startdate
1029 type (datetime_t), intent(in) :: enddate
1030 character (len=*), intent(in) :: proj4_string
1031 type (fstring_list_t), intent(in), pointer, optional :: history_list
1032 character (len=*), intent(in), optional :: executable_name
1033 real (c_double), intent(in), optional :: dplat(:,:)
1034 real (c_double), intent(in), optional :: dplon(:,:)
1035 real (c_float), intent(in), optional :: fvalidmin
1036 real (c_float), intent(in), optional :: fvalidmax
1037 logical (c_bool), intent(in), optional :: write_time_bounds
1038 character (len=*), intent(in), optional :: filename_prefix
1039 character (len=*), intent(in), optional :: filename_modifier
1040
1041! ! [ LOCALS ]
1042 type (t_netcdf_variable), pointer :: pnc_var
1043 type (t_netcdf_dimension), pointer :: pnc_dim
1044 integer (c_int) :: iindex
1045 character (len=10) :: sorigintext
1046 character (len=:), allocatable :: sfilename
1047 type (fstring_list_t), pointer :: history_list_l
1048 logical (c_bool) :: write_time_bounds_l
1049 character (len=:), allocatable :: executable_name_l
1050 real (c_float) :: valid_minimum
1051 real (c_float) :: valid_maximum
1052 logical (c_bool) :: include_latlon
1053 type (datetime_t) :: dt
1054 character (len=:), allocatable :: date_time_text
1055 character (len=:), allocatable :: filename_prefix_l
1056 character (len=:), allocatable :: filename_modifier_l
1057 call dt%systime()
1058 date_time_text = dt%prettydatetime()
1059
1060
1061 if (present( fvalidmin ) ) then
1062 valid_minimum = fvalidmin
1063 else
1064 valid_minimum = -1.0e+3
1065 endif
1066
1067 if (present( fvalidmax ) ) then
1068 valid_maximum = fvalidmax
1069 else
1070 valid_maximum = 1.0e+10
1071 endif
1072
1073 if ( present( executable_name ) ) then
1074 executable_name_l = trim( executable_name )
1075 else
1076 executable_name_l = "SWB"
1077 endif
1078
1079 if ( present( filename_modifier ) ) then
1080 filename_modifier_l = "_"//trim( filename_modifier )//"_"
1081 else
1082 filename_modifier_l = "_"
1083 endif
1084
1085 if ( present( filename_prefix ) ) then
1086 if (len_trim(filename_prefix) > 0) then
1087 filename_prefix_l = trim( filename_prefix )//"_"
1088 else
1089 filename_prefix_l = ""
1090 endif
1091 else
1092 filename_prefix_l = ""
1093 endif
1094
1095 if ( present( history_list) ) then
1096 history_list_l => history_list
1097 else
1098 allocate( history_list_l )
1099 call history_list_l%append(date_time_text//": Soil-Water-Balance run started.")
1100 endif
1101
1102 if ( present( write_time_bounds ) ) then
1103 write_time_bounds_l = write_time_bounds
1104 else
1105 write_time_bounds_l = false
1106 endif
1107
1108 include_latlon = logical( present( dpLat ) .and. present( dpLon ), c_bool )
1109
1110 write(sorigintext, fmt="(i4.4,'-',i2.2,'-',i2.2)") startdate%iYear, startdate%iMonth, startdate%iDay
1111
1112 ! if a filename_prefix argument has been supplied, override the variable specified in
1113 ! the 'output' module
1114 if (len_trim(filename_prefix_l) > 0 ) then
1115
1116 sfilename = trim(output_directory_name)//trim(filename_prefix_l) &
1117 //trim(svariablename)//"_"//filename_modifier_l &
1118 //startdate%prettydate()//"_to_"//enddate%prettydate()//"__" &
1119 //trim(ascharacter(iny))//"_by_"//trim(ascharacter(inx))//".nc"
1120
1121 else
1122
1123 sfilename = trim(output_directory_name)//trim(output_prefix_name) &
1124 //trim(svariablename)//"_"//filename_modifier_l &
1125 //startdate%prettydate()//"_to_"//enddate%prettydate()//"__" &
1126 //trim(ascharacter(iny))//"_by_"//trim(ascharacter(inx))//".nc"
1127
1128 endif
1129
1130 call logs%write("Attempting to open netCDF file for writing with filename "//dquote(sfilename))
1131
1132 call nf_create(ncfile=ncfile, sfilename=trim(sfilename) )
1133
1134 !> set dimension values in the NCFILE struct
1135 call nf_set_standard_dimensions(ncfile=ncfile, inx=inx, iny=iny, &
1136 write_time_bounds=write_time_bounds_l )
1137
1138 !> @todo implement more flexible method of assigning units
1139! NCFILE%sVarUnits(NC_X) = sXY_units
1140! NCFILE%sVarUnits(NC_Y) = sXY_units
1141 ncfile%sVarUnits(nc_z) = svariableunits
1142
1143 !> transfer dimension values to netCDF file
1144 call nf_define_dimensions( ncfile=ncfile )
1145
1146 !> set variable values in the NCFILE struct
1147 call nf_set_standard_variables(ncfile=ncfile, svarname_z = svariablename, &
1148 llatlon=include_latlon, write_time_bounds=write_time_bounds_l )
1149
1150 !> transfer variable values to netCDF file
1151 call nf_define_variables(ncfile=ncfile)
1152
1153 call nf_get_variable_id_and_type( ncfile=ncfile )
1154
1155 call nf_set_standard_attributes(ncfile=ncfile, sorigintext=sorigintext, &
1156 proj4_string=proj4_string, llatlon=include_latlon, fvalidmin=valid_minimum, &
1157 fvalidmax=valid_maximum, write_time_bounds=write_time_bounds_l )
1158
1159 call nf_set_global_attributes(ncfile=ncfile, &
1160 sdatatype=trim(ncfile%sVarName(nc_z)), history_list=history_list_l, &
1161 executable_name=executable_name_l )
1162
1163 call nf_put_attributes(ncfile=ncfile)
1164
1165 !> enable a low level of data compression for the variable of interest
1166 call nf_define_deflate(ncfile=ncfile, &
1167 ivarid=ncfile%iVarID(nc_z), &
1168 ishuffle=nc_shuffle_yes, &
1169 ideflate=nc_deflate_yes, &
1170 ideflate_level=2 )
1171
1172 call nf_enddef(ncfile=ncfile)
1173
1174 ! we are only supplying a vector of X and Y on the assumption that the base projection
1175 ! results in a uniform grid (in other words, we have the same X value for all coluns of a given row)
1176 call nf_put_x_and_y(ncfile=ncfile, &
1177 dpx=fx, &
1178 dpy=fy )
1179
1180! allocate( NCFILE%rX_Coords( size( fX) ), stat=iStat )
1181! allocate( NCFILE%rY_Coords( size( fY) ), stat=iStat )
1182 ncfile%rX_Coords = fx
1183 ncfile%rY_Coords = fy
1184
1185 if (present( dplat ) .and. present( dplon ) ) then
1186
1187 call nf_put_lat_and_lon(ncfile=ncfile, &
1188 dplat=dplat, &
1189 dplon=dplon )
1190
1191 endif
1192
1194
1195
1196!----------------------------------------------------------------------
1197
1198subroutine nf_set_z_variable_name(NCFILE, sVarName_z)
1199
1200 type (T_NETCDF4_FILE ) :: NCFILE
1201 character (len=*) :: sVarName_z
1202
1203 ncfile%sVarName(nc_z) = svarname_z
1204
1205end subroutine nf_set_z_variable_name
1206
1207!----------------------------------------------------------------------
1208
1209subroutine nf_set_iteration_bounds(NCFILE)
1210
1211 type (T_NETCDF4_FILE ) :: NCFILE
1212
1213! if (NCFILE%lFlipVertical) then
1214! NCFILE%iRowIter(NC_FIRST) = NCFILE%iNY
1215! NCFILE%iRowIter(NC_LAST) = 1
1216! NCFILE%iRowIter(NC_BY) = -1
1217! else
1218 ncfile%iRowIter(nc_first) = 1
1219 ncfile%iRowIter(nc_last) = ncfile%iNY
1220 ncfile%iRowIter(nc_by) = 1
1221! endif
1222
1223 ! if (NCFILE%lFlipHorizontal) then
1224 ! NCFILE%iColIter(NC_FIRST) = NCFILE%iNX
1225 ! NCFILE%iColIter(NC_LAST) = 1
1226 ! NCFILE%iColIter(NC_BY) = -1
1227 ! else
1228 ncfile%iColIter(nc_first) = 1
1229 ncfile%iColIter(nc_last) = ncfile%iNX
1230 ncfile%iColIter(nc_by) = 1
1231 ! endif
1232
1233end subroutine nf_set_iteration_bounds
1234
1235!----------------------------------------------------------------------
1236
1238
1239 type (T_NETCDF4_FILE ) :: NCFILE
1240
1241 ! [ LOCALS ]
1242 integer (c_int) :: iIndex
1243
1244 ! loop over the three (assumed) dimensions of the "Z" variable;
1245 ! assign appropriate bounds to each
1246 do iindex = 0,3
1247
1248 select case (iindex)
1249
1250 case (nc_x)
1251
1252 !> need to subtract 1 from the start index: we are using the
1253 !> netCDF C API, in which index values are relative to zero
1254 ncfile%iStart(iindex) = minval(ncfile%iColBounds) - 1
1255 ncfile%iNX = maxval(ncfile%iColBounds) - minval(ncfile%iColBounds) + 1
1256 ncfile%iCount(iindex) = ncfile%iNX
1257! NCFILE%iCount(iIndex) = maxval(NCFILE%iColBounds) - minval(NCFILE%iColBounds)
1258 ncfile%iStride(iindex) = 1_c_size_t
1259
1260 case (nc_y)
1261
1262 !> note: this assumes that the row numbers increase from top to bottom,
1263 !> while the Y coordinates decrease top to bottom
1264
1265 ncfile%iStart(iindex) = minval(ncfile%iRowBounds) - 1
1266 ncfile%iNY = maxval(ncfile%iRowBounds) - minval(ncfile%iRowBounds) + 1
1267 ncfile%iCount(iindex) = ncfile%iNY
1268 !>
1269 !> count must be set to the number of values! maxval minus minval results
1270 !> in a diagonal pattern in the input as we read in the incorrect number
1271 !> of results
1272! NCFILE%iCount(iIndex) = maxval(NCFILE%iRowBounds) - minval(NCFILE%iRowBounds)
1273 ncfile%iStride(iindex) = 1_c_size_t
1274
1275 case (nc_time)
1276
1277 ncfile%iStart(iindex) = 0_c_size_t
1278 ncfile%iCount(iindex) = 1_c_size_t
1279 ncfile%iStride(iindex) = 1_c_size_t
1280
1281 case default
1282
1283 end select
1284
1285 enddo
1286
1287end subroutine nf_set_start_count_stride
1288
1289!----------------------------------------------------------------------
1290
1292
1293 type (T_NETCDF4_FILE ) :: NCFILE
1294
1295 ! [ LOCALS ]
1296 real (c_double) :: rXmin, rXmax
1297 real (c_double) :: rYmin, rYmax
1298
1299 !> find the (x,y) associated with the column and row number bounds
1300 rxmin = minval(ncfile%rX_Coords(ncfile%iColBounds(nc_left):ncfile%iColBounds(nc_right)) )
1301 rxmax = maxval(ncfile%rX_Coords(ncfile%iColBounds(nc_left):ncfile%iColBounds(nc_right)) )
1302 rymin = minval(ncfile%rY_Coords(ncfile%iRowBounds(nc_top):ncfile%iRowBounds(nc_bottom)) )
1303 rymax = maxval(ncfile%rY_Coords(ncfile%iRowBounds(nc_top):ncfile%iRowBounds(nc_bottom)) )
1304
1305 ncfile%rX(nc_left) = rxmin - ncfile%rGridCellSizeX * 0.5_c_double
1306 ncfile%rX(nc_right) = rxmax + ncfile%rGridCellSizeX * 0.5_c_double
1307 ncfile%rY(nc_top) = rymax + ncfile%rGridCellSizeY * 0.5_c_double
1308 ncfile%rY(nc_bottom) = rymin - ncfile%rGridCellSizeY * 0.5_c_double
1309
1310#ifdef DEBUG_PRINT
1311 print *, ""
1312 print *, repeat("-", 80)
1313 print *, "Filename: ", ncfile%sFilename
1314 print *, "Grid cell size (X): ", ncfile%rGridCellSizeX
1315 print *, "Grid cell size (Y): ", ncfile%rGridCellSizeY
1316
1317 print *, "Bounds of data subset area, in native coordinates"
1318 print *, "X (left): ", ncfile%rX(nc_left)
1319 print *, "X (right): ", ncfile%rX(nc_right)
1320 print *, "Y (top): ", ncfile%rY(nc_top)
1321 print *, "Y (bottom): ", ncfile%rY(nc_bottom)
1322 print *, ""
1323#endif
1324
1325end subroutine nf_return_native_coord_bounds
1326
1327!----------------------------------------------------------------------
1328
1329subroutine nf_get_time_vals(NCFILE)
1330
1331 type (T_NETCDF4_FILE ) :: NCFILE
1332
1333 integer (c_int) :: iVarIndex_time
1334 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR_time
1335 type (T_NETCDF_DIMENSION), pointer :: pNC_DIM_time
1336 integer (c_int) :: iLowerBound, iUpperBound
1337 integer (c_int) :: iStat
1338
1339 istat = 0
1340
1341 ivarindex_time = ncfile%iVarIndex(nc_time)
1342
1343 call assert(ivarindex_time >= lbound(ncfile%pNC_VAR,1) &
1344 .and. ivarindex_time <= ubound(ncfile%pNC_VAR,1), &
1345 "INTERNAL PROGRAMMING ERROR - Index out of bounds", __file__, __line__)
1346
1347 pnc_var_time => ncfile%pNC_VAR(ivarindex_time)
1348 pnc_dim_time => ncfile%pNC_DIM( pnc_var_time%iNC_DimID(0) )
1349
1350 if (allocated(ncfile%rDateTimeValues) ) deallocate(ncfile%rDateTimeValues, stat=istat)
1351 call assert(istat==0, "Failed to deallocate memory for time values", &
1352 __file__, __line__)
1353
1354 allocate( ncfile%rDateTimeValues(0 : pnc_dim_time%iNC_DimSize-1 ), stat=istat )
1355 call assert(istat==0, "Failed to allocate memory for time values", &
1356 __file__, __line__)
1357
1358 !> @todo allow time to be read in as float, short, or int as well
1359
1360 call nf_get_variable_vector_double(ncfile=ncfile, &
1361 inc_varid=pnc_var_time%iNC_VarID, &
1362 inc_start=0_c_size_t, &
1363 inc_count=pnc_dim_time%iNC_DimSize, &
1364 inc_stride=1_c_size_t, &
1365 dpnc_vars=ncfile%rDateTimeValues)
1366
1367end subroutine nf_get_time_vals
1368
1369!----------------------------------------------------------------------
1370
1371subroutine nf_get_x_and_y(NCFILE)
1372
1373 type (T_NETCDF4_FILE ) :: NCFILE
1374
1375 integer (c_int) :: iVarIndex_x, iVarIndex_y
1376 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR_x, pNC_VAR_y
1377 type (T_NETCDF_DIMENSION), pointer :: pNC_DIM_x, pNC_DIM_y
1378 integer (c_int) :: iLowerBound, iUpperBound
1379 integer (c_int) :: iStat
1380
1381 ivarindex_x = ncfile%iVarIndex(nc_x)
1382 ivarindex_y = ncfile%iVarIndex(nc_y)
1383
1384 call assert(ivarindex_x >= lbound(ncfile%pNC_VAR,1) &
1385 .and. ivarindex_x <= ubound(ncfile%pNC_VAR,1), &
1386 "INTERNAL PROGRAMMING ERROR - Index out of bounds", __file__, __line__)
1387
1388 call assert(ivarindex_y >= lbound(ncfile%pNC_VAR,1) &
1389 .and. ivarindex_y <= ubound(ncfile%pNC_VAR,1), &
1390 "INTERNAL PROGRAMMING ERROR - Index out of bounds", __file__, __line__)
1391
1392 pnc_var_x => ncfile%pNC_VAR(ivarindex_x)
1393 pnc_var_y => ncfile%pNC_VAR(ivarindex_y)
1394
1395 call assert( pnc_var_x%iNumberOfDimensions == 1, &
1396 "Dimensions other than one for the x-coordinate variable are currently unsupported.", &
1397 __file__, __line__)
1398
1399 call assert( pnc_var_y%iNumberOfDimensions == 1, &
1400 "Dimensions other than one for the y-coordinate variable are currently unsupported.", &
1401 __file__, __line__)
1402
1403 pnc_dim_x => ncfile%pNC_DIM( pnc_var_x%iNC_DimID(0) )
1404 pnc_dim_y => ncfile%pNC_DIM( pnc_var_y%iNC_DimID(0) )
1405
1406 allocate( ncfile%rX_Coords( pnc_dim_x%iNC_DimSize ), stat=istat )
1407 call assert(istat==0, "Failed to allocate memory for X-coordinate values", &
1408 __file__, __line__)
1409
1410 allocate (ncfile%rY_Coords( pnc_dim_y%iNC_DimSize ), stat=istat )
1411 call assert(istat==0, "Failed to allocate memory for Y-coordinate values", &
1412 __file__, __line__)
1413
1414 call nf_get_variable_vector_double(ncfile=ncfile, &
1415 inc_varid=pnc_var_x%iNC_VarID, &
1416 inc_start=0_c_size_t, &
1417 inc_count=pnc_dim_x%iNC_DimSize, &
1418 inc_stride=1_c_size_t, &
1419 dpnc_vars=ncfile%rX_Coords)
1420
1421 call nf_get_variable_vector_double(ncfile=ncfile, &
1422 inc_varid=pnc_var_y%iNC_VarID, &
1423 inc_start=0_c_size_t, &
1424 inc_count=pnc_dim_y%iNC_DimSize, &
1425 inc_stride=1_c_size_t, &
1426 dpnc_vars=ncfile%rY_Coords)
1427
1428 ncfile%rX_Coords = ncfile%rX_Coords + ncfile%rX_Coord_AddOffset
1429 ncfile%rY_Coords = ncfile%rY_Coords + ncfile%rY_Coord_AddOffset
1430
1431 ilowerbound = lbound(ncfile%rX_Coords, 1)
1432 iupperbound = ubound(ncfile%rX_Coords, 1)
1433
1434 if (ncfile%rX_Coords(iupperbound) > ncfile%rX_Coords(ilowerbound) ) then
1435 ncfile%lX_IncreasesWithIndex = true
1436 if ( ncfile%lAllowAutomaticDataFlipping ) ncfile%lFlipHorizontal = false
1437 else
1438 ncfile%lX_IncreasesWithIndex = false
1439 if ( ncfile%lAllowAutomaticDataFlipping ) then
1440 ncfile%lFlipHorizontal = true
1441 call logs%write( "** Horizontal coordinates decrease with index values **", &
1442 ilinesbefore=1, &
1443 iloglevel=log_all )
1444 call logs%write( " ==> flipping grid horizontally", &
1445 ilinesafter=1, &
1446 iloglevel=log_all )
1447 endif
1448 endif
1449
1450 ilowerbound = lbound(ncfile%rY_Coords, 1)
1451 iupperbound = ubound(ncfile%rY_Coords, 1)
1452
1453 if (ncfile%rY_Coords(iupperbound) > ncfile%rY_Coords(ilowerbound) ) then
1454 ncfile%lY_IncreasesWithIndex = true
1455 if ( ncfile%lAllowAutomaticDataFlipping ) then
1456 ncfile%lFlipVertical = true
1457 call logs%write( "** Vertical coordinates increase with index values **", &
1458 ilinesbefore=1, &
1459 iloglevel=log_all )
1460 call logs%write( " ==> flipping grid vertically", &
1461 ilinesafter=1, &
1462 iloglevel=log_all )
1463 endif
1464 else
1465 ncfile%lY_IncreasesWithIndex = false
1466 if ( ncfile%lAllowAutomaticDataFlipping ) ncfile%lFlipVertical = false
1467 endif
1468
1469 call assert(pnc_dim_x%iNC_DimSize > 2, "INTERNAL PROGRAMMING ERROR - " &
1470 //"netCDF X dimension size must be greater than 2.", __file__, __line__)
1471
1472 call assert(pnc_dim_y%iNC_DimSize > 2, "INTERNAL PROGRAMMING ERROR - " &
1473 //"netCDF Y dimension size must be greater than 2.", __file__, __line__)
1474
1475 ncfile%rGridCellSizeX = ( maxval(ncfile%rX_Coords) &
1476 - minval(ncfile%rX_Coords) ) &
1477 / real(pnc_dim_x%iNC_DimSize - 1, c_double)
1478
1479 ncfile%rGridCellSizeY = ( maxval(ncfile%rY_Coords) &
1480 - minval(ncfile%rY_Coords) ) &
1481 / real(pnc_dim_y%iNC_DimSize - 1, c_double)
1482
1483 ! print *, '*** netCDF x- and y- coord read ***'
1484 ! print *, trim(__FILE__), ': ', __LINE__
1485 ! print *, 'file:', trim(NCFILE%sFilename)
1486 ! print *, 'x-coords: ', NCFILE%rX_Coords
1487 ! print *, 'y-coords: ', NCFILE%rY_Coords
1488 ! print *, '***********************************'
1489
1490end subroutine nf_get_x_and_y
1491
1492!----------------------------------------------------------------------
1493
1494subroutine nf_open_file(NCFILE, sFilename, iLU)
1495
1496 type (T_NETCDF4_FILE ) :: NCFILE
1497 character (len=*) :: sFilename
1498 integer (c_int), optional :: iLU
1499
1500 ! [ LOCALS ]
1501 logical (c_bool) :: lFileOpen
1502
1503 call logs%write("Attempting to open READONLY netCDF file: " &
1504 //dquote(sfilename))
1505
1506 call nf_trap( nc_open(trim(sfilename)//c_null_char, &
1507 nc_readonly, ncfile%iNCID), __file__, __line__ )
1508
1509 call nf_trap( nc_inq_format(ncid=ncfile%iNCID, formatp=ncfile%iFileFormat), &
1510 __file__, __line__)
1511
1512 call logs%write(" Succeeded. ncid: "//trim(ascharacter(ncfile%iNCID)) &
1513 //" format: "//trim(netcdf_format_string(ncfile%iFileFormat) ) )
1514
1515 ncfile%sFilename = sfilename
1516
1517 if( present(ilu) ) then
1518 inquire (unit=ilu, opened=lfileopen)
1519 if ( lfileopen ) call netcdf_dump_cdl( ncfile, ilu)
1520 endif
1521
1522end subroutine nf_open_file
1523
1524!----------------------------------------------------------------------
1525
1526subroutine netcdf_open_file(NCFILE, sFilename, iLU)
1527
1528 type (t_netcdf4_file ) :: ncfile
1529 character (len=*) :: sfilename
1530 integer (c_int), optional :: ilu
1531
1532 if (present(ilu) ) then
1533
1534 call nf_open_file(ncfile=ncfile, &
1535 sfilename=sfilename, &
1536 ilu=ilu)
1537
1538 else
1539
1540 call nf_open_file(ncfile=ncfile, &
1541 sfilename=sfilename)
1542
1543 endif
1544
1545 !> Similarly, the structure of the file may be slightly different from the
1546 !> previous file
1547 call nf_populate_dimension_struct( ncfile )
1548 call nf_populate_variable_struct( ncfile )
1549
1550 !> CANNOT ASSUME THAT THIS WILL REMAIN CONSTANT ACROSS FILES FROM THE
1551 !> SAME PROVIDER!! MUST UPDATE TO ENSURE THAT THE INDICES ARE STILL RELEVANT
1552 call nf_get_variable_id_and_type( ncfile )
1553
1554 ! OK. We only want to attempt to call functions that
1555 ! process the time variable if a time variable actually exists!!
1556 !
1557 ! NOTE: this was previously coded as 'if ( NCFILE%iVarID(NC_TIME) > 0 ) then', which meant that the code
1558 ! failed to properly initialize the time units in the event that the TIME variable happened to be
1559 ! variable number 0
1560 !
1561 if ( ncfile%iVarID(nc_time) >= 0 ) then
1562
1563 ncfile%dpFirstAndLastTimeValues = nf_get_first_and_last(ncfile=ncfile, &
1564 ivarindex=ncfile%iVarIndex(nc_time) )
1565
1566 !> retrieve the origin for the time units associated with this file
1567 call nf_get_time_units(ncfile=ncfile)
1568
1569 !> retrieve the time value specific to this file
1570 call nf_get_time_vals(ncfile)
1571
1572 call nf_calculate_time_range(ncfile)
1573
1574 endif
1575
1576 !> establish scale_factor and add_offset values, if present
1577 call nf_get_scale_and_offset(ncfile=ncfile)
1578
1579end subroutine netcdf_open_file
1580
1581!----------------------------------------------------------------------
1582
1583subroutine nf_trap( iResultCode, sFilename, iLineNumber, netcdf_filename )
1584
1585 integer (c_int) :: iResultCode
1586 character (len=*), optional :: sFilename
1587 integer (c_int), optional :: iLineNumber
1588 character (len=*), optional :: netcdf_filename
1589
1590 ! [ LOCALS ]
1591 type(c_ptr) :: cpResult
1592 character (len=256) :: sTextString
1593 character (len=256) :: sFile
1594 integer (c_int) :: iLine
1595
1596 if (iresultcode /= 0) then
1597
1598 if (present(sfilename)) then
1599 sfile = trim(sfilename)
1600 else
1601 sfile = __file__
1602 endif
1603
1604 if (present(ilinenumber)) then
1605 iline = ilinenumber
1606 else
1607 iline = __line__
1608 endif
1609
1610 cpresult = nc_strerror(iresultcode)
1611 stextstring = char_ptr_to_fortran_string( cpresult )
1612
1613 if (present( netcdf_filename ) ) &
1614 call logs%write("netCDF filename: "//dquote( netcdf_filename ) )
1615
1616 call logs%write("netCDF ERROR: "//dquote( stextstring )//" | error code was: " &
1617 //trim(ascharacter(iresultcode)) )
1618
1619 call assert(false, "SWB is stopping due to a problem reading or writing" &
1620 //" a netCDF file", trim(sfile), iline)
1621
1622 endif
1623
1624end subroutine nf_trap
1625
1626!----------------------------------------------------------------------
1627
1628subroutine netcdf_close_file( NCFILE)
1629
1630 type (t_netcdf4_file ) :: ncfile
1631
1632 call logs%write("Closing netCDF file with name: "//dquote(ncfile%sFilename))
1633 call nf_trap( nc_close(ncfile%iNCID), __file__, __line__ )
1634
1635! call nf_deallocate_data_struct( NCFILE=NCFILE )
1636
1637end subroutine netcdf_close_file
1638
1639!----------------------------------------------------------------------
1640
1642
1643 type (t_netcdf4_file ) :: ncfile
1644
1645 ! [ LOCALS ]
1646 type (t_netcdf_variable), pointer :: pnc_var
1647 integer (c_int) :: iindex
1648
1649 do iindex=0, ncfile%iNumberOfVariables - 1
1650
1651 pnc_var => ncfile%pNC_VAR(iindex)
1652
1653 if (pnc_var%iNumberOfAttributes == 0 ) cycle
1654
1655 if (associated( pnc_var%pNC_ATT )) deallocate( pnc_var%pNC_ATT )
1656 pnc_var%pNC_ATT => null()
1657
1658 enddo
1659
1660 if (associated( ncfile%pNC_VAR )) deallocate( ncfile%pNC_VAR )
1661 if (associated( ncfile%pNC_ATT )) deallocate( ncfile%pNC_ATT )
1662 if (associated( ncfile%pNC_DIM )) deallocate( ncfile%pNC_DIM )
1663
1664 ncfile%pNC_VAR => null()
1665 ncfile%pNC_ATT => null()
1666 ncfile%pNC_DIM => null()
1667
1668end subroutine netcdf_deallocate_data_struct
1669
1670!----------------------------------------------------------------------
1671
1672subroutine netcdf_nullify_data_struct( NCFILE )
1673
1674 type (t_netcdf4_file ) :: ncfile
1675
1676 ! [ LOCALS ]
1677
1678 ncfile%pNC_VAR => null()
1679 ncfile%pNC_ATT => null()
1680 ncfile%pNC_DIM => null()
1681
1682end subroutine netcdf_nullify_data_struct
1683
1684!----------------------------------------------------------------------
1685
1687
1688 type (T_NETCDF4_FILE) :: NCFILE
1689 integer (c_int) :: iStat
1690 integer (c_int) :: iIndex
1691 character (len=256) :: sDimName
1692
1693 call nf_trap( nc_inq_ndims(ncid=ncfile%iNCID, ndimsp=ncfile%iNumberOfDimensions), &
1694 __file__, __line__ )
1695
1696 istat = 0
1697 if (associated(ncfile%pNC_DIM) ) deallocate(ncfile%pNC_DIM, stat=istat)
1698 call assert(istat == 0, "Could not deallocate memory for NC_DIM member in NC_FILE defined type", &
1699 __file__, __line__)
1700
1701 allocate(ncfile%pNC_DIM( 0 : ncfile%iNumberOfDimensions-1), stat=istat )
1702 call assert(istat == 0, "Could not allocate memory for NC_DIM member in NC_FILE defined type", &
1703 __file__, __line__)
1704
1705 ! netCDF 3 function
1706 call nf_trap( nc_inq_unlimdim(ncid=ncfile%iNCID, unlimdimidp=ncfile%iNC3_UnlimitedDimensionNumber), &
1707 __file__, __line__ )
1708
1709 do iindex = 0, ncfile%iNumberOfDimensions-1
1710
1711 call nf_trap(nc_inq_dim(ncid=ncfile%iNCID, dimid=iindex, &
1712 name=sdimname, &
1713 lenp=ncfile%pNC_DIM(iindex)%iNC_DimSize), __file__, __line__ )
1714
1715 ncfile%pNC_DIM(iindex)%iNC_DimID = iindex
1716 ncfile%pNC_DIM(iindex)%sDimensionName = c_to_fortran_string(sdimname)
1717
1718 enddo
1719
1720end subroutine nf_populate_dimension_struct
1721
1722!----------------------------------------------------------------------
1723
1725
1726 type (T_NETCDF4_FILE) :: NCFILE
1727
1728 type (T_NETCDF_ATTRIBUTE), pointer :: pNC_ATT
1729 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
1730 integer (c_int) :: iStat
1731 integer (c_int) :: iIndex, iIndex2 , iIndex3
1732 character (len=256) :: sVarName
1733 character (len=256) :: sAttName
1734 character (len=512) :: sAttValue
1735 integer (c_int), dimension(0:25) :: iAttValue
1736 integer (c_short), dimension(0:25) :: i2AttValue
1737 real (c_double), dimension(0:25) :: cdAttValue
1738
1739 call nf_trap( nc_inq_nvars(ncid=ncfile%iNCID, nvarsp=ncfile%iNumberOfVariables), &
1740 __file__, __line__ )
1741
1742 istat = 0
1743 if (associated(ncfile%pNC_VAR) ) deallocate(ncfile%pNC_VAR, stat=istat)
1744 call assert(istat == 0, "Could not deallocate memory for NC_VAR member in NC_FILE defined type", &
1745 __file__, __line__)
1746
1747 allocate(ncfile%pNC_VAR( 0 : ncfile%iNumberOfVariables-1), stat=istat )
1748 call assert(istat == 0, "Could not allocate memory for NC_VAR member in NC_FILE defined type", &
1749 __file__, __line__)
1750
1751 do iindex = 0, ncfile%iNumberOfVariables-1
1752
1753 pnc_var => ncfile%pNC_VAR(iindex)
1754
1755 call nf_trap(nc_inq_var(ncid=ncfile%iNCID, &
1756 varid=iindex, &
1757 name=svarname, &
1758 xtypep=pnc_var%iNC_VarType, &
1759 ndimsp=pnc_var%iNumberOfDimensions, &
1760 dimidsp=pnc_var%iNC_DimID, &
1761 nattsp=pnc_var%iNumberOfAttributes ), __file__, __line__ )
1762
1763 pnc_var%iNC_VarID = iindex
1764 pnc_var%sVariableName = c_to_fortran_string(svarname)
1765
1766 if( pnc_var%iNumberOfAttributes > 0 ) then
1767
1768 if (associated(pnc_var%pNC_ATT) ) deallocate(pnc_var%pNC_ATT, stat=istat)
1769 call assert(istat == 0, "Could not deallocate memory for NC_ATT member within NC_VAR in NC_FILE defined type", &
1770 __file__, __line__)
1771
1772 allocate( pnc_var%pNC_ATT( 0:pnc_var%iNumberOfAttributes - 1 ), stat = istat)
1773 call assert(istat == 0, "Could not allocate memory for NC_ATT member within NC_VAR in NC_FILE defined type", &
1774 __file__, __line__)
1775
1776 do iindex2=0, pnc_var%iNumberOfAttributes - 1
1777
1778 pnc_att => pnc_var%pNC_ATT(iindex2)
1779
1780 call nf_populate_attribute_struct( ncfile=ncfile, pnc_att=pnc_att, &
1781 inc_varid=iindex, iattnum=iindex2 )
1782
1783 enddo
1784
1785 endif
1786
1787 enddo
1788
1789 call nf_trap( nc_inq_natts(ncid=ncfile%iNCID, ngattsp=ncfile%iNumberOfAttributes), &
1790 __file__, __line__ )
1791
1792
1793 if (associated(ncfile%pNC_ATT) ) deallocate(ncfile%pNC_ATT, stat=istat)
1794 call assert(istat == 0, "Could not deallocate memory for NC_ATT member within NC_FILE defined type", &
1795 __file__, __line__)
1796
1797 allocate(ncfile%pNC_ATT(0:ncfile%iNumberOfAttributes - 1), stat=istat )
1798 call assert(istat == 0, "Could not allocate memory for NC_ATT member within NC_FILE defined type", &
1799 __file__, __line__)
1800
1801 do iindex=0, ncfile%iNumberOfAttributes - 1
1802 pnc_att => ncfile%pNC_ATT(iindex)
1803
1804 call nf_populate_attribute_struct( ncfile=ncfile, pnc_att=pnc_att, &
1805 inc_varid=nc_global, iattnum=iindex )
1806
1807 enddo
1808
1809end subroutine nf_populate_variable_struct
1810
1811!----------------------------------------------------------------------
1812
1813subroutine nf_populate_attribute_struct( NCFILE, pNC_ATT, iNC_VarID, iAttNum )
1814
1815 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
1816 type (T_NETCDF_ATTRIBUTE), pointer :: pNC_ATT
1817 integer (c_int) :: iNC_VarID
1818 integer (c_int) :: iAttNum
1819
1820 ![ LOCALS ]
1821 integer (c_int) :: iStat
1822 character (len=256) :: sVarName
1823 character (len=256) :: sAttName
1824 integer (c_int) :: iIndex
1825 integer (c_int) :: iLength
1826
1827 call nf_trap( nc_inq_attname(ncid=ncfile%iNCID, &
1828 varid=inc_varid, &
1829 attnum=iattnum, &
1830 name=sattname), __file__, __line__ )
1831
1832 pnc_att%sAttributeName = c_to_fortran_string(sattname)
1833
1834 call nf_trap( nc_inq_att(ncid=ncfile%iNCID, &
1835 varid=inc_varid, &
1836 name=sattname, &
1837 xtypep=pnc_att%iNC_AttType, &
1838 lenp=pnc_att%iNC_AttSize), __file__, __line__ )
1839
1840 ilength = pnc_att%iNC_AttSize
1841
1842 istat = 0
1843 allocate(pnc_att%sAttValue(0:ilength-1), stat=istat )
1844 call assert(istat==0, "INTERNAL PROGRAMMING ERROR - problem allocating memory", &
1845 __file__, __line__)
1846 pnc_att%sAttValue = ""
1847
1848 select case(pnc_att%iNC_AttType)
1849
1850 case (nc_char)
1851
1852 call nf_trap( nc_get_att_text(ncid=ncfile%iNCID, &
1853 varid=inc_varid, &
1854 name=sattname, &
1855 ip=pnc_att%sAttValue), __file__, __line__ )
1856
1857 pnc_att%sAttValue = c_to_fortran_string(pnc_att%sAttValue)
1858
1859 case (nc_short)
1860
1861 allocate(pnc_att%i2AttValue(0:ilength-1), stat=istat )
1862 call assert(istat==0, "INTERNAL PROGRAMMING ERROR - problem allocating memory", &
1863 __file__, __line__)
1864
1865
1866 call nf_trap( nc_get_att_short(ncid=ncfile%iNCID, &
1867 varid=inc_varid, &
1868 name=sattname, &
1869 ip=pnc_att%i2AttValue), __file__, __line__ )
1870
1871 do iindex=1,ubound(pnc_att%i2AttValue,1)
1872 pnc_att%sAttValue(iindex) = ascharacter(pnc_att%i2AttValue(iindex))
1873 enddo
1874
1875 case (nc_int)
1876
1877 allocate(pnc_att%iAttValue(0:ilength-1), stat=istat )
1878 call assert(istat==0, "INTERNAL PROGRAMMING ERROR - problem allocating memory", &
1879 __file__, __line__)
1880
1881 call nf_trap( nc_get_att_int(ncid=ncfile%iNCID, &
1882 varid=inc_varid, &
1883 name=sattname, &
1884 ip=pnc_att%iAttValue), __file__, __line__ )
1885
1886 do iindex=1,ubound(pnc_att%iAttValue,1)
1887 pnc_att%sAttValue(iindex) = ascharacter(pnc_att%iAttValue(iindex))
1888 enddo
1889
1890 case (nc_float)
1891
1892 allocate(pnc_att%rAttValue(0:ilength-1), stat=istat )
1893 call assert(istat==0, "INTERNAL PROGRAMMING ERROR - problem allocating memory", &
1894 __file__, __line__)
1895
1896
1897 call nf_trap( nc_get_att_float(ncid=ncfile%iNCID, &
1898 varid=inc_varid, &
1899 name=sattname, &
1900 ip=pnc_att%rAttValue), __file__, __line__ )
1901
1902 do iindex=1,ubound(pnc_att%rAttValue,1)
1903 pnc_att%sAttValue(iindex) = ascharacter(pnc_att%rAttValue(iindex))
1904 enddo
1905
1906 case (nc_double)
1907
1908 allocate(pnc_att%dpAttValue(0:ilength-1), stat=istat )
1909 call assert(istat==0, "INTERNAL PROGRAMMING ERROR - problem allocating memory", &
1910 __file__, __line__)
1911
1912 call nf_trap( nc_get_att_double(ncid=ncfile%iNCID, &
1913 varid=inc_varid, &
1914 name=sattname, &
1915 ip=pnc_att%dpAttValue), __file__, __line__ )
1916
1917 do iindex=1,ubound(pnc_att%dpAttValue,1)
1918 pnc_att%sAttValue(iindex) = ascharacter(pnc_att%dpAttValue(iindex))
1919 enddo
1920
1921 case default
1922
1923 end select
1924
1925end subroutine nf_populate_attribute_struct
1926
1927!----------------------------------------------------------------------
1928
1929
1930subroutine netcdf_get_variable_id_for_variable( NCFILE, variable_name, &
1931 variable_id )
1932
1933 type (t_netcdf4_file), intent(inout) :: ncfile
1934 character (len=*), intent(in) :: variable_name
1935 integer (c_int), intent(out) :: variable_id
1936
1937 ! [ LOCALS ]
1938 integer (c_int) :: indx
1939 type (t_netcdf_variable), pointer :: pnc_var
1940 logical (c_bool) :: variable_was_found
1941 character (len=256) :: tempstring
1942
1943 variable_was_found = false
1944
1945 do indx=0, ncfile%iNumberOfVariables-1
1946 pnc_var => ncfile%pNC_VAR( indx )
1947 if ( associated( pnc_var ) ) then
1948 if ( pnc_var%sVariableName .strequal. variable_name ) then
1949 variable_was_found = true
1950 exit
1951 endif
1952 endif
1953 enddo
1954
1955 if ( variable_was_found ) then
1956
1957 variable_id = pnc_var%iNC_VarID
1958
1959 else
1960
1961 variable_id = -9999
1962
1963 endif
1964
1966
1967!--------------------------------------------------------------------------------------------------
1968
1969subroutine netcdf_get_attribute_list_for_variable( NCFILE, variable_name, &
1970 attribute_name_list, &
1971 attribute_value_list )
1972
1973 type (t_netcdf4_file), intent(inout) :: ncfile
1974 character (len=*), intent(in) :: variable_name
1975 type (fstring_list_t), intent(out) :: attribute_name_list
1976 type (fstring_list_t), intent(out) :: attribute_value_list
1977
1978 ! [ LOCALS ]
1979 integer (c_int) :: indx
1980 type (t_netcdf_attribute), pointer :: pnc_att
1981 type (t_netcdf_variable), pointer :: pnc_var
1982 logical (c_bool) :: variable_was_found
1983 character (len=256) :: tempstring
1984
1985 variable_was_found = false
1986
1987 call attribute_name_list%clear
1988 call attribute_value_list%clear
1989
1990 do indx=0, ncfile%iNumberOfVariables-1
1991 pnc_var => ncfile%pNC_VAR( indx )
1992 if ( associated( pnc_var ) ) then
1993 if ( pnc_var%sVariableName .strequal. variable_name ) then
1994 variable_was_found = true
1995 exit
1996 endif
1997 endif
1998 enddo
1999
2000 if ( variable_was_found ) then
2001
2002 do indx=0, pnc_var%iNumberOfAttributes-1
2003 pnc_att => pnc_var%pNC_ATT( indx )
2004 if (associated( pnc_att) ) then
2005
2006 tempstring = pnc_att%sAttributeName
2007 call attribute_name_list%append( trim( tempstring ) )
2008
2009 select case ( pnc_att%iNC_AttType )
2010
2011 case ( nc_char )
2012
2013 tempstring = pnc_att%sAttValue(0)
2014 call attribute_value_list%append( trim( tempstring ) )
2015
2016 case ( nc_short )
2017
2018 tempstring = ascharacter( pnc_att%i2AttValue(0) )
2019 call attribute_value_list%append( trim( tempstring ) )
2020
2021 case ( nc_int )
2022
2023 tempstring = ascharacter( pnc_att%iAttValue(0) )
2024 call attribute_value_list%append( trim( tempstring ) )
2025
2026 case ( nc_float )
2027
2028 tempstring = ascharacter( pnc_att%rAttValue(0) )
2029 call attribute_value_list%append( trim( tempstring ) )
2030
2031 case ( nc_double )
2032
2033 tempstring = ascharacter( pnc_att%dpAttValue(0) )
2034 call attribute_value_list%append( trim( tempstring ) )
2035
2036 end select
2037
2038 endif
2039
2040 enddo
2041
2042 else
2043
2044 call attribute_name_list%append("<NA>")
2045 call attribute_value_list%append("<NA>")
2046
2047 endif
2048
2050
2051!----------------------------------------------------------------------
2052
2053subroutine netcdf_set_coordinate_tolerance(NCFILE, tolerance)
2054
2055 type (t_netcdf4_file) :: ncfile
2056 real (c_double), intent(in) :: tolerance
2057
2058 ncfile%rCoordinateTolerance = tolerance
2059
2061
2062!----------------------------------------------------------------------
2063
2064subroutine netcdf_get_variable_list( NCFILE, variable_list )
2065
2066 type (t_netcdf4_file) :: ncfile
2067 type (fstring_list_t) :: variable_list
2068
2069 ! [ LOCALS ]
2070 integer (c_int) :: indx
2071 type (t_netcdf_attribute), pointer :: pnc_att
2072 type (t_netcdf_variable), pointer :: pnc_var
2073
2074 call variable_list%clear
2075
2076 do indx=0, ncfile%iNumberOfVariables-1
2077 pnc_var => ncfile%pNC_VAR( indx )
2078 if ( associated( pnc_var ) ) call variable_list%append( pnc_var%sVariableName )
2079 enddo
2080
2081end subroutine netcdf_get_variable_list
2082
2083!----------------------------------------------------------------------
2084
2085function netcdf_update_time_starting_index(NCFILE, iJulianDay) result(lDateTimeFound)
2086
2087 type (t_netcdf4_file) :: ncfile
2088 integer (c_int) :: ijulianday
2089 logical (c_bool) :: ldatetimefound
2090
2091 ! [ LOCALS ]
2092 real (c_double) :: rnc_datetime
2093
2094 ncfile%iStart(nc_time) = nf_julian_day_to_index_adj( ncfile=ncfile, &
2095 rjulianday=real(ijulianday, c_double ) )
2096
2097 if (ncfile%iStart(nc_time) < 0) then
2098 ncfile%iStart(nc_time) = 0
2099 ldatetimefound = false
2100 else
2101 ldatetimefound = true
2102 endif
2103
2105
2106!----------------------------------------------------------------------
2107
2108subroutine netcdf_get_variable_slice(NCFILE, rValues, dpValues, iValues)
2109
2110 type (t_netcdf4_file), intent(inout) :: ncfile
2111 real (c_float), dimension(:,:), optional :: rvalues
2112 real (c_double), dimension(:,:), optional :: dpvalues
2113 integer (c_int), dimension(:,:), optional :: ivalues
2114
2115 real (c_float), allocatable :: rtempvals(:,:)
2116 integer (c_short), allocatable :: i2tempvals(:,:)
2117 integer (c_int), allocatable :: itempvals(:,:)
2118 real (c_double), allocatable :: dptempvals(:,:)
2119 integer (c_int) :: nrow, ncol
2120
2121 if (present( rvalues) ) then
2122 nrow = size(rvalues,2)
2123 ncol = size(rvalues,1)
2124 elseif (present( dpvalues) ) then
2125 nrow = size(dpvalues,2)
2126 ncol = size(dpvalues,1)
2127 elseif (present( ivalues) ) then
2128 nrow = size(ivalues,2)
2129 ncol = size(ivalues,1)
2130 else
2131 call die("Internal programming error: unhandled data type", &
2132 __file__, __line__)
2133 endif
2134
2135 if ( ncfile%iVarType(nc_z) == nc_short &
2136 .or. ncfile%iVarType(nc_z) == nc_ushort) then
2137
2138 allocate( i2tempvals(ncol, nrow))
2139
2140 call nf_get_variable_slice_short(ncfile, i2tempvals)
2141
2142 if (present(rvalues)) rvalues = asfloat(i2tempvals)
2143 if (present(ivalues)) ivalues = i2tempvals
2144 if (present(dpvalues)) dpvalues = asdouble(i2tempvals)
2145
2146 elseif ( ncfile%iVarType(nc_z) == nc_int &
2147 .or. ncfile%iVarType(nc_z) == nc_uint) then
2148
2149 allocate( itempvals(ncol, nrow))
2150 call nf_get_variable_slice_int(ncfile, itempvals)
2151
2152 if (present(rvalues)) rvalues = asfloat(itempvals)
2153 if (present(ivalues)) ivalues = itempvals
2154 if (present(dpvalues)) dpvalues = asdouble(itempvals)
2155
2156 elseif (ncfile%iVarType(nc_z) == nc_float) then
2157
2158 allocate( rtempvals(ncol, nrow))
2159 call nf_get_variable_slice_float(ncfile, rtempvals)
2160
2161 if (present(rvalues)) rvalues = rtempvals
2162 if (present(ivalues)) ivalues = asint(rtempvals)
2163 if (present(dpvalues)) dpvalues = asdouble(rtempvals)
2164
2165 elseif (ncfile%iVarType(nc_z) == nc_double) then
2166
2167 allocate( dptempvals(ncol, nrow))
2168 call nf_get_variable_slice_double(ncfile, dptempvals)
2169
2170 if (present(rvalues)) rvalues = asfloat(dptempvals)
2171 if (present(ivalues)) ivalues = asint(dptempvals)
2172 if (present(dpvalues)) dpvalues = dptempvals
2173
2174 else
2175
2176 call warn("Failed to find a method to retrieve data of the given type.", __file__, __line__)
2177
2178 print *, 'var type: ',ncfile%iVarType(nc_z)
2179
2180 endif
2181
2182end subroutine netcdf_get_variable_slice
2183
2184!----------------------------------------------------------------------
2185
2186subroutine nf_get_variable_slice_short(NCFILE, i2Values)
2187
2188 type (T_NETCDF4_FILE) :: NCFILE
2189 integer (c_short), intent(inout) :: i2Values(:,:)
2190
2191 ! [ LOCALS ]
2192 !! dimension #1 = column (iNX)
2193 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
2194
2195 integer (c_short), dimension(size(i2Values,2) * size(i2Values,1)) :: iTemp
2196
2197 integer (c_int) :: iStat
2198 integer (c_int) :: iRow, iCol, iIndex
2199 integer (c_int) :: iFromRow, iToRow, iByRow
2200 integer (c_int) :: iFromCol, iToCol, iByCol
2201
2202 ifromrow = ncfile%iRowIter(nc_first)
2203 itorow = ncfile%iRowIter(nc_last)
2204 ibyrow = ncfile%iRowIter(nc_by)
2205
2206 ifromcol = ncfile%iColIter(nc_first)
2207 itocol = ncfile%iColIter(nc_last)
2208 ibycol = ncfile%iColIter(nc_by)
2209
2210 pnc_var => ncfile%pNC_VAR(nf_return_varindex( ncfile, ncfile%iVarID(nc_z)) )
2211
2212 select case (ncfile%sVariableOrder)
2213
2214 case ("txy") ! time, col, row
2215
2216 call nf_get_variable_array_as_vector_short(ncfile=ncfile, &
2217 inc_varid=ncfile%iVarID(nc_z), &
2218 inc_start=[ncfile%iStart(nc_time), ncfile%iStart(nc_x), ncfile%iStart(nc_y)], &
2219 inc_count=[ncfile%iCount(nc_time), ncfile%iCount(nc_x), ncfile%iCount(nc_y)], &
2220 inc_stride=[ncfile%iStride(nc_time), ncfile%iStride(nc_x), ncfile%iStride(nc_y)], &
2221 inc_vars=itemp)
2222
2223 iindex = 0
2224 do icol=ifromcol, itocol, ibycol
2225 do irow=ifromrow, itorow, ibyrow
2226 iindex = iindex + 1
2227 i2values(icol,irow) = itemp(iindex)
2228 enddo
2229 enddo
2230
2231 case ("tyx") ! time, row, col
2232
2233 call nf_get_variable_array_as_vector_short(ncfile=ncfile, &
2234 inc_varid=ncfile%iVarID(nc_z), &
2235 inc_start=[ncfile%iStart(nc_time), ncfile%iStart(nc_y), ncfile%iStart(nc_x)], &
2236 inc_count=[ncfile%iCount(nc_time), ncfile%iCount(nc_y), ncfile%iCount(nc_x)], &
2237 inc_stride=[ncfile%iStride(nc_time), ncfile%iStride(nc_y), ncfile%iStride(nc_x)], &
2238 inc_vars=itemp)
2239
2240 iindex = 0
2241 do irow=ifromrow, itorow, ibyrow
2242 do icol=ifromcol, itocol, ibycol
2243 iindex = iindex + 1
2244 i2values(icol,irow) = itemp(iindex)
2245 enddo
2246 enddo
2247
2248 case default
2249
2250 call warn("INTERNAL PROGRAMMING ERROR: Unhandled select case. Program will probably fail.", __file__, __line__)
2251
2252 end select
2253
2254end subroutine nf_get_variable_slice_short
2255
2256!----------------------------------------------------------------------
2257
2258subroutine nf_get_variable_slice_int(NCFILE, iValues)
2259
2260 type (T_NETCDF4_FILE) :: NCFILE
2261 integer (c_int), dimension(:,:) :: iValues
2262
2263 ! [ LOCALS ]
2264 !! dimension #1 = column (iNX)
2265 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
2266
2267 integer (c_int), dimension(size(iValues,2) * size(iValues,1)) :: iTemp
2268
2269 integer (c_int) :: iStat
2270 integer (c_int) :: iRow, iCol, iIndex
2271 integer (c_int) :: iFromRow, iToRow, iByRow
2272 integer (c_int) :: iFromCol, iToCol, iByCol
2273
2274 ifromrow = ncfile%iRowIter(nc_first)
2275 itorow = ncfile%iRowIter(nc_last)
2276 ibyrow = ncfile%iRowIter(nc_by)
2277
2278 ifromcol = ncfile%iColIter(nc_first)
2279 itocol = ncfile%iColIter(nc_last)
2280 ibycol = ncfile%iColIter(nc_by)
2281
2282 pnc_var => ncfile%pNC_VAR(nf_return_varindex( ncfile, ncfile%iVarID(nc_z)) )
2283
2284 select case (ncfile%sVariableOrder)
2285
2286 case ("txy") ! time, col, row
2287
2288 call nf_get_variable_array_as_vector_int(ncfile=ncfile, &
2289 inc_varid=ncfile%iVarID(nc_z), &
2290 inc_start=[ncfile%iStart(nc_time), ncfile%iStart(nc_x), ncfile%iStart(nc_y)], &
2291 inc_count=[ncfile%iCount(nc_time), ncfile%iCount(nc_x), ncfile%iCount(nc_y)], &
2292 inc_stride=[ncfile%iStride(nc_time), ncfile%iStride(nc_x), ncfile%iStride(nc_y)], &
2293 inc_vars=itemp)
2294
2295 iindex = 0
2296 do icol=ifromcol, itocol, ibycol
2297 do irow=ifromrow, itorow, ibyrow
2298 iindex = iindex + 1
2299 ivalues(icol,irow) = itemp(iindex)
2300 enddo
2301 enddo
2302
2303 case ("tyx") ! time, row, col
2304
2305 call nf_get_variable_array_as_vector_int(ncfile=ncfile, &
2306 inc_varid=ncfile%iVarID(nc_z), &
2307 inc_start=[ncfile%iStart(nc_time), ncfile%iStart(nc_y), ncfile%iStart(nc_x)], &
2308 inc_count=[ncfile%iCount(nc_time), ncfile%iCount(nc_y), ncfile%iCount(nc_x)], &
2309 inc_stride=[ncfile%iStride(nc_time), ncfile%iStride(nc_y), ncfile%iStride(nc_x)], &
2310 inc_vars=itemp)
2311
2312 iindex = 0
2313 do irow=ifromrow, itorow, ibyrow
2314 do icol=ifromcol, itocol, ibycol
2315 iindex = iindex + 1
2316 ivalues(icol,irow) = itemp(iindex)
2317 enddo
2318 enddo
2319
2320 case default
2321
2322 call warn("INTERNAL PROGRAMMING ERROR: Unhandled select case. Program will probably fail.", __file__, __line__)
2323
2324
2325 end select
2326
2327end subroutine nf_get_variable_slice_int
2328
2329!----------------------------------------------------------------------
2330
2331subroutine nf_get_variable_slice_float(NCFILE, rValues)
2332
2333 type (T_NETCDF4_FILE) :: NCFILE
2334 real (c_float), dimension(:,:) :: rValues
2335
2336 ! [ LOCALS ]
2337 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
2338 real (c_float), dimension(size(rValues,2) * size(rValues,1)) :: rTemp
2339 integer (c_int) :: iStat
2340 integer (c_int) :: iRow, iCol, iIndex
2341 integer (c_int) :: iFromRow, iToRow, iByRow
2342 integer (c_int) :: iFromCol, iToCol, iByCol
2343
2344 ifromrow = ncfile%iRowIter(nc_first)
2345 itorow = ncfile%iRowIter(nc_last)
2346 ibyrow = ncfile%iRowIter(nc_by)
2347
2348 ifromcol = ncfile%iColIter(nc_first)
2349 itocol = ncfile%iColIter(nc_last)
2350 ibycol = ncfile%iColIter(nc_by)
2351
2352 pnc_var => ncfile%pNC_VAR(nf_return_varindex( ncfile, ncfile%iVarID(nc_z)) )
2353
2354 select case (ncfile%sVariableOrder)
2355
2356 case ("txy") ! time, col, row
2357
2358 call nf_get_variable_array_as_vector_float(ncfile=ncfile, &
2359 inc_varid=ncfile%iVarID(nc_z), &
2360 inc_start=[ncfile%iStart(nc_time), ncfile%iStart(nc_x), ncfile%iStart(nc_y)], &
2361 inc_count=[ncfile%iCount(nc_time), ncfile%iCount(nc_x), ncfile%iCount(nc_y)], &
2362 inc_stride=[ncfile%iStride(nc_time), ncfile%iStride(nc_x), ncfile%iStride(nc_y)], &
2363 rnc_vars=rtemp)
2364
2365 iindex = 0
2366 do icol=ifromcol, itocol, ibycol
2367 do irow=ifromrow, itorow, ibyrow
2368 iindex = iindex + 1
2369 rvalues(icol,irow) = rtemp(iindex)
2370 enddo
2371 enddo
2372
2373 case ("tyx") ! time, row, col
2374
2375 call nf_get_variable_array_as_vector_float(ncfile=ncfile, &
2376 inc_varid=ncfile%iVarID(nc_z), &
2377 inc_start=[ncfile%iStart(nc_time), ncfile%iStart(nc_y), ncfile%iStart(nc_x)], &
2378 inc_count=[ncfile%iCount(nc_time), ncfile%iCount(nc_y), ncfile%iCount(nc_x)], &
2379 inc_stride=[ncfile%iStride(nc_time), ncfile%iStride(nc_y), ncfile%iStride(nc_x)], &
2380 rnc_vars=rtemp)
2381
2382 iindex = 0
2383 do irow=ifromrow, itorow, ibyrow
2384 do icol=ifromcol, itocol, ibycol
2385 iindex = iindex + 1
2386 rvalues(icol,irow) = rtemp(iindex)
2387 enddo
2388 enddo
2389
2390 case default
2391
2392 call warn("INTERNAL PROGRAMMING ERROR: Unhandled select case. Program will probably fail.", __file__, __line__)
2393
2394 end select
2395
2396end subroutine nf_get_variable_slice_float
2397
2398!----------------------------------------------------------------------
2399
2400subroutine nf_get_variable_slice_double(NCFILE, dpValues)
2401
2402 type (T_NETCDF4_FILE) :: NCFILE
2403 real (c_double), dimension(:,:) :: dpValues
2404
2405 ! [ LOCALS ]
2406 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
2407 real (c_double), dimension(size(dpValues,2) * size(dpValues,1)) :: dpTemp
2408 integer (c_int) :: iStat
2409 integer (c_int) :: iRow, iCol, iIndex
2410 integer (c_int) :: iFromRow, iToRow, iByRow
2411 integer (c_int) :: iFromCol, iToCol, iByCol
2412
2413 ifromrow = ncfile%iRowIter(nc_first)
2414 itorow = ncfile%iRowIter(nc_last)
2415 ibyrow = ncfile%iRowIter(nc_by)
2416
2417 ifromcol = ncfile%iColIter(nc_first)
2418 itocol = ncfile%iColIter(nc_last)
2419 ibycol = ncfile%iColIter(nc_by)
2420
2421 pnc_var => ncfile%pNC_VAR(nf_return_varindex( ncfile, ncfile%iVarID(nc_z)) )
2422
2423 select case (ncfile%sVariableOrder)
2424
2425 case ("txy") ! time, col, row
2426
2427 call nf_get_variable_array_as_vector_double(ncfile=ncfile, &
2428 inc_varid=ncfile%iVarID(nc_z), &
2429 inc_start=[ncfile%iStart(nc_time), ncfile%iStart(nc_x), ncfile%iStart(nc_y)], &
2430 inc_count=[ncfile%iCount(nc_time), ncfile%iCount(nc_x), ncfile%iCount(nc_y)], &
2431 inc_stride=[ncfile%iStride(nc_time), ncfile%iStride(nc_x), ncfile%iStride(nc_y)], &
2432 dpnc_vars=dptemp)
2433
2434 iindex = 0
2435 do icol=ifromcol, itocol, ibycol
2436 do irow=ifromrow, itorow, ibyrow
2437 iindex = iindex + 1
2438 dpvalues(icol,irow) = dptemp(iindex)
2439 enddo
2440 enddo
2441
2442 case ("tyx") ! time, row, col
2443
2444 call nf_get_variable_array_as_vector_double(ncfile=ncfile, &
2445 inc_varid=ncfile%iVarID(nc_z), &
2446 inc_start=[ncfile%iStart(nc_time), ncfile%iStart(nc_y), ncfile%iStart(nc_x)], &
2447 inc_count=[ncfile%iCount(nc_time), ncfile%iCount(nc_y), ncfile%iCount(nc_x)], &
2448 inc_stride=[ncfile%iStride(nc_time), ncfile%iStride(nc_y), ncfile%iStride(nc_x)], &
2449 dpnc_vars=dptemp)
2450
2451 iindex = 0
2452 do irow=ifromrow, itorow, ibyrow
2453 do icol=ifromcol, itocol, ibycol
2454 iindex = iindex + 1
2455 dpvalues(icol,irow) = dptemp(iindex)
2456 enddo
2457 enddo
2458
2459 case default
2460
2461 call warn("INTERNAL PROGRAMMING ERROR: Unhandled select case. Program will probably fail.", __file__, __line__)
2462
2463 end select
2464
2465end subroutine nf_get_variable_slice_double
2466
2467!----------------------------------------------------------------------
2468
2469subroutine nf_get_variable_vector_short(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2470 iNC_Stride, iNC_Vars)
2471
2472 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2473 integer (c_int) :: iNC_VarID
2474 integer (c_size_t) :: iNC_Start
2475 integer (c_size_t) :: iNC_Count
2476 integer (c_size_t) :: iNC_Stride
2477 integer (c_short), dimension(:) :: iNC_Vars
2478
2479 call nf_trap(nc_get_vars_short(ncid=ncfile%iNCID, &
2480 varid=inc_varid, &
2481 startp=[inc_start], &
2482 countp=[inc_count], &
2483 stridep=[inc_stride], &
2484 vars=inc_vars), __file__, __line__ )
2485
2486end subroutine nf_get_variable_vector_short
2487
2488!----------------------------------------------------------------------
2489
2490subroutine nf_get_variable_array_short(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2491 iNC_Stride, iNC_Vars)
2492
2493 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2494 integer (c_int) :: iNC_VarID
2495 integer (c_size_t), dimension(:) :: iNC_Start
2496 integer (c_size_t), dimension(:) :: iNC_Count
2497 integer (c_size_t), dimension(:) :: iNC_Stride
2498 integer (c_short), dimension(:,:) :: iNC_Vars
2499
2500 call nf_trap(nc_get_vars_short(ncid=ncfile%iNCID, &
2501 varid=inc_varid, &
2502 startp=[inc_start], &
2503 countp=[inc_count], &
2504 stridep=[inc_stride], &
2505 vars=inc_vars), __file__, __line__ )
2506
2507end subroutine nf_get_variable_array_short
2508
2509!----------------------------------------------------------------------
2510
2511subroutine nf_get_variable_array_as_vector_short(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2512 iNC_Stride, iNC_Vars)
2513
2514 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2515 integer (c_int) :: iNC_VarID
2516 integer (c_size_t), dimension(:) :: iNC_Start
2517 integer (c_size_t), dimension(:) :: iNC_Count
2518 integer (c_size_t), dimension(:) :: iNC_Stride
2519 integer (c_short), dimension(:) :: iNC_Vars
2520
2521 call nf_trap(nc_get_vars_short(ncid=ncfile%iNCID, &
2522 varid=inc_varid, &
2523 startp=[inc_start], &
2524 countp=[inc_count], &
2525 stridep=[inc_stride], &
2526 vars=inc_vars), __file__, __line__ )
2527
2529
2530!----------------------------------------------------------------------
2531
2532subroutine nf_get_variable_array_as_vector_int(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2533 iNC_Stride, iNC_Vars)
2534
2535 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2536 integer (c_int) :: iNC_VarID
2537 integer (c_size_t), dimension(:) :: iNC_Start
2538 integer (c_size_t), dimension(:) :: iNC_Count
2539 integer (c_size_t), dimension(:) :: iNC_Stride
2540 integer (c_int), dimension(:) :: iNC_Vars
2541
2542 call nf_trap(nc_get_vars_int(ncid=ncfile%iNCID, &
2543 varid=inc_varid, &
2544 startp=[inc_start], &
2545 countp=[inc_count], &
2546 stridep=[inc_stride], &
2547 vars=inc_vars), __file__, __line__ )
2548
2550
2551!----------------------------------------------------------------------
2552
2553subroutine nf_get_variable_vector_int(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2554 iNC_Stride, iNC_Vars)
2555
2556 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2557 integer (c_int) :: iNC_VarID
2558 integer (c_size_t) :: iNC_Start
2559 integer (c_size_t) :: iNC_Count
2560 integer (c_size_t) :: iNC_Stride
2561 integer (c_int), dimension(:) :: iNC_Vars
2562
2563 call nf_trap(nc_get_vars_int(ncid=ncfile%iNCID, &
2564 varid=inc_varid, &
2565 startp=[inc_start], &
2566 countp=[inc_count], &
2567 stridep=[inc_stride], &
2568 vars=inc_vars), __file__, __line__ )
2569
2570end subroutine nf_get_variable_vector_int
2571
2572!----------------------------------------------------------------------
2573
2574subroutine nf_get_variable_vector_double(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2575 iNC_Stride, dpNC_Vars)
2576
2577 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2578 integer (c_int) :: iNC_VarID
2579 integer (c_size_t) :: iNC_Start
2580 integer (c_size_t) :: iNC_Count
2581 integer (c_size_t) :: iNC_Stride
2582 real (c_double), dimension(:) :: dpNC_Vars
2583
2584 call nf_trap(nc_get_vars_double(ncid=ncfile%iNCID, &
2585 varid=inc_varid, &
2586 startp=[inc_start], &
2587 countp=[inc_count], &
2588 stridep=[inc_stride], &
2589 vars=dpnc_vars), __file__, __line__ )
2590
2591end subroutine nf_get_variable_vector_double
2592
2593!----------------------------------------------------------------------
2594
2595subroutine nf_get_variable_array_double(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2596 iNC_Stride, dpNC_Vars)
2597
2598 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2599 integer (c_int) :: iNC_VarID
2600 integer (c_size_t), dimension(:) :: iNC_Start
2601 integer (c_size_t), dimension(:) :: iNC_Count
2602 integer (c_size_t), dimension(:) :: iNC_Stride
2603 real (c_double), dimension(:,:) :: dpNC_Vars
2604
2605 call nf_trap(nc_get_vars_double(ncid=ncfile%iNCID, &
2606 varid=inc_varid, &
2607 startp=[inc_start], &
2608 countp=[inc_count], &
2609 stridep=[inc_stride], &
2610 vars=dpnc_vars), __file__, __line__ )
2611
2612end subroutine nf_get_variable_array_double
2613
2614!----------------------------------------------------------------------
2615
2616subroutine nf_get_variable_array_as_vector_double(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2617 iNC_Stride, dpNC_Vars)
2618
2619 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2620 integer (c_int) :: iNC_VarID
2621 integer (c_size_t), dimension(:) :: iNC_Start
2622 integer (c_size_t), dimension(:) :: iNC_Count
2623 integer (c_size_t), dimension(:) :: iNC_Stride
2624 real (c_double), dimension(:) :: dpNC_Vars
2625
2626 call nf_trap(nc_get_vars_double(ncid=ncfile%iNCID, &
2627 varid=inc_varid, &
2628 startp=[inc_start], &
2629 countp=[inc_count], &
2630 stridep=[inc_stride], &
2631 vars=dpnc_vars), __file__, __line__ )
2632
2634
2635!----------------------------------------------------------------------
2636
2637subroutine nf_get_variable_vector_float(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2638 iNC_Stride, rNC_Vars )
2639
2640 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2641 integer (c_int) :: iNC_VarID
2642 integer (c_size_t) :: iNC_Start
2643 integer (c_size_t) :: iNC_Count
2644 integer (c_size_t) :: iNC_Stride
2645 real (c_float), dimension(:) :: rNC_Vars
2646
2647 call nf_trap(nc_get_vars_float(ncid=ncfile%iNCID, &
2648 varid=inc_varid, &
2649 startp=[inc_start], &
2650 countp=[inc_count], &
2651 stridep=[inc_stride], &
2652 vars=rnc_vars), __file__, __line__ )
2653
2654end subroutine nf_get_variable_vector_float
2655
2656!----------------------------------------------------------------------
2657
2658subroutine nf_get_variable_array_float(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2659 iNC_Stride, rNC_Vars )
2660
2661 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2662 integer (c_int) :: iNC_VarID
2663 integer (c_size_t), dimension(:) :: iNC_Start
2664 integer (c_size_t), dimension(:) :: iNC_Count
2665 integer (c_size_t), dimension(:) :: iNC_Stride
2666 real (c_float), dimension(:,:) :: rNC_Vars
2667
2668 call nf_trap(nc_get_vars_float(ncid=ncfile%iNCID, &
2669 varid=inc_varid, &
2670 startp=[inc_start], &
2671 countp=[inc_count], &
2672 stridep=[inc_stride], &
2673 vars=rnc_vars), __file__, __line__ )
2674
2675end subroutine nf_get_variable_array_float
2676
2677!----------------------------------------------------------------------
2678
2679subroutine nf_get_variable_array_as_vector_float(NCFILE, iNC_VarID, iNC_Start, iNC_Count, &
2680 iNC_Stride, rNC_Vars )
2681
2682 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2683 integer (c_int) :: iNC_VarID
2684 integer (c_size_t), dimension(:) :: iNC_Start
2685 integer (c_size_t), dimension(:) :: iNC_Count
2686 integer (c_size_t), dimension(:) :: iNC_Stride
2687 real (c_float), dimension(:) :: rNC_Vars
2688
2689 call nf_trap(nc_get_vars_float(ncid=ncfile%iNCID, &
2690 varid=inc_varid, &
2691 startp=[inc_start], &
2692 countp=[inc_count], &
2693 stridep=[inc_stride], &
2694 vars=rnc_vars), __file__, __line__ )
2695
2697
2698!----------------------------------------------------------------------
2699
2700subroutine netcdf_dump_cdl(NCFILE, iLU)
2701
2702 type (t_netcdf4_file ) :: ncfile
2703 type (t_netcdf_attribute), pointer :: pnc_att
2704 type (t_netcdf_variable), pointer :: pnc_var
2705 type (t_netcdf_dimension), pointer :: pnc_dim
2706 integer :: ilu
2707 character (len=256) :: sbuf, sbuf2
2708 character (len=256) :: sdimname
2709 integer (c_int) :: idimid
2710 integer (c_int) :: iubound
2711
2712 integer :: iresult, iindex, iindex2, iindex3, iindex4
2713
2714 sbuf=""; sbuf2=""
2715
2716 write(unit=ilu, fmt="(a)") "netcdf "//trim(ncfile%sFilename)//" {"
2717 write(unit=ilu, fmt="(a)") " dimensions:"
2718
2719 do iindex = 0, ncfile%iNumberOfDimensions - 1
2720 write(unit=ilu, fmt="(4x,a, ' = ', i0, ';')") trim(ncfile%pNC_DIM(iindex)%sDimensionName), &
2721 ncfile%pNC_DIM(iindex)%iNC_DimSize
2722 enddo
2723
2724 do iindex = 0, ncfile%iNumberOfVariables - 1
2725
2726 pnc_var => ncfile%pNC_VAR(iindex)
2727
2728 if(pnc_var%iNumberOfDimensions > 0) then
2729
2730 sbuf = ' ('
2731
2732 iubound = pnc_var%iNumberOfDimensions - 1
2733 do iindex3 = 0, iubound
2734
2735 idimid = pnc_var%iNC_DimID(iindex3)
2736
2737 call assert(idimid >=0 .and. &
2738 idimid <= ubound( ncfile%pNC_DIM, 1 ), &
2739 "INTERNAL PROGRAMMING ERROR -- iDimID out of bounds", &
2740 __file__, __line__)
2741
2742 pnc_dim => ncfile%pNC_DIM(idimid)
2743 sdimname = pnc_dim%sDimensionName
2744
2745 write(sbuf2, fmt="(i12)") pnc_dim%iNC_DimSize
2746 sbuf = trim(sbuf)//trim(pnc_dim%sDimensionName)//"=" &
2747 //trim(adjustl(sbuf2))
2748
2749 if (iindex3 /= iubound) sbuf = trim(sbuf)//", "
2750
2751 enddo
2752
2753 sbuf = trim(sbuf)//')'
2754
2755 else
2756
2757 sbuf = ""
2758
2759 endif
2760
2761 sbuf = trim(netcdf_data_type(pnc_var%iNC_VarType)) &
2762 //" "//trim(pnc_var%sVariableName)//sbuf//";"
2763
2764 write(unit=ilu, fmt="(2x,a)") trim(sbuf)
2765
2766 iubound = pnc_var%iNumberOfAttributes - 1
2767 do iindex3 = 0, iubound
2768
2769 pnc_att => ncfile%pNC_VAR(iindex)%pNC_ATT(iindex3)
2770
2771 sbuf = trim(pnc_var%sVariableName)//":"//trim(pnc_att%sAttributeName )//" ="
2772
2773 do iindex4=0, ubound(pnc_att%sAttValue, 1)
2774
2775 sbuf = trim(sbuf)//" "//trim(pnc_att%sAttValue(iindex4))
2776
2777 enddo
2778
2779 sbuf=trim(sbuf)//"; // "//trim(netcdf_data_type(pnc_att%iNC_AttType) )
2780
2781 write(unit=ilu, fmt="(4x,a)") trim(sbuf)
2782
2783 enddo
2784
2785 enddo
2786
2787 do iindex = 0, ncfile%iNumberOfAttributes - 1
2788
2789 pnc_att => ncfile%pNC_ATT(iindex)
2790
2791 sbuf = ":"//trim(pnc_att%sAttributeName )//" ="
2792
2793 do iindex4=0, ubound(pnc_att%sAttValue, 1)
2794
2795 sbuf = trim(sbuf)//" "//trim(pnc_att%sAttValue(iindex4))
2796
2797 enddo
2798
2799 sbuf=trim(sbuf)//"; // "//trim(netcdf_data_type(pnc_att%iNC_AttType) )
2800
2801 write(unit=ilu, fmt="(a)") trim(sbuf)
2802
2803 enddo
2804
2805 write(unit=ilu, fmt="(a,/,/)") "}"
2806
2807
2808end subroutine netcdf_dump_cdl
2809
2810!----------------------------------------------------------------------
2811
2812function nf_get_first_and_last(NCFILE, iVarIndex) result(dpValues)
2813
2814 type (t_netcdf4_file ) :: ncfile
2815 integer (c_int) :: ivarindex
2816 real (c_double), dimension(0:1) :: dpvalues
2817
2818 ! [ LOCALS ]
2819 type (t_netcdf_variable), pointer :: pnc_var
2820 type (t_netcdf_dimension), pointer :: pnc_dim
2821 integer (c_int) :: idimsize
2822 integer (c_int) :: idimindex
2823 integer (c_size_t) :: istride
2824 integer (c_size_t) :: icount
2825 integer (c_short), dimension(0:1) :: spvalues
2826 integer (c_int), dimension(0:1) :: ipvalues
2827 real (c_float), dimension(0:1) :: rpvalues
2828
2829 call assert (ivarindex >= lbound(ncfile%pNC_VAR,1) &
2830 .and. ivarindex <= ubound(ncfile%pNC_VAR,1), &
2831 "INTERNAL PROGRAMMING ERROR - index out of bounds NC_FILE%pNC_VAR" &
2832 //"~Offending index value: "//trim(ascharacter(ivarindex)), &
2833 __file__, __line__)
2834
2835 pnc_var => ncfile%pNC_VAR(ivarindex)
2836 idimsize = nf_return_dimsize(ncfile, pnc_var%iNC_DimID(0) )
2837
2838 if (idimsize > 1) then
2839 icount = 2_c_size_t
2840 istride = int(idimsize, c_size_t) - 1_c_size_t
2841 else
2842 icount = 1_c_size_t
2843 istride = 1_c_size_t
2844 endif
2845
2846 select case (pnc_var%iNC_VarType )
2847
2848 case (nc_short)
2849
2850 call nf_get_variable_vector_short(ncfile=ncfile, &
2851 inc_varid=pnc_var%iNC_VarID, &
2852 inc_start=0_c_size_t, &
2853 inc_count=icount, &
2854 inc_stride=istride, &
2855 inc_vars=spvalues)
2856
2857 dpvalues = real(spvalues, c_double)
2858
2859 case (nc_int)
2860
2861 call nf_get_variable_vector_int(ncfile=ncfile, &
2862 inc_varid=pnc_var%iNC_VarID, &
2863 inc_start=0_c_size_t, &
2864 inc_count=icount, &
2865 inc_stride=istride, &
2866 inc_vars=ipvalues)
2867
2868 dpvalues = real(ipvalues, c_double)
2869
2870 case (nc_float)
2871
2872 call nf_get_variable_vector_float(ncfile=ncfile, &
2873 inc_varid=pnc_var%iNC_VarID, &
2874 inc_start=0_c_size_t, &
2875 inc_count=icount, &
2876 inc_stride=istride, &
2877 rnc_vars=rpvalues)
2878
2879 dpvalues = real(rpvalues, c_double)
2880
2881 case (nc_double)
2882
2883 call nf_get_variable_vector_double(ncfile=ncfile, &
2884 inc_varid=pnc_var%iNC_VarID, &
2885 inc_start=0_c_size_t, &
2886 inc_count=icount, &
2887 inc_stride=istride, &
2888 dpnc_vars=dpvalues)
2889
2890 case default
2891
2892 call warn("INTERNAL PROGRAMMING ERROR: Unhandled select case. Program will probably fail.", __file__, __line__)
2893
2894 end select
2895
2896 !> if there is only one day of data in this netCDF file, the
2897 !> first day equals the last day
2898 if (icount == 1) dpvalues(nc_last) = dpvalues(nc_first)
2899
2900end function nf_get_first_and_last
2901
2902!----------------------------------------------------------------------
2903
2904subroutine nf_calculate_time_range(NCFILE)
2905
2906 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2907
2908 ncfile%iOriginJD = julian_day(ncfile%iOriginYear, &
2909 ncfile%iOriginMonth, ncfile%iOriginDay)
2910
2911 ncfile%iFirstDayJD = ncfile%iOriginJD + ncfile%dpFirstAndLastTimeValues(nc_first)
2912 ncfile%iLastDayJD = ncfile%iOriginJD + ncfile%dpFirstAndLastTimeValues(nc_last)
2913
2914end subroutine nf_calculate_time_range
2915
2916!----------------------------------------------------------------------
2917
2918subroutine nf_get_time_units(NCFILE)
2919
2920 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2921
2922 ! [ LOCALS ]
2923 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
2924 character (len=256) :: sDateTime
2925 character (len=256) :: sItem
2926 integer (c_int) :: iIndex
2927 logical (c_bool) :: lFound
2928 integer (c_int) :: iStat
2929 real (c_float) :: fTempVal
2930
2931 call assert(ncfile%iVarID(nc_time) >= 0, "INTERNAL PROGRAMMING ERROR -- " &
2932 //"nf_get_time_units must be called only after a call is made to ~" &
2933 //"netcdf_get_variable_ids", __file__, __line__)
2934
2935 pnc_var => ncfile%pNC_VAR(ncfile%iVarID(nc_time) )
2936
2937 lfound = false
2938
2939 do iindex=0, pnc_var%iNumberOfAttributes - 1
2940
2941 if ( pnc_var%pNC_ATT(iindex)%sAttributeName .strequal. "units" ) then
2942 lfound = true
2943 exit
2944 endif
2945
2946 enddo
2947
2948 call assert (lfound, "Failed to find the 'units' attribute associated " &
2949 //"with time variable "//dquote(pnc_var%sVariableName), &
2950 __file__, __line__)
2951
2952 sdatetime = pnc_var%pNC_ATT(iindex)%sAttValue(0)
2953
2954 call chomp(sdatetime, sitem) ! should be "days"
2955 call chomp(sdatetime, sitem) ! should be "since"
2956
2957 call chomp(sdatetime, sitem, "/-")
2958 read(sitem, *) ncfile%iOriginYear
2959
2960 call chomp(sdatetime, sitem, "/-")
2961 read(sitem, *) ncfile%iOriginMonth
2962
2963 !> @todo this does not appear to have the fix that was applied to the master swb branch to
2964 !! deal with cases where no time values are given at all
2965
2966 read(sdatetime, *) ncfile%iOriginDay
2967
2968 call chomp(sdatetime, sitem, ":")
2969 read(sitem, *, iostat=istat) ncfile%iOriginHH
2970 if (istat /=0) ncfile%iOriginHH = 0
2971
2972 call chomp(sdatetime, sitem, ":")
2973 read(sitem, *, iostat=istat) ncfile%iOriginMM
2974 if (istat /=0) ncfile%iOriginMM = 0
2975
2976 ! changed this to a real value, since some data providers encode the date and
2977 ! time as YYYY-MM-DD HH-MM-SS.S
2978 read(sdatetime, *, iostat=istat) ftempval
2979 if (istat ==0) then
2980 ncfile%iOriginSS = int(ftempval, c_int)
2981 else
2982 ncfile%iOriginSS = 0
2983 endif
2984
2985end subroutine nf_get_time_units
2986
2987!----------------------------------------------------------------------
2988
2989subroutine nf_get_xyz_units(NCFILE)
2990
2991 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
2992
2993 ! [ LOCALS ]
2994 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
2995 integer (c_int) :: iIndex, iIndex2
2996 logical (c_bool) :: lFound
2997 integer (c_int) :: iStat
2998
2999 do iindex = nc_y, nc_z
3000
3001 call assert(ncfile%iVarID(iindex) >= 0, "INTERNAL PROGRAMMING ERROR -- " &
3002 //"nc_get_XYZ_units must be called only after a call is made to ~" &
3003 //"netcdf_get_variable_ids", __file__, __line__)
3004
3005 pnc_var => ncfile%pNC_VAR(ncfile%iVarID(iindex) )
3006
3007 lfound = false
3008
3009 do iindex2=0, pnc_var%iNumberOfAttributes - 1
3010
3011 if ( pnc_var%pNC_ATT(iindex2)%sAttributeName .strequal. "units" ) then
3012 lfound = true
3013 exit
3014 endif
3015
3016 enddo
3017
3018 if (lfound) then
3019 ncfile%sVarUnits(iindex) = trim(pnc_var%pNC_ATT(iindex2)%sAttValue(0))
3020 endif
3021
3022 enddo
3023
3024end subroutine nf_get_xyz_units
3025
3026!----------------------------------------------------------------------
3027
3028subroutine nf_get_scale_and_offset(NCFILE)
3029
3030 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
3031
3032 ! [ LOCALS ]
3033 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
3034 integer (c_int) :: iIndex
3035 logical (c_bool) :: lFound
3036 integer (c_int) :: iStat
3037 character (len=32) :: sBuf
3038
3039 pnc_var => ncfile%pNC_VAR(ncfile%iVarID(nc_z) )
3040
3041 lfound = false
3042
3043 do iindex=0, pnc_var%iNumberOfAttributes - 1
3044
3045 if ( pnc_var%pNC_ATT(iindex)%sAttributeName .strequal. "scale_factor" ) then
3046 lfound = true
3047 exit
3048 endif
3049
3050 enddo
3051
3052 if (lfound) then
3053 if (allocated( pnc_var%pNC_ATT(iindex)%i2AttValue )) then
3054 ncfile%rScaleFactor(nc_z) = asfloat( pnc_var%pNC_ATT(iindex)%i2AttValue(0) )
3055 elseif (allocated( pnc_var%pNC_ATT(iindex)%iAttValue )) then
3056 ncfile%rScaleFactor(nc_z) = asfloat( pnc_var%pNC_ATT(iindex)%iAttValue(0) )
3057 elseif (allocated( pnc_var%pNC_ATT(iindex)%rAttValue )) then
3058 ncfile%rScaleFactor(nc_z) = pnc_var%pNC_ATT(iindex)%rAttValue(0)
3059 elseif (allocated( pnc_var%pNC_ATT(iindex)%dpAttValue )) then
3060 ncfile%rScaleFactor(nc_z) = asfloat( pnc_var%pNC_ATT(iindex)%dpAttValue(0) )
3061 elseif (len_trim(pnc_var%pNC_ATT(iindex)%sAttValue(0)) > 0) then
3062 sbuf = trim(pnc_var%pNC_ATT(iindex)%sAttValue(0) )
3063 read(sbuf,*) ncfile%rScaleFactor(nc_z)
3064 else
3065 call die("Error reading the 'scale_factor' attribute from the netCDF file" &
3066 //dquote(ncfile%sFilename))
3067 endif
3068 endif
3069
3070 !> Now repeat the process for "add_offset" attribute
3071 lfound = false
3072
3073 do iindex=0, pnc_var%iNumberOfAttributes - 1
3074
3075 if ( pnc_var%pNC_ATT(iindex)%sAttributeName .strequal. "add_offset" ) then
3076 lfound = true
3077 exit
3078 endif
3079
3080 enddo
3081
3082 if (lfound) then
3083 if (allocated( pnc_var%pNC_ATT(iindex)%i2AttValue )) then
3084 ncfile%rAddOffset(nc_z) = asfloat( pnc_var%pNC_ATT(iindex)%i2AttValue(0) )
3085 elseif (allocated( pnc_var%pNC_ATT(iindex)%iAttValue )) then
3086 ncfile%rAddOffset(nc_z) = asfloat( pnc_var%pNC_ATT(iindex)%iAttValue(0) )
3087 elseif (allocated( pnc_var%pNC_ATT(iindex)%rAttValue )) then
3088 ncfile%rAddOffset(nc_z) = pnc_var%pNC_ATT(iindex)%rAttValue(0)
3089 elseif (allocated( pnc_var%pNC_ATT(iindex)%dpAttValue )) then
3090 ncfile%rAddOffset(nc_z) = asfloat( pnc_var%pNC_ATT(iindex)%dpAttValue(0) )
3091 elseif (len_trim(pnc_var%pNC_ATT(iindex)%sAttValue(0)) > 0) then
3092 sbuf = trim(pnc_var%pNC_ATT(iindex)%sAttValue(0) )
3093 read(sbuf,*) ncfile%rAddOffset(nc_z)
3094 else
3095 call die("Error reading the 'add_offset' attribute from the netCDF file" &
3096 //dquote(ncfile%sFilename))
3097 endif
3098 endif
3099
3100end subroutine nf_get_scale_and_offset
3101
3102!----------------------------------------------------------------------
3103
3104subroutine nf_get_variable_id_and_type( NCFILE, strict_asserts )
3105 type (T_NETCDF4_FILE), intent(inout) :: NCFILE
3106 logical (c_bool), intent(in), optional :: strict_asserts
3107
3108 ! [ LOCALS ]
3109 integer (c_int) :: iIndex
3110 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
3111 logical (c_bool) :: strict_asserts_l
3112
3113 if ( present( strict_asserts ) ) then
3114 strict_asserts_l = strict_asserts
3115 else
3116 strict_asserts_l = true
3117 endif
3118
3119 ncfile%iVarID = -9999
3120
3121 do iindex=0, ncfile%iNumberOfVariables - 1
3122
3123 pnc_var => ncfile%pNC_VAR(iindex)
3124
3125 if ( pnc_var%sVariableName .strequal. ncfile%sVarName(nc_x) ) then
3126 ncfile%iVarIndex(nc_x) = iindex
3127 ncfile%iVarID(nc_x) = pnc_var%iNC_VarID
3128 ncfile%iVarType(nc_x) = pnc_var%iNC_VarType
3129 ncfile%iVar_DimID(nc_x,:) = pnc_var%iNC_DimID
3130
3131 elseif ( pnc_var%sVariableName .strequal. ncfile%sVarName(nc_y) ) then
3132 ncfile%iVarIndex(nc_y) = iindex
3133 ncfile%iVarID(nc_y) = pnc_var%iNC_VarID
3134 ncfile%iVarType(nc_y) = pnc_var%iNC_VarType
3135 ncfile%iVar_DimID(nc_y,:) = pnc_var%iNC_DimID
3136
3137 elseif ( pnc_var%sVariableName .strequal. ncfile%sVarName(nc_z) ) then
3138 ncfile%iVarIndex(nc_z) = iindex
3139 ncfile%iVarID(nc_z) = pnc_var%iNC_VarID
3140 ncfile%iVarType(nc_z) = pnc_var%iNC_VarType
3141 ncfile%iVar_DimID(nc_z,:) = pnc_var%iNC_DimID
3142
3143 elseif ( pnc_var%sVariableName .strequal. ncfile%sVarName(nc_time) ) then
3144 ncfile%iVarIndex(nc_time) = iindex
3145 ncfile%iVarID(nc_time) = pnc_var%iNC_VarID
3146 ncfile%iVarType(nc_time) = pnc_var%iNC_VarType
3147 ncfile%iVar_DimID(nc_time,:) = pnc_var%iNC_DimID
3148 endif
3149
3150 enddo
3151
3152 if ( strict_asserts_l ) then
3153
3154 call assert(ncfile%iVarID(nc_x) >= 0, &
3155 "Unable to find the variable named "//dquote(ncfile%sVarName(nc_x) )//" in " &
3156 //"file "//dquote(ncfile%sFilename), __file__, __line__)
3157
3158 call assert(ncfile%iVarID(nc_y) >= 0, &
3159 "Unable to find the variable named "//dquote(ncfile%sVarName(nc_y))//" in " &
3160 //"file "//dquote(ncfile%sFilename), __file__, __line__)
3161
3162 call assert(ncfile%iVarID(nc_z) >= 0, &
3163 "Unable to find the variable named "//dquote(ncfile%sVarName(nc_z))//" in " &
3164 //"file "//dquote(ncfile%sFilename), __file__, __line__)
3165
3166 if ( ncfile%iVarID(nc_time) < 0 ) &
3167 call warn("Unable to find the variable named "//dquote(ncfile%sVarName(nc_time))//" in " &
3168 //"file "//dquote(ncfile%sFilename) )
3169
3170 endif
3171
3172end subroutine nf_get_variable_id_and_type
3173
3174!----------------------------------------------------------------------
3175
3176function nf_return_index_double(rValues, rTargetValue, rOffsetValue) result(iIndex)
3177
3178 real (c_double), dimension(:) :: rvalues
3179 real (c_double) :: rtargetvalue
3180 real (c_double) :: roffsetvalue
3181 integer (c_int) :: iindex
3182
3183 ! [ LOCALS ]
3184 integer (c_int) :: icount
3185 real (c_double) :: rdiff, rdiffmin
3186
3187 ! attempting to account for the fact that coordinates are specified
3188 ! initially relative toi cell edges, but are stored internally within netCDF
3189 ! relative to cell centers
3190 if ( .not. (rtargetvalue >= (minval(rvalues) - roffsetvalue) ) &
3191 .and. (rtargetvalue <= (maxval(rvalues) + roffsetvalue) ) ) then
3192 call logs%write("rTargetValue (" &
3193 //trim(ascharacter(rtargetvalue))//") is not within the range " &
3194 //trim(ascharacter(minval(rvalues)))//" to "//trim(ascharacter(maxval(rvalues))), lecho=true )
3195
3196 call assert(false, "INTERNAL PROGRAMMING ERROR", __file__, __line__)
3197 endif
3198
3199 rdiffmin = 1.e+20
3200
3201 do icount=lbound(rvalues,1), ubound(rvalues,1)
3202
3203 rdiff = abs(rvalues(icount) - rtargetvalue)
3204
3205 if ( rdiff < rdiffmin ) then
3206 iindex = icount
3207 rdiffmin =rdiff
3208 endif
3209
3210 enddo
3211
3212! print *, trim(__FILE__), ": ", __LINE__
3213! print *, "index: ", iIndex, " value: ", rValues(iIndex), &
3214! " target value: ", rTargetValue
3215
3216end function nf_return_index_double
3217
3218!----------------------------------------------------------------------
3219
3220function netcdf_coord_to_col_row(NCFILE, rX, rY) result(iColRow)
3221
3222 type (t_netcdf4_file ) :: ncfile
3223 real (c_double) :: rx
3224 real (c_double) :: ry
3225 integer (c_size_t), dimension(2) :: icolrow
3226
3227 ! [ LOCALS ]
3228 integer (c_int) :: icolnum, irownum
3229 real (c_double) :: x_offset
3230 real (c_double) :: y_offset
3231
3232 x_offset = ncfile%rGridCellSizeX / 2.0_c_double + ncfile%rCoordinateTolerance
3233 y_offset = ncfile%rGridCellSizeY / 2.0_c_double + ncfile%rCoordinateTolerance
3234
3235 call assert( allocated( ncfile%rX_Coords ), "Internal programming error -- attempt " &
3236 //"to access unallocated array rX_Coords.", __file__, __line__ )
3237
3238 if (rx < (minval(ncfile%rX_Coords) - x_offset) ) &
3239 call die( "X coordinate value "//ascharacter(rx)//" is less than the minimum X coordinate " &
3240 //"value ("//ascharacter(minval(ncfile%rX_Coords)-x_offset)//") contained in the netCDF file " &
3241 //dquote(ncfile%sFilename), trim(__file__), __line__ )
3242
3243 if (rx > (maxval(ncfile%rX_Coords) + x_offset) ) &
3244 call die( "X coordinate value "//ascharacter(rx)//" is greater than the maximum X coordinate " &
3245 //"value ("//ascharacter(maxval(ncfile%rX_Coords)+x_offset)//") contained in the netCDF file " &
3246 //dquote(ncfile%sFilename), trim(__file__), __line__ )
3247
3248 if (ry < (minval(ncfile%rY_Coords) - y_offset) ) &
3249 call die( "Y coordinate value "//ascharacter(ry)//" is less than the minimum Y coordinate " &
3250 //"value ("//ascharacter(minval(ncfile%rY_Coords)-y_offset)//") contained in the netCDF file " &
3251 //dquote(ncfile%sFilename), trim(__file__), __line__ )
3252
3253 if (ry > (maxval(ncfile%rY_Coords) + y_offset) ) &
3254 call die( "Y coordinate value "//ascharacter(ry)//" is greater than the maximum Y coordinate " &
3255 //"value ("//ascharacter(maxval(ncfile%rY_Coords)+y_offset)//") contained in the netCDF file " &
3256 //dquote(ncfile%sFilename), trim(__file__), __line__ )
3257
3258 icolnum = nf_return_index_double(ncfile%rX_Coords, rx, x_offset)
3259 irownum = nf_return_index_double(ncfile%rY_Coords, ry, y_offset)
3260
3261 icolrow(column) = icolnum
3262 icolrow(row) = irownum
3263
3264end function netcdf_coord_to_col_row
3265
3266!----------------------------------------------------------------------
3267
3268function nf_get_varid(NCFILE, sVariableName) result(iNC_VarID)
3269
3270 type (t_netcdf4_file ) :: ncfile
3271 character (len=*) :: svariablename
3272 integer (c_int) :: inc_varid
3273
3274 integer (c_int) :: iindex
3275 type (t_netcdf_variable), pointer :: pnc_var
3276
3277 inc_varid = -9999
3278
3279 do iindex=0, ncfile%iNumberOfVariables - 1
3280
3281 pnc_var => ncfile%pNC_VAR(iindex)
3282
3283 if(trim(svariablename) .eq. trim(pnc_var%sVariableName) ) then
3284
3285 inc_varid = iindex
3286 exit
3287
3288 endif
3289
3290 enddo
3291
3292end function nf_get_varid
3293
3294!----------------------------------------------------------------------
3295
3296subroutine nf_create(NCFILE, sFilename, iLU)
3297
3298 type (T_NETCDF4_FILE ) :: NCFILE
3299 character (len=*) :: sFilename
3300 integer (c_int), optional :: iLU
3301
3302 call nf_trap(nc_create(path=trim(fortran_to_c_string(sfilename)), &
3303 cmode=nc_netcdf4, &
3304 ncidp=ncfile%iNCID), &
3305 __file__, __line__)
3306
3307!
3308! had read somewhere that the interface:
3309! character (c_char) :: varname(*)
3310!
3311! would properly pass fortran string to c; however,
3312! this does not appear ot be the case.
3313!
3314
3315! call nf_trap(nc_create(path=trim(sFilename), &
3316! cmode=NC_NETCDF4, &
3317! ncidp=NCFILE%iNCID), &
3318! __FILE__, __LINE__)
3319
3320
3321 ncfile%sFilename = trim(sfilename)
3322 ncfile%iFileFormat = nc_format_netcdf4
3323
3324 if (present(ilu) ) then
3325 call logs%write("Created netCDF file for output. Filename: " &
3326 //dquote(ncfile%sFilename)//"; NCID="//trim(ascharacter(ncfile%iNCID) ) )
3327 endif
3328
3329end subroutine nf_create
3330
3331!----------------------------------------------------------------------
3332
3333subroutine nf_define_deflate(NCFILE, iVarID, iShuffle, iDeflate, iDeflate_level)
3334
3335 type (T_NETCDF4_FILE ) :: NCFILE
3336 integer (c_int) :: iVarID
3337 integer (c_int) :: iShuffle
3338 integer (c_int) :: iDeflate
3339 integer (c_int) :: iDeflate_level
3340
3341 call nf_trap(nc_def_var_deflate(ncid=ncfile%iNCID, &
3342 varid=ivarid, &
3343 shuffle=ishuffle, &
3344 deflate=ideflate, &
3345 deflate_level=ideflate_level), &
3346 __file__, __line__)
3347
3348end subroutine nf_define_deflate
3349
3350!----------------------------------------------------------------------
3351
3352subroutine nf_enddef(NCFILE)
3353
3354 type (T_NETCDF4_FILE ) :: NCFILE
3355
3356 call nf_trap(nc_enddef(ncid=ncfile%iNCID), &
3357 __file__, __line__)
3358
3359end subroutine nf_enddef
3360
3361!----------------------------------------------------------------------
3362
3363subroutine nf_redef(NCFILE)
3364
3365 type (T_NETCDF4_FILE ) :: NCFILE
3366
3367 call nf_trap(nc_redef(ncid=ncfile%iNCID), &
3368 __file__, __line__)
3369
3370end subroutine nf_redef
3371
3372!----------------------------------------------------------------------
3373
3374subroutine nf_define_dimension(NCFILE, sDimensionName, iDimensionSize)
3375
3376 type (T_NETCDF4_FILE ) :: NCFILE
3377 character (len=*) :: sDimensionName
3378 integer (c_int) :: iDimensionSize
3379 integer (c_int) :: iDimID
3380
3381 integer (c_size_t) :: iDimSize
3382 type (T_NETCDF_DIMENSION), pointer :: pNC_DIM
3383
3384 idimsize = int(idimensionsize, c_size_t)
3385
3386 call nf_trap(nc_def_dim(ncid=ncfile%iNCID, &
3387 name=trim(sdimensionname)//c_null_char, &
3388 lenv=idimsize, &
3389 dimidp=idimid), &
3390 __file__, __line__)
3391
3392end subroutine nf_define_dimension
3393
3394!----------------------------------------------------------------------
3395
3396subroutine nf_delete_attribute(NCFILE, sVariableName, sAttributeName)
3397
3398 type (T_NETCDF4_FILE ) :: NCFILE
3399 character (len=*) :: sVariableName
3400 character (len=*) :: sAttributeName
3401
3402 integer (c_int) :: iVarID
3403
3404 ivarid = nf_get_varid(ncfile, svariablename//c_null_char)
3405
3406 call nf_trap(nc_del_att(ncid=ncfile%iNCID, &
3407 varid=ivarid, &
3408 name=trim(sattributename)//c_null_char), &
3409 __file__, __line__)
3410
3411end subroutine nf_delete_attribute
3412
3413!----------------------------------------------------------------------
3414
3415subroutine nf_define_dimensions( NCFILE )
3416
3417 type (T_NETCDF4_FILE) :: NCFILE
3418
3419 ! [ LOCALS ]
3420 integer (c_int) :: iStat
3421 integer (c_int) :: iIndex
3422 character (len=256) :: sDimName
3423 type (T_NETCDF_DIMENSION), pointer :: pNC_DIM
3424
3425 do iindex = 0, ncfile%iNumberOfDimensions-1
3426
3427 pnc_dim => ncfile%pNC_DIM(iindex)
3428
3429 call nf_trap(nc_def_dim(ncid=ncfile%iNCID, &
3430 name=trim(pnc_dim%sDimensionName)//c_null_char, &
3431 lenv=pnc_dim%iNC_DimSize, &
3432 dimidp=pnc_dim%iNC_DimID), &
3433 __file__, __line__ )
3434
3435 enddo
3436
3437end subroutine nf_define_dimensions
3438
3439!----------------------------------------------------------------------
3440
3441subroutine nf_set_standard_dimensions(NCFILE, iNX, iNY, write_time_bounds )
3442
3443 type (T_NETCDF4_FILE ) :: NCFILE
3444 integer (c_int) :: iNX
3445 integer (c_int) :: iNY
3446 logical (c_bool), optional :: write_time_bounds
3447
3448 ! [ LOCALS ]
3449 integer (c_int) :: iStat
3450 logical (c_bool) :: write_time_bounds_l
3451
3452 istat = 0
3453
3454 ncfile%iNumberOfDimensions = 3
3455
3456 if ( present( write_time_bounds ) ) then
3457
3458 write_time_bounds_l = write_time_bounds
3459
3460 else
3461
3462 write_time_bounds_l = false
3463
3464 endif
3465
3466 if ( write_time_bounds_l ) ncfile%iNumberOfDimensions = 4
3467
3468 if (associated(ncfile%pNC_DIM) ) deallocate(ncfile%pNC_DIM, stat=istat)
3469 call assert(istat == 0, "Could not deallocate memory for NC_DIM member in NC_FILE defined type", &
3470 __file__, __line__)
3471
3472 allocate(ncfile%pNC_DIM( 0 : ncfile%iNumberOfDimensions-1), stat=istat )
3473 call assert(istat == 0, "Could not allocate memory for NC_DIM member in NC_FILE defined type", &
3474 __file__, __line__)
3475
3476 !> define the time dimension;
3477 ncfile%pNC_DIM(nc_time)%sDimensionName = "time"
3478 ncfile%pNC_DIM(nc_time)%iNC_DimSize = nc_unlimited
3479
3480 !> define the y dimension;
3481 ncfile%pNC_DIM(nc_y)%sDimensionName = "y"
3482 ncfile%pNC_DIM(nc_y)%iNC_DimSize = iny
3483
3484 !> define the x dimension;
3485 ncfile%pNC_DIM(nc_x)%sDimensionName = "x"
3486 ncfile%pNC_DIM(nc_x)%iNC_DimSize = inx
3487
3488 if ( write_time_bounds_l ) then
3489 !> define the auxiliary dimension;
3490 ncfile%pNC_DIM(nc_aux)%sDimensionName = "nv"
3491 ncfile%pNC_DIM(nc_aux)%iNC_DimSize = 2
3492 endif
3493
3494end subroutine nf_set_standard_dimensions
3495
3496!----------------------------------------------------------------------
3497
3498subroutine nf_set_standard_variables(NCFILE, sVarName_z, lLatLon, write_time_bounds )
3499
3500 type (T_NETCDF4_FILE ) :: NCFILE
3501 character (len=*) :: sVarName_z
3502 logical (c_bool), optional :: lLatLon
3503 logical (c_bool), optional :: write_time_bounds
3504
3505 ! [ LOCALS ]
3506 integer (c_int) :: iStat
3507 logical (c_bool) :: lLatLon_l
3508 logical (c_bool) :: write_time_bounds_l
3509
3510 if (present( llatlon) ) then
3511 llatlon_l = llatlon
3512 else
3513 llatlon_l = false
3514 endif
3515
3516 if (present(write_time_bounds) ) then
3517 write_time_bounds_l = write_time_bounds
3518 else
3519 write_time_bounds_l = false
3520 endif
3521
3522 istat = 0
3523
3524 ncfile%iNumberOfVariables = 5
3525
3526 if ( llatlon_l ) ncfile%iNumberOfVariables = 7
3527 if ( write_time_bounds_l ) ncfile%iNumberOfVariables = &
3528 ncfile%iNumberOfVariables + 1
3529
3530 ! reset the ID for TIME BNDS to the last varid
3531 nc_time_bnds = ncfile%iNumberOfVariables - 1
3532
3533 if (associated(ncfile%pNC_VAR) ) deallocate(ncfile%pNC_VAR, stat=istat)
3534 call assert(istat == 0, "Could not deallocate memory for NC_VAR member in NC_FILE defined type", &
3535 __file__, __line__)
3536
3537 allocate(ncfile%pNC_VAR( 0 : ncfile%iNumberOfVariables-1), stat=istat )
3538 call assert(istat == 0, "Could not allocate memory for NC_VAR member in NC_FILE defined type", &
3539 __file__, __line__)
3540
3541 ncfile%pNC_VAR(nc_time)%sVariableName = "time"
3542 ncfile%pNC_VAR(nc_time)%iNC_VarType = nc_float
3543 ncfile%pNC_VAR(nc_time)%iNumberOfDimensions = 1
3544 ncfile%pNC_VAR(nc_time)%iNC_DimID(0) = ncfile%pNC_DIM(nc_time)%iNC_DimID
3545
3546 ncfile%pNC_VAR(nc_y)%sVariableName = "y"
3547 ncfile%pNC_VAR(nc_y)%iNC_VarType = nc_double
3548 ncfile%pNC_VAR(nc_y)%iNumberOfDimensions = 1
3549 ncfile%pNC_VAR(nc_y)%iNC_DimID = ncfile%pNC_DIM(nc_y)%iNC_DimID
3550
3551 ncfile%pNC_VAR(nc_x)%sVariableName = "x"
3552 ncfile%pNC_VAR(nc_x)%iNC_VarType = nc_double
3553 ncfile%pNC_VAR(nc_x)%iNumberOfDimensions = 1
3554 ncfile%pNC_VAR(nc_x)%iNC_DimID = ncfile%pNC_DIM(nc_x)%iNC_DimID
3555
3556 ncfile%pNC_VAR(nc_crs)%sVariableName = "crs"
3557 ncfile%pNC_VAR(nc_crs)%iNC_VarType = nc_int
3558 ncfile%pNC_VAR(nc_crs)%iNumberOfDimensions = 0
3559
3560 ncfile%pNC_VAR(nc_z)%sVariableName = trim(svarname_z)
3561 ncfile%pNC_VAR(nc_z)%iNC_VarType = nc_float
3562 ncfile%pNC_VAR(nc_z)%iNumberOfDimensions = 3
3563 ncfile%pNC_VAR(nc_z)%iNC_DimID = [ncfile%pNC_DIM(nc_time)%iNC_DimID, &
3564 ncfile%pNC_DIM(nc_y)%iNC_DimID, &
3565 ncfile%pNC_DIM(nc_x)%iNC_DimID,0]
3566
3567 ncfile%sVarName(nc_z) = trim(svarname_z)
3568
3569 if ( llatlon_l ) then
3570
3571 ncfile%pNC_VAR(nc_lat)%sVariableName = "lat"
3572 ncfile%pNC_VAR(nc_lat)%iNC_VarType = nc_double
3573 ncfile%pNC_VAR(nc_lat)%iNumberOfDimensions = 2
3574 ncfile%pNC_VAR(nc_lat)%iNC_DimID = [ncfile%pNC_DIM(nc_y)%iNC_DimID, &
3575 ncfile%pNC_DIM(nc_x)%iNC_DimID,0,0]
3576
3577 ncfile%pNC_VAR(nc_lon)%sVariableName = "lon"
3578 ncfile%pNC_VAR(nc_lon)%iNC_VarType = nc_double
3579 ncfile%pNC_VAR(nc_lon)%iNumberOfDimensions = 2
3580 ncfile%pNC_VAR(nc_lon)%iNC_DimID = [ncfile%pNC_DIM(nc_y)%iNC_DimID, &
3581 ncfile%pNC_DIM(nc_x)%iNC_DimID,0,0]
3582 endif
3583
3584 if ( write_time_bounds_l ) then
3585
3586 ncfile%pNC_VAR(nc_time_bnds)%sVariableName = "time_bnds"
3587 ncfile%pNC_VAR(nc_time_bnds)%iNC_VarType = nc_double
3588 ncfile%pNC_VAR(nc_time_bnds)%iNumberOfDimensions = 2
3589 ncfile%pNC_VAR(nc_time_bnds)%iNC_DimID = [ncfile%pNC_DIM(nc_time)%iNC_DimID, &
3590 ncfile%pNC_DIM(nc_aux)%iNC_DimID,0,0]
3591
3592 endif
3593
3594end subroutine nf_set_standard_variables
3595
3596!----------------------------------------------------------------------
3597
3598subroutine nf_set_global_attributes(NCFILE, sDataType, executable_name, &
3599 history_list, sSourceFile )
3600
3601 type (T_NETCDF4_FILE ) :: NCFILE
3602 character (len=*), intent(in) :: sDataType
3603 character (len=*), intent(in), optional :: executable_name
3604 type (FSTRING_LIST_T), intent(in), pointer, optional :: history_list
3605 character (len=*), intent(in), optional :: sSourceFile
3606
3607 ! [ LOCALS ]
3608 integer (c_int) :: iStat
3609 type (DATETIME_T) :: DT
3610 character (len=20) :: sDateTime
3611 character (len=:), allocatable :: executable_name_l
3612 type (FSTRING_LIST_T), pointer :: history_list_l
3613 integer (c_int) :: indx, jndx
3614 integer (c_int) :: records
3615
3616 if (present( executable_name) ) then
3617 executable_name_l = trim( executable_name )
3618 else
3619 executable_name_l = "SWB"
3620 endif
3621
3622 if ( present( history_list ) ) then
3623 history_list_l => history_list
3624 ncfile%iNumberOfAttributes = 3 + history_list_l%count
3625 else
3626 allocate( history_list_l )
3627 call history_list_l%append(trim(sdatetime)//": Soil-Water-Balance model run started.")
3628 ncfile%iNumberOfAttributes = 4
3629 endif
3630
3631 call dt%systime()
3632 sdatetime = dt%prettydatetime()
3633
3634 allocate( ncfile%pNC_ATT(0:ncfile%iNumberOfAttributes-1), stat=istat)
3635 call assert(istat == 0, "Could not allocate memory for NC_ATT member of NC_FILE", &
3636 __file__, __line__)
3637
3638 block
3639
3640 if (present(ssourcefile) ) then
3641
3642 ncfile%pNC_ATT(0)%sAttributeName = "source"
3643 allocate(ncfile%pNC_ATT(0)%sAttValue(0:0))
3644 ncfile%pNC_ATT(0)%sAttValue(0) = trim(sdatatype)//" data from file "//dquote(ssourcefile)
3645 ncfile%pNC_ATT(0)%iNC_AttType = nc_char
3646 ncfile%pNC_ATT(0)%iNC_AttSize = 1_c_size_t
3647
3648 else
3649
3650 ncfile%pNC_ATT(0)%sAttributeName = "source"
3651 allocate(ncfile%pNC_ATT(0)%sAttValue(0:0))
3652 ncfile%pNC_ATT(0)%sAttValue(0) = trim(sdatatype)//" output from " &
3653 //executable_name_l//" run " &
3654 //"started on "//trim(sdatetime)//"."
3655 ncfile%pNC_ATT(0)%iNC_AttType = nc_char
3656 ncfile%pNC_ATT(0)%iNC_AttSize = 1_c_size_t
3657
3658 endif
3659
3660 ncfile%pNC_ATT(1)%sAttributeName = "executable_version"
3661 allocate(ncfile%pNC_ATT(1)%sAttValue(0:0))
3662 ncfile%pNC_ATT(1)%sAttValue(0) = "version "//trim(swb_version) &
3663 //", Git branch: "//trim(git_branch_string)//", Git commit hash string: " &
3664 //trim(git_commit_hash_string)//", compiled on: "//trim(compile_date) &
3665 //" "//trim(compile_time)//"."
3666 ncfile%pNC_ATT(1)%iNC_AttType = nc_char
3667 ncfile%pNC_ATT(1)%iNC_AttSize = 1_c_size_t
3668
3669 ncfile%pNC_ATT(2)%sAttributeName = "Conventions"
3670 allocate(ncfile%pNC_ATT(2)%sAttValue(0:0))
3671 ncfile%pNC_ATT(2)%sAttValue(0) = "CF-1.6"
3672 ncfile%pNC_ATT(2)%iNC_AttType = nc_char
3673 ncfile%pNC_ATT(2)%iNC_AttSize = 1_c_size_t
3674
3675 ! special case: history may have meny records
3676 records = history_list_l%count
3677
3678 do indx=1, records
3679
3680 jndx = indx + 2
3681 ncfile%pNC_ATT( jndx )%sAttributeName = "history"
3682 allocate(ncfile%pNC_ATT(jndx)%sAttValue( 0:0 ) )
3683 ncfile%pNC_ATT(jndx)%iNC_AttType = nc_char
3684 ncfile%pNC_ATT(jndx)%iNC_AttSize = int( records, c_size_t )
3685 ncfile%pNC_ATT(jndx)%sAttValue( 0 ) = trim(history_list_l%get( indx ))//c_null_char
3686
3687 enddo
3688
3689 end block
3690
3691end subroutine nf_set_global_attributes
3692
3693!----------------------------------------------------------------------
3694
3695subroutine nf_set_standard_attributes(NCFILE, sOriginText, PROJ4_string, &
3696 lLatLon, fValidMin, fValidMax, &
3697 write_time_bounds )
3698
3699 type (T_NETCDF4_FILE ) :: NCFILE
3700 character (len=*) :: sOriginText
3701 character (len=*), optional :: PROJ4_string
3702 logical (c_bool), optional :: lLatLon
3703 real (c_float), optional :: fValidMin
3704 real (c_float), optional :: fValidMax
3705 logical (c_bool), optional :: write_time_bounds
3706
3707 ! [ LOCALS ]
3708 integer (c_int) :: iStat
3709 integer (c_int) :: iNumAttributes
3710 type (T_NETCDF_ATTRIBUTE), dimension(:), pointer :: pNC_ATT
3711 logical (c_bool) :: lLatLon_l
3712 logical (c_bool) :: write_time_bounds_l
3713 type (FSTRING_LIST_T) :: attribute_name_list
3714 type (FSTRING_LIST_T) :: attribute_value_list
3715 character (len=:), allocatable :: tempstring
3716 character (len=:), allocatable :: value_string
3717 character (len=:), allocatable :: value_string1
3718 character (len=:), allocatable :: value_string2
3719 integer (c_int) :: indx
3720
3721 if (present( llatlon ) ) then
3722 llatlon_l = llatlon
3723 else
3724 llatlon_l = false
3725 endif
3726
3727 if ( present( write_time_bounds ) ) then
3728 write_time_bounds_l = write_time_bounds
3729 else
3730 write_time_bounds_l = false
3731 endif
3732
3733 if (present( proj4_string ) ) then
3734 call create_attributes_from_proj4_string( proj4_string, attribute_name_list, &
3735 attribute_value_list )
3736
3737 ! Define attributes for the coordinate reference system (CRS)
3738 inumattributes = attribute_name_list%count + 1
3739
3740 allocate( ncfile%pNC_VAR(nc_crs)%pNC_ATT(0:inumattributes-1), stat=istat)
3741 call assert(istat == 0, "Could not allocate memory for NC_ATT member in NC_VAR struct of NC_FILE", &
3742 __file__, __line__)
3743 ncfile%pNC_VAR(nc_crs)%iNumberOfAttributes = inumattributes
3744
3745 pnc_att => ncfile%pNC_VAR(nc_crs)%pNC_ATT
3746
3747 ! the following block of code parses the PROJ4 string and rips standard
3748 ! CF attributes from the string
3749 do indx=0, inumattributes-2
3750
3751 tempstring = attribute_name_list%get( indx + 1 )
3752 pnc_att(indx)%sAttributeName = tempstring
3753
3754 select case ( tempstring )
3755
3756 case ( "units" )
3757
3758 value_string = attribute_value_list%get( indx + 1 )
3759 ncfile%sVarUnits(nc_x) = value_string
3760 ncfile%sVarUnits(nc_y) = value_string
3761
3762 allocate(pnc_att(indx)%sAttValue(0:0))
3763 pnc_att(indx)%sAttValue(0) = value_string
3764 pnc_att(indx)%iNC_AttType = nc_char
3765 pnc_att(indx)%iNC_AttSize = 1_c_size_t
3766
3767 case ( "datum", "spheroid", "grid_mapping_name" )
3768
3769 allocate(pnc_att(indx)%sAttValue(0:0))
3770 pnc_att(indx)%sAttValue(0) = attribute_value_list%get( indx + 1 )
3771 pnc_att(indx)%iNC_AttType = nc_char
3772 pnc_att(indx)%iNC_AttSize = 1_c_size_t
3773
3774 case ( "standard_parallel" )
3775
3776 allocate(pnc_att(indx)%dpAttValue(0:1))
3777
3778 value_string = attribute_value_list%get( indx + 1 )
3779 value_string1 = left(value_string, substring=",")
3780 value_string2 = right(value_string, substring=",")
3781
3782 call assert(len_trim(value_string1) > 0, "standard_parallel requires valid values for '+lat_1' and '+lat_2'.", &
3783 shints="Are '+lat_1' or '+lat_2' missing or out of order in the control file PROJ string?")
3784
3785 pnc_att(indx)%dpAttValue(0) = asdouble( value_string1 )
3786 pnc_att(indx)%dpAttValue(1) = asdouble( value_string2 )
3787 pnc_att(indx)%iNC_AttType = nc_double
3788 pnc_att(indx)%iNC_AttSize = 2_c_size_t
3789
3790 case ( "UTM_zone" )
3791
3792 allocate(pnc_att(indx)%iAttValue(0:0))
3793 pnc_att(indx)%iAttValue(0) = asint( attribute_value_list%get( indx + 1 ) )
3794 pnc_att(indx)%iNC_AttType = nc_int
3795 pnc_att(indx)%iNC_AttSize = 1_c_size_t
3796
3797 case default
3798
3799 allocate(pnc_att(indx)%dpAttValue(0:0))
3800 pnc_att(indx)%dpAttValue(0) = asdouble( attribute_value_list%get( indx + 1 ) )
3801 pnc_att(indx)%iNC_AttType = nc_double
3802 pnc_att(indx)%iNC_AttSize = 1_c_size_t
3803
3804 end select
3805
3806 enddo
3807
3808 ! last, store the actual PROJ4 string
3809 pnc_att(indx)%sAttributeName = "proj4_string"
3810 allocate(pnc_att(indx)%sAttValue(0:0))
3811 pnc_att(indx)%sAttValue(0) = proj4_string
3812 pnc_att(indx)%iNC_AttType = nc_char
3813 pnc_att(indx)%iNC_AttSize = 1_c_size_t
3814
3815 call attribute_name_list%clear()
3816 call attribute_value_list%clear()
3817
3818 endif
3819
3820 !! define attributes associated with TIME variable
3821 inumattributes = 3
3822 if ( write_time_bounds_l ) inumattributes=4
3823 allocate( ncfile%pNC_VAR(nc_time)%pNC_ATT(0:inumattributes-1), stat=istat)
3824 call assert(istat == 0, "Could not allocate memory for NC_ATT member in NC_VAR struct of NC_FILE", &
3825 __file__, __line__)
3826 ncfile%pNC_VAR(nc_time)%iNumberOfAttributes = inumattributes
3827
3828 pnc_att => ncfile%pNC_VAR(nc_time)%pNC_ATT
3829
3830 pnc_att(0)%sAttributeName = "units"
3831 allocate(pnc_att(0)%sAttValue(0:0))
3832 pnc_att(0)%sAttValue(0) = "days since "//trim(sorigintext)//" 00:00:00"
3833 pnc_att(0)%iNC_AttType = nc_char
3834 pnc_att(0)%iNC_AttSize = 1_c_size_t
3835
3836 pnc_att(1)%sAttributeName = "calendar"
3837 allocate(pnc_att(1)%sAttValue(0:0))
3838 pnc_att(1)%sAttValue(0) = "standard"
3839 pnc_att(1)%iNC_AttType = nc_char
3840 pnc_att(1)%iNC_AttSize = 1_c_size_t
3841
3842 pnc_att(2)%sAttributeName = "long_name"
3843 allocate(pnc_att(2)%sAttValue(0:0))
3844 pnc_att(2)%sAttValue(0) = "time"
3845 pnc_att(2)%iNC_AttType = nc_char
3846 pnc_att(2)%iNC_AttSize = 1_c_size_t
3847
3848 if ( write_time_bounds_l ) then
3849 pnc_att(3)%sAttributeName = "bounds"
3850 allocate(pnc_att(3)%sAttValue(0:0))
3851 pnc_att(3)%sAttValue(0) = "time_bounds"
3852 pnc_att(3)%iNC_AttType = nc_char
3853 pnc_att(3)%iNC_AttSize = 1_c_size_t
3854 endif
3855
3856 if (present( fvalidmin ) .and. present( fvalidmax) ) then
3857
3858 inumattributes = 7
3859 allocate( ncfile%pNC_VAR(nc_z)%pNC_ATT(0:inumattributes-1), stat=istat)
3860 call assert(istat == 0, "Could not allocate memory for NC_ATT member in NC_VAR struct of NC_FILE", &
3861 __file__, __line__)
3862 ncfile%pNC_VAR(nc_z)%iNumberOfAttributes = inumattributes
3863
3864 pnc_att => ncfile%pNC_VAR(nc_z)%pNC_ATT
3865
3866 pnc_att(0)%sAttributeName = "units"
3867 allocate(pnc_att(0)%sAttValue(0:0))
3868 pnc_att(0)%sAttValue(0) = ncfile%sVarUnits(nc_z)
3869 pnc_att(0)%iNC_AttType = nc_char
3870 pnc_att(0)%iNC_AttSize = 1_c_size_t
3871
3872 pnc_att(1)%sAttributeName = "valid_min"
3873 allocate(pnc_att(1)%rAttValue(0:0))
3874 pnc_att(1)%rAttValue(0) = fvalidmin
3875 pnc_att(1)%iNC_AttType = nc_float
3876 pnc_att(1)%iNC_AttSize = 1_c_size_t
3877
3878 pnc_att(2)%sAttributeName = "valid_max"
3879 allocate(pnc_att(2)%rAttValue(0:0))
3880 pnc_att(2)%rAttValue(0) = fvalidmax
3881 pnc_att(2)%iNC_AttType = nc_float
3882 pnc_att(2)%iNC_AttSize = 1_c_size_t
3883
3884 pnc_att(3)%sAttributeName = "valid_range"
3885 allocate(pnc_att(3)%rAttValue(0:1))
3886 pnc_att(3)%rAttValue(0) = fvalidmin
3887 pnc_att(3)%rAttValue(1) = fvalidmax
3888 pnc_att(3)%iNC_AttType = nc_float
3889 pnc_att(3)%iNC_AttSize = 2_c_size_t
3890
3891 pnc_att(4)%sAttributeName = "_FillValue"
3892 allocate(pnc_att(4)%rAttValue(0:0))
3893 pnc_att(4)%rAttValue(0) = nc_fill_float
3894 pnc_att(4)%iNC_AttType = nc_float
3895 pnc_att(4)%iNC_AttSize = 1_c_size_t
3896
3897 pnc_att(5)%sAttributeName = "coordinates"
3898 allocate(pnc_att(5)%sAttValue(0:0))
3899! pNC_ATT(5)%sAttValue(0) = "lat lon"
3900 pnc_att(5)%sAttValue(0) = "crs"
3901 pnc_att(5)%iNC_AttType = nc_char
3902 pnc_att(5)%iNC_AttSize = 1_c_size_t
3903
3904 pnc_att(6)%sAttributeName = "grid_mapping"
3905 allocate(pnc_att(6)%sAttValue(0:0))
3906 pnc_att(6)%sAttValue(0) = "crs"
3907 pnc_att(6)%iNC_AttType = nc_char
3908 pnc_att(6)%iNC_AttSize = 1_c_size_t
3909
3910 else
3911
3912 inumattributes = 3
3913 allocate( ncfile%pNC_VAR(nc_z)%pNC_ATT(0:inumattributes-1), stat=istat)
3914 call assert(istat == 0, "Could not allocate memory for NC_ATT member in NC_VAR struct of NC_FILE", &
3915 __file__, __line__)
3916 ncfile%pNC_VAR(nc_z)%iNumberOfAttributes = inumattributes
3917
3918 pnc_att => ncfile%pNC_VAR(nc_z)%pNC_ATT
3919
3920 pnc_att(0)%sAttributeName = "units"
3921 allocate(pnc_att(0)%sAttValue(0:0))
3922 pnc_att(0)%sAttValue(0) = ncfile%sVarUnits(nc_z)
3923 pnc_att(0)%iNC_AttType = nc_char
3924 pnc_att(0)%iNC_AttSize = 1_c_size_t
3925
3926 pnc_att(1)%sAttributeName = "coordinates"
3927 allocate(pnc_att(1)%sAttValue(0:0))
3928 pnc_att(1)%sAttValue(0) = "lat lon"
3929 pnc_att(1)%iNC_AttType = nc_char
3930 pnc_att(1)%iNC_AttSize = 1_c_size_t
3931
3932 pnc_att(2)%sAttributeName = "grid_mapping"
3933 allocate(pnc_att(2)%sAttValue(0:0))
3934 pnc_att(2)%sAttValue(0) = "crs"
3935 pnc_att(2)%iNC_AttType = nc_char
3936 pnc_att(2)%iNC_AttSize = 1_c_size_t
3937
3938 endif
3939
3940 inumattributes = 3
3941 allocate( ncfile%pNC_VAR(nc_y)%pNC_ATT(0:inumattributes-1), stat=istat)
3942 call assert(istat == 0, "Could not allocate memory for NC_ATT member in NC_VAR struct of NC_FILE", &
3943 __file__, __line__)
3944 ncfile%pNC_VAR(nc_y)%iNumberOfAttributes = inumattributes
3945
3946 pnc_att => ncfile%pNC_VAR(nc_y)%pNC_ATT
3947
3948 block
3949
3950 pnc_att(0)%sAttributeName = "units"
3951 allocate(pnc_att(0)%sAttValue(0:0))
3952 pnc_att(0)%sAttValue(0) = ncfile%sVarUnits(nc_y)
3953 pnc_att(0)%iNC_AttType = nc_char
3954 pnc_att(0)%iNC_AttSize = 1_c_size_t
3955
3956 pnc_att(1)%sAttributeName = "long_name"
3957 allocate(pnc_att(1)%sAttValue(0:0))
3958 pnc_att(1)%sAttValue(0) = "y coordinate of projection"
3959 pnc_att(1)%iNC_AttType = nc_char
3960 pnc_att(1)%iNC_AttSize = 1_c_size_t
3961
3962 pnc_att(2)%sAttributeName = "standard_name"
3963 allocate(pnc_att(2)%sAttValue(0:0))
3964 pnc_att(2)%sAttValue(0) = "projection_y_coordinate"
3965 pnc_att(2)%iNC_AttType = nc_char
3966 pnc_att(2)%iNC_AttSize = 1_c_size_t
3967
3968
3969 end block
3970
3971 inumattributes = 3
3972 allocate( ncfile%pNC_VAR(nc_x)%pNC_ATT(0:inumattributes-1), stat=istat)
3973 call assert(istat == 0, "Could not allocate memory for NC_ATT member in NC_VAR struct of NC_FILE", &
3974 __file__, __line__)
3975 ncfile%pNC_VAR(nc_x)%iNumberOfAttributes = inumattributes
3976
3977 pnc_att => ncfile%pNC_VAR(nc_x)%pNC_ATT
3978
3979 block
3980
3981 pnc_att(0)%sAttributeName = "units"
3982 allocate(pnc_att(0)%sAttValue(0:0))
3983 pnc_att(0)%sAttValue(0) = ncfile%sVarUnits(nc_x)
3984 pnc_att(0)%iNC_AttType = nc_char
3985 pnc_att(0)%iNC_AttSize = 1_c_size_t
3986
3987 pnc_att(1)%sAttributeName = "long_name"
3988 allocate(pnc_att(1)%sAttValue(0:0))
3989 pnc_att(1)%sAttValue(0) = "x coordinate of projection"
3990 pnc_att(1)%iNC_AttType = nc_char
3991 pnc_att(1)%iNC_AttSize = 1_c_size_t
3992
3993 pnc_att(2)%sAttributeName = "standard_name"
3994 allocate(pnc_att(2)%sAttValue(0:0))
3995 pnc_att(2)%sAttValue(0) = "projection_x_coordinate"
3996 pnc_att(2)%iNC_AttType = nc_char
3997 pnc_att(2)%iNC_AttSize = 1_c_size_t
3998
3999
4000 end block
4001
4002 if ( llatlon_l ) then
4003
4004 inumattributes = 3
4005 allocate( ncfile%pNC_VAR(nc_lat)%pNC_ATT(0:inumattributes-1), stat=istat)
4006 call assert(istat == 0, "Could not allocate memory for NC_ATT member in NC_VAR struct of NC_FILE", &
4007 __file__, __line__)
4008 ncfile%pNC_VAR(nc_lat)%iNumberOfAttributes = inumattributes
4009
4010 pnc_att => ncfile%pNC_VAR(nc_lat)%pNC_ATT
4011
4012 block
4013
4014 pnc_att(0)%sAttributeName = "units"
4015 allocate(pnc_att(0)%sAttValue(0:0))
4016 pnc_att(0)%sAttValue(0) = "degrees_north"
4017 pnc_att(0)%iNC_AttType = nc_char
4018 pnc_att(0)%iNC_AttSize = 1_c_size_t
4019
4020 pnc_att(1)%sAttributeName = "long_name"
4021 allocate(pnc_att(1)%sAttValue(0:0))
4022 pnc_att(1)%sAttValue(0) = "latitude"
4023 pnc_att(1)%iNC_AttType = nc_char
4024 pnc_att(1)%iNC_AttSize = 1_c_size_t
4025
4026 pnc_att(2)%sAttributeName = "standard_name"
4027 allocate(pnc_att(2)%sAttValue(0:0))
4028 pnc_att(2)%sAttValue(0) = "latitude"
4029 pnc_att(2)%iNC_AttType = nc_char
4030 pnc_att(2)%iNC_AttSize = 1_c_size_t
4031
4032
4033 end block
4034
4035
4036 inumattributes = 3
4037 allocate( ncfile%pNC_VAR(nc_lon)%pNC_ATT(0:inumattributes-1), stat=istat)
4038 call assert(istat == 0, "Could not allocate memory for NC_ATT member in NC_VAR struct of NC_FILE", &
4039 __file__, __line__)
4040 ncfile%pNC_VAR(nc_lon)%iNumberOfAttributes = inumattributes
4041
4042 pnc_att => ncfile%pNC_VAR(nc_lon)%pNC_ATT
4043
4044 block
4045
4046 pnc_att(0)%sAttributeName = "units"
4047 allocate(pnc_att(0)%sAttValue(0:0))
4048 pnc_att(0)%sAttValue(0) = "degrees_east"
4049 pnc_att(0)%iNC_AttType = nc_char
4050 pnc_att(0)%iNC_AttSize = 1_c_size_t
4051
4052 pnc_att(1)%sAttributeName = "long_name"
4053 allocate(pnc_att(1)%sAttValue(0:0))
4054 pnc_att(1)%sAttValue(0) = "longitude"
4055 pnc_att(1)%iNC_AttType = nc_char
4056 pnc_att(1)%iNC_AttSize = 1_c_size_t
4057
4058 pnc_att(2)%sAttributeName = "standard_name"
4059 allocate(pnc_att(2)%sAttValue(0:0))
4060 pnc_att(2)%sAttValue(0) = "longitude"
4061 pnc_att(2)%iNC_AttType = nc_char
4062 pnc_att(2)%iNC_AttSize = 1_c_size_t
4063
4064
4065 end block
4066
4067 endif
4068
4069end subroutine nf_set_standard_attributes
4070
4071!----------------------------------------------------------------------
4072
4073subroutine nf_put_x_and_y(NCFILE, dpX, dpY)
4074
4075 type (T_NETCDF4_FILE) :: NCFILE
4076 real (c_double), dimension(:) :: dpX
4077 real (c_double), dimension(:) :: dpY
4078
4079 ! [ LOCALS ]
4080 integer (c_size_t) :: iLength
4081 real (c_double), dimension(:), allocatable :: rX, rY
4082
4083 ilength = int(size(dpx, 1), c_size_t)
4084
4085 call netcdf_put_variable_vector(ncfile=ncfile, &
4086 ivarid=ncfile%pNC_VAR(nc_x)%iNC_VarID, &
4087 istart=[0_c_size_t], &
4088 icount=[ilength], &
4089 istride=[1_c_size_t], &
4090 dpvalues=dpx)
4091
4092 ilength = int(size(dpy, 1), c_size_t)
4093
4094 call netcdf_put_variable_vector(ncfile=ncfile, &
4095 ivarid=ncfile%pNC_VAR(nc_y)%iNC_VarID, &
4096 istart=[0_c_size_t], &
4097 icount=[ilength], &
4098 istride=[1_c_size_t], &
4099 dpvalues=dpy)
4100
4101end subroutine nf_put_x_and_y
4102
4103!----------------------------------------------------------------------
4104
4105subroutine nf_put_lat_and_lon(NCFILE, dpLat, dpLon)
4106
4107 type (T_NETCDF4_FILE) :: NCFILE
4108 real (c_double), dimension(:,:) :: dpLat
4109 real (c_double), dimension(:,:) :: dpLon
4110
4111 ! [ LOCALS ]
4112 integer (c_size_t) :: iNX, iNY
4113
4114 inx = int( size(dplat, 1), c_size_t)
4115 iny = int( size(dplat, 2), c_size_t)
4116
4117 call netcdf_put_variable_array(ncfile=ncfile, &
4118 ivarid=ncfile%pNC_VAR(nc_lat)%iNC_VarID, &
4119 istart=[0_c_size_t, 0_c_size_t], &
4120 icount=[ iny, inx ], &
4121 istride=[1_c_size_t,1_c_size_t], &
4122 dpvalues=dplat)
4123
4124
4125 call netcdf_put_variable_array(ncfile=ncfile, &
4126 ivarid=ncfile%pNC_VAR(nc_lon)%iNC_VarID, &
4127 istart=[0_c_size_t, 0_c_size_t], &
4128 icount=[ iny, inx ],&
4129 istride=[1_c_size_t,1_c_size_t], &
4130 dpvalues=dplon)
4131
4132end subroutine nf_put_lat_and_lon
4133
4134!----------------------------------------------------------------------
4135
4136function nf_define_variable(NCFILE, sVariableName, iVariableType, &
4137 iNumberOfDimensions, iDimIDs) result(iVarID)
4138
4139 type (t_netcdf4_file ) :: ncfile
4140 character (len=*) :: svariablename
4141 integer (c_int) :: ivariabletype
4142 integer (c_int) :: inumberofdimensions
4143 integer (c_int), dimension(:) :: idimids
4144 integer (c_int) :: ivarid
4145
4146 call nf_trap( nc_def_var(ncid=ncfile%iNCID,&
4147 name=trim(fortran_to_c_string(svariablename)), &
4148 xtype=ivariabletype, &
4149 ndims=inumberofdimensions, &
4150 dimidsp=idimids, &
4151 varidp=ivarid), &
4152 __file__, __line__)
4153
4154end function nf_define_variable
4155
4156!----------------------------------------------------------------------
4157
4158!! before this function is called, the values associated with NCFILE must be defined.
4159
4160subroutine nf_define_variables( NCFILE )
4161
4162 type (T_NETCDF4_FILE) :: NCFILE
4163
4164 ! [ LOCALS ]
4165 integer (c_int) :: iStat
4166 integer (c_int) :: iIndex
4167 character (len=256) :: sDimName
4168 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
4169
4170 !! note: the default number of variables for a simple archive file is 4:
4171 !! 0) time, 1) Y, 2) X, 3) variable of interest
4172
4173 do iindex = 0, ncfile%iNumberOfVariables-1
4174
4175 pnc_var => ncfile%pNC_VAR(iindex)
4176
4177 call nf_trap( nc_def_var(ncid=ncfile%iNCID,&
4178 name=trim(fortran_to_c_string(pnc_var%sVariableName)), &
4179 xtype=pnc_var%iNC_VarType, &
4180 ndims=pnc_var%iNumberOfDimensions, &
4181 dimidsp=pnc_var%iNC_DimID, &
4182 varidp=pnc_var%iNC_VarID), &
4183 __file__, __line__)
4184
4185 enddo
4186
4187end subroutine nf_define_variables
4188
4189!----------------------------------------------------------------------
4190
4191subroutine netcdf_rewrite_attribute(NCFILE, sVariableName, sAttributeName, &
4192 sAttributeValue, iAttributeValue, rAttributeValue, dpAttributeValue)
4193
4194 type (t_netcdf4_file ) :: ncfile
4195 character (len=*) :: svariablename
4196 character (len=*) :: sattributename
4197 character (len=*), dimension(:), optional :: sattributevalue
4198 integer (c_int), dimension(:), optional :: iattributevalue
4199 real (c_float), dimension(:), optional :: rattributevalue
4200 real (c_double), dimension(:), optional :: dpattributevalue
4201
4202 integer (c_int) :: ivarid
4203
4204 ! put netCDF file into define mode again before attempting to redefine the attribute
4205 call nf_redef(ncfile)
4206
4207 ivarid = nf_get_varid(ncfile, trim(svariablename))
4208
4209 if (present(sattributevalue)) &
4210 call nf_put_attribute( ncfile, ivarid, trim(sattributename)//c_null_char, sattributevalue )
4211
4212 if (present(iattributevalue)) &
4213 call nf_put_attribute( ncfile, ivarid, trim(sattributename)//c_null_char, iattributevalue=iattributevalue )
4214
4215 if (present(rattributevalue)) &
4216 call nf_put_attribute( ncfile, ivarid, trim(sattributename)//c_null_char, rattributevalue=rattributevalue )
4217
4218 if (present(dpattributevalue)) &
4219 call nf_put_attribute( ncfile, ivarid, trim(sattributename)//c_null_char, dpattributevalue=dpattributevalue )
4220
4221end subroutine netcdf_rewrite_attribute
4222
4223!----------------------------------------------------------------------
4224
4225subroutine nf_put_attribute(NCFILE, iVarID, sAttributeName, &
4226 sAttributeValue, iAttributeValue, rAttributeValue, dpAttributeValue)
4227
4228 type (T_NETCDF4_FILE ) :: NCFILE
4229 integer (c_int) :: iVarID
4230 character (len=*) :: sAttributeName
4231 character (len=*), dimension(:), optional :: sAttributeValue
4232 integer (c_int), dimension(:), optional :: iAttributeValue
4233 real (c_float), dimension(:), optional :: rAttributeValue
4234 real (c_double), dimension(:), optional :: dpAttributeValue
4235
4236 ! [ LOCALS ]
4237 integer (c_size_t) :: iNumberOfAttributes
4238
4239 if (present(sattributevalue) ) then
4240
4241 inumberofattributes = size( sattributevalue, 1)
4242 inumberofattributes = int(len_trim(sattributevalue(1)), c_size_t)
4243
4244 call nf_trap( nc_put_att_text(ncid=ncfile%iNCID, &
4245 varid=ivarid, &
4246 name=trim(sattributename), &
4247 nlen=inumberofattributes, &
4248 tp=trim(sattributevalue(1))), &
4249 __file__, __line__)
4250
4251 elseif (present(iattributevalue) ) then
4252
4253 inumberofattributes = size( iattributevalue, 1)
4254
4255 call nf_trap( nc_put_att_int(ncid=ncfile%iNCID, &
4256 varid=ivarid, &
4257 name=trim(sattributename), &
4258 xtype=nc_int, &
4259 nlen=inumberofattributes, &
4260 ip=iattributevalue), &
4261 __file__, __line__)
4262
4263 elseif (present(rattributevalue) ) then
4264
4265 inumberofattributes = size( rattributevalue, 1)
4266
4267 call nf_trap( nc_put_att_float(ncid=ncfile%iNCID, &
4268 varid=ivarid, &
4269 name=trim(sattributename), &
4270 xtype=nc_float, &
4271 nlen=inumberofattributes, &
4272 fp=rattributevalue), &
4273 __file__, __line__)
4274
4275 elseif (present(dpattributevalue) ) then
4276
4277 inumberofattributes = size( dpattributevalue, 1)
4278
4279 call nf_trap( nc_put_att_double(ncid=ncfile%iNCID, &
4280 varid=ivarid, &
4281 name=trim(sattributename), &
4282 xtype=nc_double, &
4283 nlen=inumberofattributes, &
4284 dp=dpattributevalue), &
4285 __file__, __line__)
4286
4287 endif
4288
4289
4290end subroutine nf_put_attribute
4291
4292!----------------------------------------------------------------------
4293
4294subroutine nf_put_attributes(NCFILE)
4295
4296 type (T_NETCDF4_FILE ) :: NCFILE
4297
4298 ! [ LOCALS ]
4299 integer (c_size_t) :: iNumberOfAttributes
4300 type (T_NETCDF_VARIABLE), pointer :: pNC_VAR
4301 type (T_NETCDF_ATTRIBUTE), pointer :: pNC_ATT
4302 integer (c_int) :: iIndex
4303 integer (c_int) :: iIndex2
4304 integer (c_int) :: iStat
4305 integer (c_int) :: indx
4306
4307 ! loop over variables
4308 do iindex = 0, ncfile%iNumberOfVariables-1
4309
4310 pnc_var => ncfile%pNC_VAR(iindex)
4311
4312 ! for each variable, loop over the associated attributes
4313 do iindex2 = 0, pnc_var%iNumberOfAttributes-1
4314
4315 pnc_att => pnc_var%pNC_ATT(iindex2)
4316
4317 select case (pnc_att%iNC_AttType)
4318
4319 case (nc_double)
4320
4321 if (.not. allocated(pnc_att%dpAttValue) ) &
4322 call die("INTERNAL PROGRAMMING ERROR - attempt to use unallocated variable; " &
4323 //"attribute name: "//dquote(pnc_att%sAttributeName), &
4324 __file__, __line__)
4325
4326 call nf_put_attribute(ncfile=ncfile, &
4327 ivarid=pnc_var%iNC_VarID, &
4328 sattributename=trim(pnc_att%sAttributeName)//c_null_char, &
4329 dpattributevalue=pnc_att%dpAttValue)
4330
4331 case (nc_int)
4332
4333 if (.not. allocated(pnc_att%iAttValue) ) &
4334 call die("INTERNAL PROGRAMMING ERROR - attempt to use unallocated variable; " &
4335 //"attribute name: "//dquote(pnc_att%sAttributeName), &
4336 __file__, __line__)
4337
4338 call nf_put_attribute(ncfile=ncfile, &
4339 ivarid=pnc_var%iNC_VarID, &
4340 sattributename=trim(pnc_att%sAttributeName)//c_null_char, &
4341 iattributevalue=pnc_att%iAttValue)
4342
4343 case (nc_float)
4344
4345 if (.not. allocated(pnc_att%rAttValue) ) &
4346 call die("INTERNAL PROGRAMMING ERROR - attempt to use unallocated variable; " &
4347 //"attribute name: "//dquote(pnc_att%sAttributeName), &
4348 __file__, __line__)
4349
4350 call nf_put_attribute(ncfile=ncfile, &
4351 ivarid=pnc_var%iNC_VarID, &
4352 sattributename=trim(pnc_att%sAttributeName)//c_null_char, &
4353 rattributevalue=pnc_att%rAttValue)
4354
4355 case (nc_char)
4356
4357 if (.not. allocated(pnc_att%sAttValue) ) &
4358 call die("INTERNAL PROGRAMMING ERROR - attempt to use unallocated variable; " &
4359 //"attribute name: "//dquote(pnc_att%sAttributeName), &
4360 __file__, __line__)
4361
4362 do indx=0,ubound(pnc_att%sAttValue, 1)
4363
4364 call nf_put_attribute(ncfile=ncfile, &
4365 ivarid=pnc_var%iNC_VarID, &
4366 sattributename=trim(pnc_att%sAttributeName)//c_null_char, &
4367 sattributevalue=[trim(pnc_att%sAttValue(indx))//c_null_char])
4368
4369 enddo
4370
4371 end select
4372
4373 enddo
4374
4375 enddo
4376
4377 ! now loop over global attributes
4378 do iindex2 = 0, ncfile%iNumberOfAttributes-1
4379
4380 pnc_att => ncfile%pNC_ATT(iindex2)
4381
4382 select case (pnc_att%iNC_AttType)
4383
4384 case (nc_double)
4385
4386 if (.not. allocated(pnc_att%sAttValue) ) &
4387 call die("INTERNAL PROGRAMMING ERROR - attempt to use unallocated variable; " &
4388 //"attribute name: "//dquote(pnc_att%sAttributeName), &
4389 __file__, __line__)
4390
4391 call nf_put_attribute(ncfile=ncfile, &
4392 ivarid=nc_global, &
4393 sattributename=trim(pnc_att%sAttributeName)//c_null_char, &
4394 dpattributevalue=pnc_att%dpAttValue)
4395
4396 case (nc_int)
4397
4398 if (.not. allocated(pnc_att%sAttValue) ) &
4399 call die("INTERNAL PROGRAMMING ERROR - attempt to use unallocated variable; " &
4400 //"attribute name: "//dquote(pnc_att%sAttributeName), &
4401 __file__, __line__)
4402
4403 call nf_put_attribute(ncfile=ncfile, &
4404 ivarid=nc_global, &
4405 sattributename=trim(pnc_att%sAttributeName)//c_null_char, &
4406 iattributevalue=pnc_att%iAttValue)
4407
4408 case (nc_float)
4409
4410 if (.not. allocated(pnc_att%sAttValue) ) &
4411 call die("INTERNAL PROGRAMMING ERROR - attempt to use unallocated variable; " &
4412 //"attribute name: "//dquote(pnc_att%sAttributeName), &
4413 __file__, __line__)
4414
4415 call nf_put_attribute(ncfile=ncfile, &
4416 ivarid=nc_global, &
4417 sattributename=trim(pnc_att%sAttributeName)//c_null_char, &
4418 rattributevalue=pnc_att%rAttValue)
4419
4420 case (nc_char)
4421
4422 if (.not. allocated(pnc_att%sAttValue) ) &
4423 call die("INTERNAL PROGRAMMING ERROR - attempt to use unallocated variable; " &
4424 //"attribute name: "//dquote(pnc_att%sAttributeName), &
4425 __file__, __line__)
4426
4427 do indx=0, ubound(pnc_att%sAttValue, 1)
4428
4429 call nf_put_attribute(ncfile=ncfile, &
4430 ivarid=nc_global, &
4431 sattributename=trim(pnc_att%sAttributeName)//c_null_char, &
4432 sattributevalue=[trim(pnc_att%sAttValue(indx))//c_null_char])
4433
4434 enddo
4435
4436 end select
4437
4438 enddo
4439
4440end subroutine nf_put_attributes
4441
4442!----------------------------------------------------------------------
4443
4444subroutine netcdf_put_variable_array(NCFILE, iVarID, iStart, iCount, iStride, &
4445 iValues, i2Values, rValues, dpValues)
4446
4447 type (t_netcdf4_file ) :: ncfile
4448 integer (c_int) :: ivarid
4449 integer (c_size_t), dimension(:) :: istart
4450 integer (c_size_t), dimension(:) :: icount
4451 integer (c_size_t), dimension(:) :: istride
4452 integer (c_int), dimension(:,:), optional :: ivalues
4453 integer (c_short), dimension(:,:), optional :: i2values
4454 real (c_float), dimension(:,:), optional :: rvalues
4455 real (c_double), dimension(:,:), optional :: dpvalues
4456
4457 if (present(ivalues) ) then
4458
4459 call nf_trap(nc_put_vars_int(ncid=ncfile%iNCID, &
4460 varid=ivarid, &
4461 startp=istart, &
4462 countp=icount, &
4463 stridep=istride, &
4464 vars=ivalues), &
4465 __file__, __line__)
4466
4467 elseif (present(i2values) ) then
4468
4469 call nf_trap(nc_put_vars_short(ncid=ncfile%iNCID, &
4470 varid=ivarid, &
4471 startp=istart, &
4472 countp=icount, &
4473 stridep=istride, &
4474 vars=i2values), &
4475 __file__, __line__)
4476
4477 elseif (present(rvalues) ) then
4478
4479 call nf_trap(nc_put_vars_float(ncid=ncfile%iNCID, &
4480 varid=ivarid, &
4481 startp=istart, &
4482 countp=icount, &
4483 stridep=istride, &
4484 vars=rvalues), &
4485 __file__, __line__)
4486
4487 elseif (present(dpvalues) ) then
4488
4489
4490
4491 call nf_trap(nc_put_vars_double(ncid=ncfile%iNCID, &
4492 varid=ivarid, &
4493 startp=istart, &
4494 countp=icount, &
4495 stridep=istride, &
4496 vars=dpvalues), &
4497 __file__, __line__)
4498
4499 endif
4500
4501end subroutine netcdf_put_variable_array
4502
4503subroutine netcdf_put_packed_variable_array(NCFILE, iVarID, iStart, iCount, iStride, &
4504 lMask, iValues, iField, i2Values, i2Field, rValues, rField, dpValues, dpField)
4505
4506 type (t_netcdf4_file ) :: ncfile
4507 integer (c_int) :: ivarid
4508 integer (c_size_t), dimension(:) :: istart
4509 integer (c_size_t), dimension(:) :: icount
4510 integer (c_size_t), dimension(:) :: istride
4511 logical (c_bool), dimension(:,:) :: lmask
4512 integer (c_int), dimension(:), optional :: ivalues
4513 integer (c_int), dimension(:,:), optional :: ifield
4514 integer (c_short), dimension(:), optional :: i2values
4515 integer (c_short), dimension(:,:), optional :: i2field
4516 real (c_float), dimension(:), optional :: rvalues
4517 real (c_float), dimension(:,:), optional :: rfield
4518 real (c_double), dimension(:), optional :: dpvalues
4519 real (c_double), dimension(:,:), optional :: dpfield
4520
4521 if (present(ivalues) ) then
4522
4523 call nf_trap(nc_put_vars_int(ncid=ncfile%iNCID, &
4524 varid=ivarid, &
4525 startp=istart, &
4526 countp=icount, &
4527 stridep=istride, &
4528 vars=unpack(ivalues, lmask, ifield)), &
4529 __file__, __line__)
4530
4531 elseif (present(i2values) ) then
4532
4533 call nf_trap(nc_put_vars_short(ncid=ncfile%iNCID, &
4534 varid=ivarid, &
4535 startp=istart, &
4536 countp=icount, &
4537 stridep=istride, &
4538 vars=unpack(i2values, lmask, i2field)), &
4539 __file__, __line__)
4540
4541 elseif (present(rvalues) ) then
4542
4543 call nf_trap(nc_put_vars_float(ncid=ncfile%iNCID, &
4544 varid=ivarid, &
4545 startp=istart, &
4546 countp=icount, &
4547 stridep=istride, &
4548 vars=unpack(rvalues, lmask, rfield)), &
4549 __file__, __line__)
4550
4551 elseif (present(dpvalues) ) then
4552
4553 call nf_trap(nc_put_vars_double(ncid=ncfile%iNCID, &
4554 varid=ivarid, &
4555 startp=istart, &
4556 countp=icount, &
4557 stridep=istride, &
4558 vars=unpack(dpvalues, lmask, dpfield)), &
4559 __file__, __line__)
4560
4561 endif
4562
4564
4565
4566subroutine netcdf_put_variable_vector(NCFILE, iVarID, iStart, iCount, iStride, &
4567 iValues, i2Values, rValues, dpValues)
4568
4569 type (t_netcdf4_file ) :: ncfile
4570 integer (c_int) :: ivarid
4571 integer (c_size_t), dimension(:) :: istart
4572 integer (c_size_t), dimension(:) :: icount
4573 integer (c_size_t), dimension(:) :: istride
4574 integer (c_int), dimension(:), optional :: ivalues
4575 integer (c_short), dimension(:), optional :: i2values
4576 real (c_float), dimension(:), optional :: rvalues
4577 real (c_double), dimension(:), optional :: dpvalues
4578
4579 if (present(ivalues) ) then
4580
4581 call nf_trap(nc_put_vars_int(ncid=ncfile%iNCID, &
4582 varid=ivarid, &
4583 startp=istart, &
4584 countp=icount, &
4585 stridep=istride, &
4586 vars=ivalues), &
4587 __file__, __line__)
4588
4589 elseif (present(i2values) ) then
4590
4591 call nf_trap(nc_put_vars_short(ncid=ncfile%iNCID, &
4592 varid=ivarid, &
4593 startp=istart, &
4594 countp=icount, &
4595 stridep=istride, &
4596 vars=i2values), &
4597 __file__, __line__)
4598
4599 elseif (present(rvalues) ) then
4600
4601 call nf_trap(nc_put_vars_float(ncid=ncfile%iNCID, &
4602 varid=ivarid, &
4603 startp=istart, &
4604 countp=icount, &
4605 stridep=istride, &
4606 vars=rvalues), &
4607 __file__, __line__)
4608
4609 elseif (present(dpvalues) ) then
4610
4611 call nf_trap(nc_put_vars_double(ncid=ncfile%iNCID, &
4612 varid=ivarid, &
4613 startp=istart, &
4614 countp=icount, &
4615 stridep=istride, &
4616 vars=dpvalues), &
4617 __file__, __line__, ncfile%sFilename )
4618
4619 endif
4620
4621end subroutine netcdf_put_variable_vector
4622
4623
4624end module netcdf4_support
This module contains physical constants and convenience functions aimed at performing unit conversion...
logical(c_bool), parameter, public true
elemental character(len=256) function, public fortran_to_c_string(stext)
character(len=:), allocatable, public output_prefix_name
logical(c_bool), parameter, public false
character(len=:), allocatable, public output_directory_name
elemental character(len=len(ccharacterstring) - 1) function, public c_to_fortran_string(ccharacterstring)
character(len=256) function, public char_ptr_to_fortran_string(cpcharacterptr)
integer(c_int), parameter, public ibigval
This module contains the DATETIME_T class and associated time and date-related routines,...
Definition datetime.F90:9
integer(c_int) function, public julian_day(iyear, imonth, iday, iorigin, sinputitemname)
Definition datetime.F90:642
subroutine, public warn(smessage, smodule, iline, shints, lfatal, iloglevel, lecho)
subroutine, public die(smessage, smodule, iline, shints, scalledby, icalledbyline)
Provides support for input and output of gridded ASCII data, as well as for creation and destruction ...
Definition grid.F90:8
real(c_float), parameter nc_fill_float
Definition grid.F90:34
integer(c_int), parameter, private row
Definition grid.F90:171
integer(c_int), parameter, private column
Definition grid.F90:170
integer(c_int), parameter nc_fill_int
Definition grid.F90:33
real(c_double), parameter nc_fill_double
Definition grid.F90:35
type(logfile_t), public logs
Definition logfiles.F90:62
Provide support for use of netCDF files as input for time-varying, gridded meteorlogic data,...
integer(c_int), parameter nc_64bit_offset
subroutine, public netcdf_set_coordinate_tolerance(ncfile, tolerance)
integer(c_int), parameter nc_netcdf4
integer(c_int), parameter nc_short
integer(c_int) function nf_get_varid(ncfile, svariablename)
integer(c_int), parameter, public nc_bottom
integer(c_int), parameter, public nc_y
subroutine nf_get_variable_array_as_vector_float(ncfile, inc_varid, inc_start, inc_count, inc_stride, rnc_vars)
subroutine nf_define_dimension(ncfile, sdimensionname, idimensionsize)
integer(c_int), parameter nc_string
integer(c_int) function nf_return_index_double(rvalues, rtargetvalue, roffsetvalue)
subroutine, public netcdf_nullify_data_struct(ncfile)
integer(c_int), parameter nc_int64
subroutine nf_populate_dimension_struct(ncfile)
integer(c_int), parameter, public nc_x
integer(c_int) function nf_julian_day_to_index(ncfile, rjulianday)
We need two functions to convert from index to timeval, and timeval to JD; note that timeval refers t...
integer(c_int), parameter nc_max_attrs
integer(c_int), parameter, public nc_crs
integer(c_int), parameter nc_fill_short
subroutine, public netcdf_open_and_prepare_as_output(ncfile, svariablename, svariableunits, inx, iny, fx, fy, startdate, enddate, proj4_string, history_list, executable_name, dplat, dplon, fvalidmin, fvalidmax, write_time_bounds, filename_prefix, filename_modifier)
integer(c_int), parameter nc_max_dims
subroutine, public netcdf_dump_cdl(ncfile, ilu)
integer(c_int) function nf_return_varindex(ncfile, ivarid)
subroutine nf_get_variable_slice_double(ncfile, dpvalues)
subroutine nf_guess_z_variable_name(ncfile)
integer(c_int), parameter, public nc_top
integer(c_int), parameter nc_ushort
integer(c_int), parameter nc_shuffle_no
integer(c_int), parameter nc_char
integer(c_int), parameter, public nc_right
integer(c_int), parameter nc_format_64bit
integer(c_int), parameter nc_max_name
integer(c_int), parameter nc_first
integer(c_int), parameter nc_lock
subroutine nf_get_variable_slice_short(ncfile, i2values)
integer(c_int), parameter nc_fill_byte
character(len=6), dimension(0:6), parameter netcdf_data_type
integer(c_int), public nc_readwrite
integer(c_int), parameter nc_byte
subroutine nf_get_variable_vector_float(ncfile, inc_varid, inc_start, inc_count, inc_stride, rnc_vars)
integer(c_int), parameter year_is_360_days
subroutine nf_get_variable_id_and_type(ncfile, strict_asserts)
subroutine nf_put_x_and_y(ncfile, dpx, dpy)
integer(c_int), parameter nc_int
integer(c_int), parameter nc_fill_char
subroutine nf_get_variable_array_double(ncfile, inc_varid, inc_start, inc_count, inc_stride, dpnc_vars)
real(c_double) function nf_index_to_dayvalue(ncfile, iindex)
subroutine, public netcdf_put_packed_variable_array(ncfile, ivarid, istart, icount, istride, lmask, ivalues, ifield, i2values, i2field, rvalues, rfield, dpvalues, dpfield)
subroutine, public netcdf_get_variable_slice(ncfile, rvalues, dpvalues, ivalues)
subroutine, public netcdf_close_file(ncfile)
integer(c_int), parameter nc_deflate_yes
integer(c_size_t) function nf_return_dimsize(ncfile, idimid)
subroutine nf_define_dimensions(ncfile)
subroutine nf_set_standard_attributes(ncfile, sorigintext, proj4_string, llatlon, fvalidmin, fvalidmax, write_time_bounds)
integer(c_int), parameter nc_double
subroutine nf_get_variable_array_as_vector_short(ncfile, inc_varid, inc_start, inc_count, inc_stride, inc_vars)
integer(c_int), parameter nc_max_vars
subroutine, public netcdf_get_attribute_list_for_variable(ncfile, variable_name, attribute_name_list, attribute_value_list)
integer(c_int), parameter nc_sizehint_default
subroutine nf_set_iteration_bounds(ncfile)
integer(c_int), parameter, public nc_time
@TODO: implement a more flexible way of tracking variable IDs; presently the code can break if lat an...
subroutine, public netcdf_open_and_prepare_for_merging(ncfile, sfilename, guess_z_var_name)
subroutine nf_calculate_time_range(ncfile)
subroutine, public netcdf_open_file(ncfile, sfilename, ilu)
integer(c_int), parameter, public nc_lon
integer(c_int), parameter nc_share
subroutine, public netcdf_open_and_prepare_as_input(ncfile, sfilename, lfliphorizontal, lflipvertical, lallowautomaticdataflipping, rx_coord_addoffset, ry_coord_addoffset, svariableorder, svarname_x, svarname_y, svarname_z, svarname_time, rcoordinatetolerance, tgridbounds, ilu)
real(c_float), parameter, public nc_fill_float
subroutine nf_put_attribute(ncfile, ivarid, sattributename, sattributevalue, iattributevalue, rattributevalue, dpattributevalue)
subroutine nf_get_scale_and_offset(ncfile)
character(len=25), dimension(4), parameter netcdf_format_string
subroutine nf_get_time_units(ncfile)
character(len=256) function nf_return_attvalue(ncfile, ivarindex, sattname)
integer(c_int), parameter nc_long
real(c_double) function nf_dayvalue_to_julian_day(ncfile, rdayvalue)
integer(c_int), parameter nc_nowrite
integer(c_int), parameter nc_shuffle_yes
integer(c_int), parameter nc_format_netcdf4
subroutine nf_redef(ncfile)
integer(c_int) function nf_define_variable(ncfile, svariablename, ivariabletype, inumberofdimensions, idimids)
subroutine nf_trap(iresultcode, sfilename, ilinenumber, netcdf_filename)
integer(c_int), parameter nc_classic_model
subroutine nf_enddef(ncfile)
subroutine nf_get_time_vals(ncfile)
subroutine nf_set_start_count_stride(ncfile)
integer(c_int), parameter nc_uint
logical(c_bool) function, public netcdf_date_within_range(ncfile, ijulianday)
integer(c_int), parameter, public nc_aux
subroutine nf_populate_variable_struct(ncfile)
subroutine nf_set_z_variable_name(ncfile, svarname_z)
integer(c_int), parameter nc_format_classic
integer(c_int) function nf_return_dimindex(ncfile, idimid)
integer(c_int), parameter nc_nat
integer(c_int), parameter nc_ubyte
subroutine nf_get_variable_vector_double(ncfile, inc_varid, inc_start, inc_count, inc_stride, dpnc_vars)
integer(c_int), parameter nc_unlimited
subroutine nf_get_variable_slice_int(ncfile, ivalues)
subroutine nf_set_standard_variables(ncfile, svarname_z, llatlon, write_time_bounds)
real(c_double) function, dimension(0:1) nf_get_first_and_last(ncfile, ivarindex)
subroutine nf_get_variable_vector_short(ncfile, inc_varid, inc_start, inc_count, inc_stride, inc_vars)
integer(c_int), parameter nc_write
integer(c_int), parameter nc_deflate_no
subroutine nf_get_xyz_units(ncfile)
subroutine nf_put_attributes(ncfile)
subroutine nf_delete_attribute(ncfile, svariablename, sattributename)
subroutine nf_get_variable_slice_float(ncfile, rvalues)
subroutine nf_populate_attribute_struct(ncfile, pnc_att, inc_varid, iattnum)
integer(c_int) function nf_return_varid(ncfile, ivarindex)
integer(c_int), parameter, public nc_lat
subroutine nf_set_global_attributes(ncfile, sdatatype, executable_name, history_list, ssourcefile)
subroutine nf_define_deflate(ncfile, ivarid, ishuffle, ideflate, ideflate_level)
subroutine nf_set_standard_dimensions(ncfile, inx, iny, write_time_bounds)
integer(c_int), parameter nc_global
integer(c_int), public nc_time_bnds
subroutine nf_define_variables(ncfile)
integer(c_int), parameter nc_fill
subroutine nf_open_file(ncfile, sfilename, ilu)
integer(c_int), parameter, public nc_left
subroutine, public netcdf_put_variable_array(ncfile, ivarid, istart, icount, istride, ivalues, i2values, rvalues, dpvalues)
subroutine nf_get_variable_array_as_vector_int(ncfile, inc_varid, inc_start, inc_count, inc_stride, inc_vars)
subroutine, public netcdf_put_variable_vector(ncfile, ivarid, istart, icount, istride, ivalues, i2values, rvalues, dpvalues)
subroutine nf_get_variable_vector_int(ncfile, inc_varid, inc_start, inc_count, inc_stride, inc_vars)
integer(c_int) function nf_return_dimid(ncfile, idimindex)
subroutine, public netcdf_open_and_prepare_as_output_archive(ncfile, ncfile_archive, ioriginmonth, ioriginday, ioriginyear, istartyear, iendyear)
integer(c_int), public nc_readonly
subroutine nf_create(ncfile, sfilename, ilu)
integer(c_int), parameter nc_clobber
subroutine nf_get_variable_array_as_vector_double(ncfile, inc_varid, inc_start, inc_count, inc_stride, dpnc_vars)
subroutine, public netcdf_get_variable_list(ncfile, variable_list)
integer(c_int), parameter nc_noclobber
subroutine nf_get_x_and_y(ncfile)
logical(c_bool) function, public netcdf_update_time_starting_index(ncfile, ijulianday)
integer(c_size_t) function, dimension(2), public netcdf_coord_to_col_row(ncfile, rx, ry)
integer(c_int), parameter, public nc_z
integer(c_int), parameter nc_align_chunk
integer(c_int), parameter nc_last
integer(c_int), parameter, public nc_float
integer(c_int), parameter nc_format_netcdf4_classic
subroutine nf_return_native_coord_bounds(ncfile)
subroutine, public netcdf_get_variable_id_for_variable(ncfile, variable_name, variable_id)
integer(c_int), parameter nc_by
subroutine nf_get_variable_array_short(ncfile, inc_varid, inc_start, inc_count, inc_stride, inc_vars)
integer(c_int), parameter nc_uint64
integer(c_int), parameter nc_strict_nc3
integer(c_int), parameter noleap_year
subroutine, public netcdf_rewrite_attribute(ncfile, svariablename, sattributename, sattributevalue, iattributevalue, rattributevalue, dpattributevalue)
subroutine, public netcdf_deallocate_data_struct(ncfile)
integer(c_int), parameter leap_year
integer(c_int), parameter nc_nofill
integer(c_size_t) function nf_julian_day_to_index_adj(ncfile, rjulianday)
subroutine nf_put_lat_and_lon(ncfile, dplat, dplon)
subroutine nf_get_variable_array_float(ncfile, inc_varid, inc_start, inc_count, inc_stride, rnc_vars)
integer(c_int), parameter nc_na_int
Provides Fortran interfaces to the NetCDF C API. This approach is much more straightforward than usin...
subroutine, public create_attributes_from_proj4_string(proj4_string, attribute_name_list, attribute_value_list)