Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit test for existing point output I/O code #1158

Merged
merged 25 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions .github/workflows/io_gnu_yml.old
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: io_gnu
on: [push, pull_request, workflow_dispatch]

# Cancel in-progress workflows when pushing to a branch
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
cache_key: gnu11-1
CC: gcc-10
FC: gfortran-10
CXX: g++-10


# Split into a steup step, and a WW3 build step which
# builds multiple switches in a matrix. The setup is run once and
# the environment is cached so each build of WW3 can share the dependencies.

jobs:
setup:
runs-on: ubuntu-latest

steps:
- name: checkout-ww3
if: steps.cache-env.outputs.cache-hit != 'true'
uses: actions/checkout@v3
with:
path: ww3
# Cache spack, OASIS, and compiler
# No way to flush Action cache, so key may have # appended
- name: cache-env
id: cache-env
uses: actions/cache@v3
with:
path: |
spack
~/.spack
work_oasis3-mct
key: spack-${{ runner.os }}-${{ env.cache_key }}-${{ hashFiles('ww3/model/ci/spack_gnu.yaml') }}

# Build WW3 spack environment
- name: install-dependencies-with-spack
if: steps.cache-env.outputs.cache-hit != 'true'
run: |
# Install NetCDF, ESMF, g2, etc using Spack
sudo apt install cmake
git clone -c feature.manyFiles=true https://github.com/JCSDA/spack.git
source spack/share/spack/setup-env.sh
spack env create ww3-gnu ww3/model/ci/spack_gnu.yaml
spack env activate ww3-gnu
spack compiler find
spack external find cmake
spack add [email protected]
spack concretize
spack install --dirty -v

- name: build-oasis
if: steps.cache-env.outputs.cache-hit != 'true'
run: |
source spack/share/spack/setup-env.sh
spack env activate ww3-gnu
export WWATCH3_DIR=${GITHUB_WORKSPACE}/ww3/model
export OASIS_INPUT_PATH=${GITHUB_WORKSPACE}/ww3/regtests/ww3_tp2.14/input/oasis3-mct
export OASIS_WORK_PATH=${GITHUB_WORKSPACE}/ww3/regtests/ww3_tp2.14/input/work_oasis3-mct
cd ww3/regtests/ww3_tp2.14/input/oasis3-mct/util/make_dir
cmake .
make VERBOSE=1
cp -r ${GITHUB_WORKSPACE}/ww3/regtests/ww3_tp2.14/input/work_oasis3-mct ${GITHUB_WORKSPACE}

io_gnu:
needs: setup
runs-on: ubuntu-latest

steps:
- name: install-dependencies
run: |
sudo apt-get update
sudo apt-get install doxygen gcovr valgrind

- name: checkout-ww3
uses: actions/checkout@v3
with:
path: ww3

- name: cache-env
id: cache-env
uses: actions/cache@v3
with:
path: |
spack
~/.spack
work_oasis3-mct
key: spack-${{ runner.os }}-${{ env.cache_key }}-${{ hashFiles('ww3/model/ci/spack_gnu.yaml') }}

- name: build-ww3
run: |
source spack/share/spack/setup-env.sh
spack env activate ww3-gnu
set -x
cd ww3
export CC=mpicc
export FC=mpif90
export OASISDIR=${GITHUB_WORKSPACE}/work_oasis3-mct
mkdir build && cd build
export LD_LIBRARY_PATH="/home/runner/work/WW3/WW3/spack/var/spack/environments/ww3-gnu/.spack-env/view/:$LD_LIBRARY_PATH"
cmake -DSWITCH=${GITHUB_WORKSPACE}/ww3/regtests/unittests/data/switch.io -DCMAKE_BUILD_TYPE=Debug -DCMAKE_Fortran_FLAGS="-g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0 -Wall -fno-omit-frame-pointer -fsanitize=address" -DCMAKE_C_FLAGS="-g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0 -Wall -fno-omit-frame-pointer -fsanitize=address" ..
make -j2 VERBOSE=1
./bin/ww3_grid
mv mod_def.ww3 regtests/unittests
ctest --verbose --output-on-failure --rerun-failed
gcovr --root .. -v --html-details --exclude ../regtests/unittests --exclude CMakeFiles --print-summary -o test-coverage.html &> /dev/null

- name: upload-test-coverage
uses: actions/upload-artifact@v3
with:
name: ww3-test-coverage
path: |
ww3/build/*.html
ww3/build/*.css


6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,9 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)$")
endif()

add_subdirectory(model)

# Turn on unit testing.
include(CTest)
if(BUILD_TESTING)
add_subdirectory(regtests/unittests)
endif()
39 changes: 39 additions & 0 deletions regtests/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This is the CMake file for the model/tests directory in the WW3
# project.
#
# Ed Hartnett, 10/14/23

# Some very small test files may be committed to the repo. This
# function copies such a data file to the build directory.
function(copy_test_data name)
message(STATUS "Copying ${name} to ${CMAKE_CURRENT_BINARY_DIR}")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/data/${name}"
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
endfunction()

# Some very small test files may be committed to the repo. This
# function copies such a data file to the build directory.
function(copy_test_data_2 srcname destname)
message(STATUS "Copying ${srcname} to ${CMAKE_CURRENT_BINARY_DIR}/${destname}")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/data/${srcname}"
DESTINATION "${CMAKE_BINARY_DIR}"
FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
file(RENAME "${CMAKE_BINARY_DIR}/${srcname}" "${CMAKE_BINARY_DIR}/${destname}")
endfunction()

# Function to build and run a test.
function(unit_test name)
add_executable(${name} ${name}.F90)
target_link_libraries(${name} PRIVATE ww3_lib)
add_test(NAME ${name} COMMAND ${name})
endfunction()

# Copy test data files that are in the repo to the build directory.
copy_test_data(switch.io)
copy_test_data_2(ww3_grid.inp ww3_grid.inp)

# Build and run the tests.
unit_test(test_io_points_bin)


1 change: 1 addition & 0 deletions regtests/unittests/data/switch.io
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NOGRB SHRD PR1 FLX2 LN0 ST0 NL0 BT0 DB0 TR0 BS0 IC0 IS0 REF0 WNT1 WNX1 CRT1 CRX1 O0 O1 O2 O3 O4 O5 O6 O7 O10 O11
48 changes: 48 additions & 0 deletions regtests/unittests/data/ww3_grid.inp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
$ WAVEWATCH III Grid preprocessor input file
$ ------------------------------------------
'1-D REFRACTION X '
$
1.25 0.08 3 24 0.
$
F T F T F F
300. 300. 150. 300.
$
&PRO1 CFLTM = 0.75 /
&PRO2 CFLTM = 0.75 /
&PRO3 CFLTM = 0.75, WDTHCG = 0., WDTHTH = 0. /
&PRO4 CFLTM = 0.75, RNFAC = 0., RSFAC = 0. /
END OF NAMELISTS
$
'RECT' F 'NONE'
13 3
5.E3 5.E3 1.
-5.E3 -5.E3 1.
$
-1. 1. 10 -1. 2 1 '(....)' 'UNIT' 'input'
$
$ First grid
$
50 50 50 45 40 35 30 25 20 15 10 5 0
50 50 50 45 40 35 30 25 20 15 10 5 0
50 50 50 45 40 35 30 25 20 15 10 5 0
$
$ Second grid
$
$ 0 5 10 15 20 25 30 35 40 45 50 50 50
$ 0 5 10 15 20 25 30 35 40 45 50 50 50
$ 0 5 10 15 20 25 30 35 40 45 50 50 50
$
10 1 1 '(....)' 'PART' 'input'
$
$ First grid
$
2 2 F
$
$ Second grid
$
$ 12 2 F
0 0 F
0 0 F
0 0
$
0. 0. 0. 0. 0
8 changes: 8 additions & 0 deletions regtests/unittests/data/ww3_outp.inp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
$
20100101 000000 3600 1
$
1
-1
$
4
2 30 20100101 000000 'UTC'
152 changes: 152 additions & 0 deletions regtests/unittests/test_io_points_bin.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
! This is a test for model IO for WW3. This tests the legacy (binary)
! output of points data, done by function W3IOPO().
!
! Ed Hartnett 10/14/23
program test_io_points_bin
use w3iopomd
use w3gdatmd
use w3wdatmd
use w3odatmd
use w3iogrmd
use w3adatmd
implicit none

integer, target :: i
integer :: ndsop, iotest, ndsbul, ndsm
integer :: ndstrc, ntrace
character*7 expected_ptnme
character*6 my_fmt
real :: expected_loc_1
integer :: write_test_file

print *, 'Testing WW3 binary point file code.'

! These are mysterious but have to be called or else the IPASS
! variable does not exist and w3iopo() crashes.
call w3nmod(1, 6, 6)
call w3setg(1, 6, 6)
call w3ndat(6, 6)
call w3setw(1, 6, 6)
call w3nout(6, 6)
call w3seto(1, 6, 6)

ndsm = 20
ndsop = 20
ndsbul = 0
ndstrc = 6
ntrace = 10

! Create a point output file needed for this test.
if (write_test_file() .ne. 0) stop 1

write (ndso,900)
900 FORMAT (/15X,' *** WAVEWATCH III Point output post.*** '/ &
15X,'==============================================='/)

! 2. Read model definition file.
CALL W3IOGR('READ', NDSM)
WRITE (NDSO,920) GNAME
920 FORMAT (' Grid name : ',A/)

! This will not work. But cannot be tested because it will change the value of IPASS,
! call w3iopo('EAD', ndsop, iotest)
! if (iotest .ne. 1) stop 7

! Read the file out_pnt.ww3 from the model/tests/data directory.
call w3iopo('READ', ndsop, iotest)
if (iotest .ne. 0) stop 10
close(ndsop)

! Make sure we got the values we expected.
if (nopts .ne. 11) stop 11
expected_loc_1 = 0.0
do i = 1, nopts
! Check ptnme and ptloc arrays.
print *, ptnme(i), ptloc(1, i), ptloc(2, i)
if (i .lt. 10) then
my_fmt = '(a,i1)'
else
my_fmt = '(a,i2)'
endif
write(fmt = my_fmt, unit=expected_ptnme) 'Point', i
if (ptnme(i) .ne. expected_ptnme) stop 20
print *, expected_loc_1
if (ptloc(1, i) .ne. expected_loc_1) stop 21
expected_loc_1 = expected_loc_1 + 5000.0
if (ptloc(2, i) .ne. 0) stop 22
end do

print *, 'OK!'
print *, 'SUCCESS!'
end program test_io_points_bin

integer function write_test_file()
implicit none

integer :: ntlu, nk, nth, nopts
character(len=10), parameter :: veropt = '2021-04-06'
character(len=31), parameter :: idstr = 'WAVEWATCH III POINT OUTPUT FILE'
real :: ptloc(2,11) = reshape((/ 0., 0., 5000., 0., 10000., 0., 15000., 0., &
20000., 0., 25000., 0., 30000., 0., 35000., 0., 40000., 0., 45000., 0., 50000., 0. /), &
(/ 2, 11 /))
character*40 ptnme(11)
integer :: time(2) = (/ 19680606, 0 /)
integer :: nspec = 72
integer :: iw(11) = (/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /)
integer :: ii(11) = (/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /)
integer :: il(11) = (/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /)
real :: iceo(11) = (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. /)
real :: iceho(11) = (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. /)
real :: icefo(11) = (/ 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000. /)
real :: dpo(11) = (/ 50., 50., 45., 40., 35., 30., 25., 20., 15., 10., 5. /)
real :: wao(11) = (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. /)
real :: wdo(11) = (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. /)
real :: aso(11) = (/ -999.900024, -999.900024, -999.900024, -999.900024, -999.900024, &
-999.900024, -999.900024, -999.900024, -999.900024, -999.900024, -999.900024 /)
real :: cao(11) = (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. /)
real :: cdo(11) = (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. /)
character*13 :: grdid(11)
real :: spco(72, 11)
integer :: i, j
integer :: ierr

! Initialize some values.
ntlu = 21
nk = 3
nth = 24
nopts = 11
do i = 1, nopts
if (i .le. 9) then
write(ptnme(i), '(a,i1)') 'Point', i
else
write(ptnme(i), '(a,i2)') 'Point', i
endif
grdid(i) = 'ww3 '
end do

! Open the file.
open(ntlu, file="out_pnt.ww3", form="unformatted", status="replace", &
action="write", convert="big_endian", iostat=ierr)
if (ierr .ne. 0) stop 111

! Write our values.
write (ntlu, iostat=ierr) idstr, veropt, nk, nth, nopts
if (ierr .ne. 0) stop 112
write (ntlu, iostat=ierr) ((ptloc(j,i),j=1,2),i=1,nopts), (ptnme(i),i=1,nopts)
if (ierr .ne. 0) stop 113
write (ntlu, iostat=ierr) time
if (ierr .ne. 0) stop 114
do i=1, nopts
write (ntlu, iostat=ierr) iw(i), ii(i), il(i), dpo(i), wao(i), wdo(i), &
aso(i), cao(i), cdo(i), iceo(i), iceho(i), &
icefo(i), grdid(i), (spco(j,i),j=1,nspec)
if (ierr .ne. 0) stop 115
enddo

! Close the file.
close(ntlu)

! We're done!
write_test_file = 0
end function write_test_file