7 integer :: num_vars = 0
8 integer :: current_var = 0
9 integer, dimension(:), pointer :: varids => null()
10 integer :: unlimited_dimid
11 end type input_handle_type
14 character (len=64) :: name
15 logical :: isTimeDependent = .false.
19 character (len=64), dimension(:), pointer :: dimnames
20 integer, dimension(:), pointer :: dimlens
21 integer, dimension(:), pointer :: dimids
22 type (input_handle_type), pointer :: file_handle
24 ! Members to store field data
26 real, dimension(:), pointer :: array1r => null()
27 real, dimension(:,:), pointer :: array2r => null()
28 real, dimension(:,:,:), pointer :: array3r => null()
29 real, dimension(:,:,:,:), pointer :: array4r => null()
30 double precision :: array0d
31 double precision, dimension(:), pointer :: array1d => null()
32 double precision, dimension(:,:), pointer :: array2d => null()
33 double precision, dimension(:,:,:), pointer :: array3d => null()
34 double precision, dimension(:,:,:,:), pointer :: array4d => null()
36 integer, dimension(:), pointer :: array1i => null()
37 integer, dimension(:,:), pointer :: array2i => null()
38 integer, dimension(:,:,:), pointer :: array3i => null()
39 end type input_field_type
41 integer, parameter :: FIELD_TYPE_UNSUPPORTED = -1, &
42 FIELD_TYPE_REAL = 1, &
43 FIELD_TYPE_DOUBLE = 2, &
44 FIELD_TYPE_INTEGER = 3, &
45 FIELD_TYPE_CHARACTER = 4
51 integer function scan_input_open(filename, handle, nRecords) result(stat)
55 character (len=*), intent(in) :: filename
56 type (input_handle_type), intent(out) :: handle
57 integer, intent(out), optional :: nRecords
63 stat = nf90_open(trim(filename), NF90_NOWRITE, handle % ncid)
64 if (stat /= NF90_NOERR) then
69 stat = nf90_inquire(handle % ncid, nVariables=handle % num_vars)
70 if (stat /= NF90_NOERR) then
75 allocate(handle % varids(handle % num_vars))
77 #ifdef HAVE_NF90_INQ_VARIDS
78 stat = nf90_inq_varids(handle % ncid, handle % num_vars, handle % varids)
79 if (stat /= NF90_NOERR) then
84 ! Newer versions of the netCDF4 library (perhaps newer than 4.2.0?)
85 ! provide a function to return a list of all variable IDs in a file; if
86 ! we are using an older version of the netCDF library, we can apparently
87 ! assume that the variable IDs are numbered 1 through nVars.
88 ! See http://www.unidata.ucar.edu/software/netcdf/docs/tutorial_ncids.html
89 do i=1,handle % num_vars
90 handle % varids(i) = i
94 stat = nf90_inquire(handle % ncid, unlimitedDimId=handle % unlimited_dimid)
95 if (stat /= NF90_NOERR) then
100 if (present(nRecords)) then
101 stat = nf90_inquire_dimension(handle % ncid, handle % unlimited_dimid, len=nRecords)
102 if (stat /= NF90_NOERR) then
107 ! In case we have an input file that no time-varying records but
108 ! does have time-invariant fields, set nRecords = 1 so that we can
109 ! at least extract these fields
110 if ((nRecords == 0) .and. (handle % num_vars > 0)) then
115 handle % current_var = 1
117 end function scan_input_open
120 integer function scan_input_close(handle) result(stat)
124 type (input_handle_type), intent(inout) :: handle
129 stat = nf90_close(handle % ncid)
130 if (stat /= NF90_NOERR) then
134 if (associated(handle % varids)) then
135 deallocate(handle % varids)
137 handle % current_var = 0
139 end function scan_input_close
142 integer function scan_input_rewind(handle) result(stat)
146 type (input_handle_type), intent(inout) :: handle
151 handle % current_var = 1
153 end function scan_input_rewind
156 integer function scan_input_next_field(handle, field) result(stat)
160 type (input_handle_type), intent(inout), target :: handle
161 type (input_field_type), intent(out) :: field
168 if (handle % current_var < 1 .or. handle % current_var > handle % num_vars) then
173 field % varid = handle % varids(handle % current_var)
174 stat = nf90_inquire_variable(handle % ncid, field % varid, &
176 xtype=field % xtype, &
178 if (stat /= NF90_NOERR) then
183 if (field % xtype == NF90_FLOAT) then
184 field % xtype = FIELD_TYPE_REAL
185 else if (field % xtype == NF90_DOUBLE) then
186 field % xtype = FIELD_TYPE_DOUBLE
187 else if (field % xtype == NF90_INT) then
188 field % xtype = FIELD_TYPE_INTEGER
189 else if (field % xtype == NF90_CHAR) then
190 field % xtype = FIELD_TYPE_CHARACTER
192 field % xtype = FIELD_TYPE_UNSUPPORTED
195 allocate(field % dimids(field % ndims))
197 stat = nf90_inquire_variable(handle % ncid, field % varid, &
198 dimids=field % dimids)
199 if (stat /= NF90_NOERR) then
201 deallocate(field % dimids)
205 allocate(field % dimlens(field % ndims))
206 allocate(field % dimnames(field % ndims))
208 do idim=1,field % ndims
209 stat = nf90_inquire_dimension(handle % ncid, field % dimids(idim), &
210 name=field % dimnames(idim), &
211 len=field % dimlens(idim))
212 if (field % dimids(idim) == handle % unlimited_dimid) then
213 field % isTimeDependent = .true.
217 field % file_handle => handle
219 handle % current_var = handle % current_var + 1
221 end function scan_input_next_field
224 integer function scan_input_for_field(handle, fieldname, field) result(stat)
228 type (input_handle_type), intent(inout), target :: handle
229 character (len=*), intent(in) :: fieldname
230 type (input_field_type), intent(out) :: field
236 stat = nf90_inq_varid(handle % ncid, trim(fieldname), field % varid)
237 if (stat /= NF90_NOERR) then
242 stat = nf90_inquire_variable(handle % ncid, field % varid, &
244 xtype=field % xtype, &
246 if (stat /= NF90_NOERR) then
251 if (field % xtype == NF90_FLOAT) then
252 field % xtype = FIELD_TYPE_REAL
253 else if (field % xtype == NF90_DOUBLE) then
254 field % xtype = FIELD_TYPE_DOUBLE
255 else if (field % xtype == NF90_INT) then
256 field % xtype = FIELD_TYPE_INTEGER
257 else if (field % xtype == NF90_CHAR) then
258 field % xtype = FIELD_TYPE_CHARACTER
260 field % xtype = FIELD_TYPE_UNSUPPORTED
263 allocate(field % dimids(field % ndims))
265 stat = nf90_inquire_variable(handle % ncid, field % varid, &
266 dimids=field % dimids)
267 if (stat /= NF90_NOERR) then
269 deallocate(field % dimids)
273 allocate(field % dimlens(field % ndims))
274 allocate(field % dimnames(field % ndims))
276 do idim=1,field % ndims
277 stat = nf90_inquire_dimension(handle % ncid, field % dimids(idim), &
278 name=field % dimnames(idim), &
279 len=field % dimlens(idim))
280 if (field % dimids(idim) == handle % unlimited_dimid) then
281 field % isTimeDependent = .true.
285 field % file_handle => handle
287 end function scan_input_for_field
290 integer function scan_input_read_field(field, frame) result(stat)
294 type (input_field_type), intent(inout) :: field
295 integer, intent(in), optional :: frame
297 integer :: local_frame
298 integer, dimension(5) :: start, count
299 real, dimension(1) :: temp1r
300 double precision, dimension(1) :: temp1d
301 integer, dimension(1) :: temp1i
307 if (present(frame)) then
311 if (field % xtype == FIELD_TYPE_REAL) then
312 if (field % ndims == 0 .or. (field % ndims == 1 .and. field % isTimeDependent)) then
313 if (field % isTimeDependent) then
314 start(1) = local_frame
316 stat = nf90_get_var(field % file_handle % ncid, field % varid, temp1r, &
317 start=start(1:1), count=count(1:1))
318 field % array0r = temp1r(1)
320 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array0r)
322 else if (field % ndims == 1 .or. (field % ndims == 2 .and. field % isTimeDependent)) then
323 if (field % isTimeDependent) then
325 count(1) = field % dimlens(1)
326 start(2) = local_frame
328 allocate(field % array1r(count(1)))
329 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array1r, &
330 start=start(1:2), count=count(1:2))
332 allocate(field % array1r(field%dimlens(1)))
333 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array1r)
335 else if (field % ndims == 2 .or. (field % ndims == 3 .and. field % isTimeDependent)) then
336 if (field % isTimeDependent) then
338 count(1) = field % dimlens(1)
340 count(2) = field % dimlens(2)
341 start(3) = local_frame
343 allocate(field % array2r(count(1),count(2)))
344 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array2r, &
345 start=start(1:3), count=count(1:3))
347 allocate(field % array2r(field%dimlens(1),field%dimlens(2)))
348 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array2r)
350 else if (field % ndims == 3 .or. (field % ndims == 4 .and. field % isTimeDependent)) then
351 if (field % isTimeDependent) then
353 count(1) = field % dimlens(1)
355 count(2) = field % dimlens(2)
357 count(3) = field % dimlens(3)
358 start(4) = local_frame
360 allocate(field % array3r(count(1),count(2),count(3)))
361 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array3r, &
362 start=start(1:4), count=count(1:4))
364 allocate(field % array3r(field%dimlens(1),field%dimlens(2),field%dimlens(3)))
365 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array3r)
367 else if (field % ndims == 4 .or. (field % ndims == 5 .and. field % isTimeDependent)) then
368 if (field % isTimeDependent) then
370 count(1) = field % dimlens(1)
372 count(2) = field % dimlens(2)
374 count(3) = field % dimlens(3)
376 count(4) = field % dimlens(4)
377 start(5) = local_frame
379 allocate(field % array4r(count(1),count(2),count(3),count(4)))
380 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array4r, &
381 start=start(1:5), count=count(1:5))
383 allocate(field % array4r(field%dimlens(1),field%dimlens(2),field%dimlens(3),field%dimlens(4)))
384 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array4r)
387 else if (field % xtype == FIELD_TYPE_DOUBLE) then
388 if (field % ndims == 0 .or. (field % ndims == 1 .and. field % isTimeDependent)) then
389 if (field % isTimeDependent) then
390 start(1) = local_frame
392 stat = nf90_get_var(field % file_handle % ncid, field % varid, temp1d, &
393 start=start(1:1), count=count(1:1))
394 field % array0d = temp1d(1)
396 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array0d)
398 else if (field % ndims == 1 .or. (field % ndims == 2 .and. field % isTimeDependent)) then
399 if (field % isTimeDependent) then
401 count(1) = field % dimlens(1)
402 start(2) = local_frame
404 allocate(field % array1d(count(1)))
405 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array1d, &
406 start=start(1:2), count=count(1:2))
408 allocate(field % array1d(field%dimlens(1)))
409 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array1d)
411 else if (field % ndims == 2 .or. (field % ndims == 3 .and. field % isTimeDependent)) then
412 if (field % isTimeDependent) then
414 count(1) = field % dimlens(1)
416 count(2) = field % dimlens(2)
417 start(3) = local_frame
419 allocate(field % array2d(count(1),count(2)))
420 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array2d, &
421 start=start(1:3), count=count(1:3))
423 allocate(field % array2d(field%dimlens(1),field%dimlens(2)))
424 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array2d)
426 else if (field % ndims == 3 .or. (field % ndims == 4 .and. field % isTimeDependent)) then
427 if (field % isTimeDependent) then
429 count(1) = field % dimlens(1)
431 count(2) = field % dimlens(2)
433 count(3) = field % dimlens(3)
434 start(4) = local_frame
436 allocate(field % array3d(count(1),count(2),count(3)))
437 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array3d, &
438 start=start(1:4), count=count(1:4))
440 allocate(field % array3d(field%dimlens(1),field%dimlens(2),field%dimlens(3)))
441 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array3d)
443 else if (field % ndims == 4 .or. (field % ndims == 5 .and. field % isTimeDependent)) then
444 if (field % isTimeDependent) then
446 count(1) = field % dimlens(1)
448 count(2) = field % dimlens(2)
450 count(3) = field % dimlens(3)
452 count(4) = field % dimlens(4)
453 start(5) = local_frame
455 allocate(field % array4d(count(1),count(2),count(3),count(4)))
456 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array4d, &
457 start=start(1:5), count=count(1:5))
459 allocate(field % array4d(field%dimlens(1),field%dimlens(2),field%dimlens(3),field%dimlens(4)))
460 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array4d)
464 else if (field % xtype == FIELD_TYPE_INTEGER) then
465 if (field % ndims == 0 .or. (field % ndims == 1 .and. field % isTimeDependent)) then
466 if (field % isTimeDependent) then
467 start(1) = local_frame
469 stat = nf90_get_var(field % file_handle % ncid, field % varid, temp1i, &
470 start=start(1:1), count=count(1:1))
471 field % array0i = temp1i(1)
473 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array0i)
475 else if (field % ndims == 1 .or. (field % ndims == 2 .and. field % isTimeDependent)) then
476 if (field % isTimeDependent) then
478 count(1) = field % dimlens(1)
479 start(2) = local_frame
481 allocate(field % array1i(count(1)))
482 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array1i, &
483 start=start(1:2), count=count(1:2))
485 allocate(field % array1i(field%dimlens(1)))
486 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array1i)
488 else if (field % ndims == 2 .or. (field % ndims == 3 .and. field % isTimeDependent)) then
489 if (field % isTimeDependent) then
491 count(1) = field % dimlens(1)
493 count(2) = field % dimlens(2)
494 start(3) = local_frame
496 allocate(field % array2i(count(1),count(2)))
497 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array2i, &
498 start=start(1:3), count=count(1:3))
500 allocate(field % array2i(field%dimlens(1),field%dimlens(2)))
501 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array2i)
503 else if (field % ndims == 3 .or. (field % ndims == 4 .and. field % isTimeDependent)) then
504 if (field % isTimeDependent) then
506 count(1) = field % dimlens(1)
508 count(2) = field % dimlens(2)
510 count(3) = field % dimlens(3)
511 start(4) = local_frame
513 allocate(field % array3i(count(1),count(2),count(3)))
514 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array3i, &
515 start=start(1:4), count=count(1:4))
517 allocate(field % array3i(field%dimlens(1),field%dimlens(2),field%dimlens(3)))
518 stat = nf90_get_var(field % file_handle % ncid, field % varid, field % array3i)
522 else if (field % xtype == FIELD_TYPE_CHARACTER) then
524 write(0,*) 'Processing of character fields is not supported; skipping read of field '//trim(field % name)
529 write(0,*) 'Unsupported type; skipping read of field '//trim(field % name)
533 if (stat /= NF90_NOERR) then
535 write(0,*) 'NetCDF error: reading '//trim(field % name)//' returned ', stat
542 end function scan_input_read_field
545 integer function scan_input_free_field(field) result(stat)
549 type (input_field_type), intent(inout) :: field
554 if (associated(field % dimids)) then
555 deallocate(field % dimids)
557 if (associated(field % dimlens)) then
558 deallocate(field % dimlens)
560 if (associated(field % dimnames)) then
561 deallocate(field % dimnames)
564 if (associated(field % array1r)) then
565 deallocate(field % array1r)
567 if (associated(field % array2r)) then
568 deallocate(field % array2r)
570 if (associated(field % array3r)) then
571 deallocate(field % array3r)
573 if (associated(field % array4r)) then
574 deallocate(field % array4r)
577 if (associated(field % array1d)) then
578 deallocate(field % array1d)
580 if (associated(field % array2d)) then
581 deallocate(field % array2d)
583 if (associated(field % array3d)) then
584 deallocate(field % array3d)
586 if (associated(field % array4d)) then
587 deallocate(field % array4d)
590 if (associated(field % array1i)) then
591 deallocate(field % array1i)
593 if (associated(field % array2i)) then
594 deallocate(field % array2i)
596 if (associated(field % array3i)) then
597 deallocate(field % array3i)
600 nullify(field % file_handle)
602 end function scan_input_free_field
604 end module scan_input