Skip to content

Commit d140c38

Browse files
committed
add nc4version function
1 parent e54c20c commit d140c38

File tree

6 files changed

+135
-79
lines changed

6 files changed

+135
-79
lines changed

API.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# nc4fortran Usage
2+
3+
All examples assume:
4+
5+
```fortran
6+
use nc4fortran, only: netcdf_file
7+
type(netcdf_file) :: hf
8+
```
9+
10+
* gzip compression may be applied for rank ≥ 2 arrays by setting `comp_lvl` to a value between 1 and 9.
11+
Shuffle filter is automatically applied for better compression
12+
* string attributes may be applied to any variable at time of writing or later.
13+
14+
Check NetCDF4 library version:
15+
16+
```fortran
17+
use nc4fortran, only: nc4version
18+
print *, nc4version()
19+
```
20+
21+
Create new NetCDF file, with variable "value1"
22+
23+
```fortran
24+
call hf%open('test.nc', action='w')
25+
26+
call hf%write('value1', 123.)
27+
28+
call hf%close()
29+
```
30+
31+
Check if variable exists
32+
33+
```fortran
34+
logical :: exists
35+
36+
exists = hf%exist('fooname')
37+
```
38+
39+
Add/append variable "value1" to existing NetCDF file "test.nc"
40+
41+
* if file `test.nc` exists, add a variable to it
42+
* if file `test.nc` does not exist, create it and add a variable to it.
43+
44+
```fortran
45+
call hf%open('test.nc', action='rw')
46+
47+
call hf%write('value1', 123.)
48+
49+
call hf%close()
50+
```
51+
52+
Read scalar, 3-D array of unknown size
53+
54+
```fortran
55+
call ncf%open('test.nc', action='r')
56+
57+
integer, allocatable :: dims(:)
58+
real, allocatable :: A(:,:,:)
59+
60+
call ncf%shape('foo', dims)
61+
allocate(A(dims(1), dims(2), dims(3)))
62+
call ncf%read('foo', A)
63+
64+
call ncf%close()
65+
```

README.md

Lines changed: 4 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Tested on systems with NetCDF4 including:
3232
* Windows Subsystem for Linux
3333
* Windows Cygwin
3434

35+
See [API](./API.md) for usage.
36+
3537
## Build
3638

3739
Requirements:
@@ -78,7 +80,7 @@ include(FetchContent)
7880
7981
FetchContent_Declare(nc4fortran_proj
8082
GIT_REPOSITORY https://github.com/geospace-code/nc4fortran.git
81-
GIT_TAG v1.3.0)
83+
GIT_TAG v1.5.0)
8284
8385
FetchContent_MakeAvailable(nc4fortran_proj)
8486
@@ -113,73 +115,7 @@ and have a file in the master project `subprojects/nc4fortran.wrap` containing:
113115
[wrap-git]
114116
directory = nc4fortran
115117
url = https://github.com/geospace-code/nc4fortran.git
116-
revision = head
117-
```
118-
119-
## Usage
120-
121-
All examples assume:
122-
123-
```fortran
124-
use nc4fortran, only: netcdf_file
125-
type(netcdf_file) :: hf
126-
```
127-
128-
* gzip compression may be applied for rank ≥ 2 arrays by setting `comp_lvl` to a value between 1 and 9.
129-
Shuffle filter is automatically applied for better compression
130-
* string attributes may be applied to any variable at time of writing or later.
131-
132-
`integer, intent(out) :: ierr` is optional.
133-
It will be non-zero if error detected.
134-
This value should be checked, particularly for write operations to avoid missing error conditions.
135-
If `ierr` is omitted, nc4fortran will `error stop` on error.
136-
137-
### Create new NetCDF file, with variable "value1"
138-
139-
```fortran
140-
call hf%open('test.nc', action='w')
141-
142-
call hf%write('value1', 123.)
143-
144-
call hf%close()
145-
```
146-
147-
### Check if variable exists
148-
149-
This will not raise error stop, even if the file isn't opened, but it will print a message to stderr.
150-
151-
```fortran
152-
logical :: exists
153-
154-
exists = hf%exist('fooname')
155-
```
156-
157-
### Add/append variable "value1" to existing NetCDF file "test.nc"
158-
159-
* if file `test.nc` exists, add a variable to it
160-
* if file `test.nc` does not exist, create it and add a variable to it.
161-
162-
```fortran
163-
call hf%open('test.nc', action='rw')
164-
165-
call hf%write('value1', 123.)
166-
167-
call hf%close()
168-
```
169-
170-
### Read scalar, 3-D array of unknown size
171-
172-
```fortran
173-
call ncf%open('test.nc', action='r')
174-
175-
integer, allocatable :: dims(:)
176-
real, allocatable :: A(:,:,:)
177-
178-
call ncf%shape('foo', dims)
179-
allocate(A(dims(1), dims(2), dims(3)))
180-
call ncf%read('foo', A)
181-
182-
call ncf%close()
118+
revision = v1.5.0
183119
```
184120

185121
## Permissive syntax

src/interface.f90

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module nc4fortran
1212

1313
implicit none (type, external)
1414
private
15-
public :: netcdf_file, NF90_MAX_NAME, NF90_NOERR, check_error, is_netcdf, nc_exist
15+
public :: netcdf_file, NF90_MAX_NAME, NF90_NOERR, check_error, is_netcdf, nc_exist, nc4version
1616

1717
!! at this time, we assume up to 7 dimension NetCDF variable.
1818
integer, parameter :: NC_MAXDIM = 7
@@ -28,7 +28,6 @@ module nc4fortran
2828
logical :: debug = .false.
2929
logical :: is_open = .false.
3030
!! will be auto-deleted on close
31-
character(80) :: libversion
3231

3332
contains
3433

@@ -240,9 +239,6 @@ subroutine nc_initialize(self, filename, action, comp_lvl, verbose, debug)
240239
if (present(verbose)) self%verbose = verbose
241240
if (present(debug)) self%debug = debug
242241

243-
!> get library version
244-
self%libversion = nf90_inq_libvers()
245-
246242
laction = 'rw'
247243
if(present(action)) laction = action
248244

@@ -307,6 +303,13 @@ subroutine nc_finalize(self)
307303
end subroutine nc_finalize
308304

309305

306+
function nc4version()
307+
!! get NetCDF4 library version
308+
character(:), allocatable :: nc4version
309+
nc4version = nf90_inq_libvers()
310+
end function nc4version
311+
312+
310313
subroutine nc_flush(self)
311314

312315
class(netcdf_file), intent(in) :: self

src/tests/CMakeLists.txt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,22 @@ FIXTURES_SETUP nclib
1111
LABELS core
1212
)
1313

14-
foreach(t array attributes deflate destructor error exist scalar shape string)
14+
foreach(t array attributes deflate destructor error exist scalar shape string version)
1515
add_executable(test_${t} test_${t}.f90)
1616
target_link_libraries(test_${t} PRIVATE nc4fortran::nc4fortran)
1717
set_target_properties(test_${t} PROPERTIES LABELS unit)
1818
target_compile_options(test_${t} PRIVATE "$<$<Fortran_COMPILER_ID:GNU>:-Wno-compare-reals>")
1919

20-
add_test(NAME ${t}
21-
COMMAND test_${t}
22-
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
23-
)
20+
if(${t} STREQUAL version)
21+
add_test(NAME ${t} COMMAND test_${t} ${NetCDF_VERSION})
22+
else()
23+
add_test(NAME ${t} COMMAND test_${t})
24+
endif()
25+
2426
set_tests_properties(${t} PROPERTIES
2527
FIXTURES_REQUIRED nclib
2628
LABELS unit
29+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
2730
)
2831
endforeach()
2932

src/tests/meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ test('minimal', test_minimal,
66
priority: 100,
77
timeout: 10)
88

9-
foreach t : ['array', 'attributes', 'deflate', 'destructor', 'error', 'exist', 'scalar', 'shape', 'string']
9+
foreach t : ['array', 'attributes', 'deflate', 'destructor', 'error', 'exist', 'scalar', 'shape', 'string', 'version']
1010

1111
e = executable('test_'+t, 'test_' + t + '.f90', dependencies: netcdf_interface, fortran_args: quiet)
1212
if t == 'shape'

src/tests/test_version.f90

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
program test_version
2+
!! tests that NetCDF4 library version is available
3+
4+
use nc4fortran, only : nc4version
5+
6+
implicit none (type, external)
7+
8+
character(24) :: vstr, v
9+
character(:), allocatable :: libver, compver
10+
integer :: i
11+
12+
v = nc4version()
13+
14+
print '(A)', v
15+
16+
if(command_argument_count() < 1) stop
17+
18+
call get_command_argument(1, vstr, status=i)
19+
if (i/=0) error stop "input version string to compare"
20+
21+
compver = get_version_mmr(vstr)
22+
libver = get_version_mmr(v)
23+
if (compver /= libver) error stop "version mismatch: " // compver // " /= " // libver
24+
25+
contains
26+
27+
pure function get_version_mmr(v)
28+
!! get the major.minor.release part of a version string
29+
!! cuts off further patch and arbitrary text
30+
character(:), allocatable :: get_version_mmr
31+
character(*), intent(in) :: v
32+
33+
integer :: i, j, k, e
34+
35+
k = index(v, '.')
36+
j = index(v(k+1:), '.')
37+
i = scan(v(k+j+1:), '.-_ ')
38+
if (i == 0) then
39+
e = len_trim(v)
40+
else
41+
e = k + j + i - 1
42+
end if
43+
44+
get_version_mmr = v(:e)
45+
46+
end function get_version_mmr
47+
48+
49+
end program

0 commit comments

Comments
 (0)