Skip to content

Commit

Permalink
Separate the namelist read routine and netcdf error
Browse files Browse the repository at this point in the history
routines into their own library.

Write a unit test for the namelist read routine.

Fixes ufs-community#944.
  • Loading branch information
George Gayno committed Sep 26, 2024
1 parent a3237fb commit e17b8d8
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 50 deletions.
16 changes: 10 additions & 6 deletions sorc/ocean_merge.fd/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
list(APPEND fortran_src
merge_lake_ocnmsk.f90
)
set(lib_src utils.F90 namelist.F90)
set(exe_src merge_lake_ocnmsk.F90)

if(CMAKE_Fortran_COMPILER_ID MATCHES "^(Intel)$")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8 -i4 -convert big_endian")
Expand All @@ -12,12 +11,17 @@ elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^(GNU)$")
endif()

set(exe_name ocean_merge)
add_executable(${exe_name} ${fortran_src})

add_library(om_lib STATIC ${lib_src})
add_executable(${exe_name} ${exe_src})

target_link_libraries(
${exe_name}

om_lib
PUBLIC
NetCDF::NetCDF_Fortran)

target_link_libraries(${exe_name} PRIVATE om_lib)

install(TARGETS ${exe_name})

# If doxygen documentation we enabled, build it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,47 +138,3 @@ program merge_lake_ocnmsk
write(*,'(a,i8,a,i8,a)') 'total lake point ',lake_pt,' where ',nodp_pt,' has no depth'

end program merge_lake_ocnmsk

!> Handle netCDF errors.
!!
!! @param[in] ret NetCDF return code.
!! @author Shan Sun
subroutine handle_err (ret)
use netcdf
integer, intent(in) :: ret

if (ret /= NF90_NOERR) then
write(6,*) nf90_strerror (ret)
stop 999
end if
end subroutine handle_err

!> Read program namelist.
!!
!! @param[out] ocean_mask_dir Directory containing MOM6 ocean mask file.
!! @param[out] lake_mask_dir Directory containing the lake mask file.
!! @param[out] out_dir Directory where output file will be written.
!! @param[out] atmres Atmosphere grid resolution.
!! @param[out] ocnres Ocean grid resolution.
!! @param[out] binary_lake or fractional lake
!! @author Rahul Mahajan
!! @author Sanath Kumar
subroutine read_nml(ocean_mask_dir, lake_mask_dir, atmres,ocnres,out_dir,binary_lake)

integer :: unit=7, io_status

character(len=120), intent(out) :: ocean_mask_dir
character(len=120), intent(out) :: lake_mask_dir
character(len=120), intent(out) :: out_dir
character(len=10), intent(out) :: atmres,ocnres
integer, intent(out):: binary_lake

namelist/mask_nml/ocean_mask_dir, lake_mask_dir, atmres, ocnres,out_dir,binary_lake
open(unit=unit, file='input.nml', iostat=io_status )
read(unit,mask_nml, iostat=io_status )
close(unit)
if (io_status > 0) then
print *,'Error reading input.nml'
call handle_err(-1)
end if
end subroutine read_nml
29 changes: 29 additions & 0 deletions sorc/ocean_merge.fd/namelist.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
!> Read program namelist.
!!
!! @param[out] ocean_mask_dir Directory containing MOM6 ocean mask file.
!! @param[out] lake_mask_dir Directory containing the lake mask file.
!! @param[out] out_dir Directory where output file will be written.
!! @param[out] atmres Atmosphere grid resolution.
!! @param[out] ocnres Ocean grid resolution.
!! @param[out] binary_lake or fractional lake
!! @author Rahul Mahajan
!! @author Sanath Kumar
subroutine read_nml(ocean_mask_dir, lake_mask_dir, atmres,ocnres,out_dir,binary_lake)

integer :: unit=7, io_status

character(len=120), intent(out) :: ocean_mask_dir
character(len=120), intent(out) :: lake_mask_dir
character(len=120), intent(out) :: out_dir
character(len=10), intent(out) :: atmres,ocnres
integer, intent(out):: binary_lake

namelist/mask_nml/ocean_mask_dir, lake_mask_dir, atmres, ocnres,out_dir,binary_lake
open(unit=unit, file='input.nml', iostat=io_status )
read(unit,mask_nml, iostat=io_status )
close(unit)
if (io_status > 0) then
print *,'Error reading input.nml'
call handle_err(-1)
end if
end subroutine read_nml
13 changes: 13 additions & 0 deletions sorc/ocean_merge.fd/utils.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
!> Handle netCDF errors.
!!
!! @param[in] ret NetCDF return code.
!! @author Shan Sun
subroutine handle_err (ret)
use netcdf
integer, intent(in) :: ret

if (ret /= NF90_NOERR) then
write(6,*) nf90_strerror (ret)
stop 999
end if
end subroutine handle_err
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ add_subdirectory(sfc_climo_gen)
add_subdirectory(cpld_gridgen)
add_subdirectory(emcsfc_snow2mdl)
add_subdirectory(ocnice_prep)
add_subdirectory(ocean_merge)
21 changes: 21 additions & 0 deletions tests/ocean_merge/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# This is the cmake build file for the tests directory of the
# UFS_UTILS project.
#
# George Gayno

if(CMAKE_Fortran_COMPILER_ID MATCHES "^(Intel)$")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8 -assume byterecl")
elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^(GNU)$")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-0 -fdefault-real-8")
endif()

# Copy necessary test files from the source data directory to the
# build data directory.

execute_process( COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/data/input.nml ${CMAKE_CURRENT_BINARY_DIR}/input.nml)

add_executable(ftst_read_nml ftst_read_nml.F90)
target_link_libraries(ftst_read_nml om_lib)

add_test(NAME ocean_merge-ftst_read_nml COMMAND ftst_read_nml)
8 changes: 8 additions & 0 deletions tests/ocean_merge/data/input.nml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
&mask_nml
ocean_mask_dir="/ocean/mask/dir"
ocnres="mx025"
lake_mask_dir="/lake/mask/dir"
atmres="C96"
out_dir="/out/dir"
binary_lake=1
/
29 changes: 29 additions & 0 deletions tests/ocean_merge/ftst_read_nml.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
! Unit test for the read_nml routine.

program read_namelist

implicit none

character(len=120) :: ocean_mask_dir
character(len=120) :: lake_mask_dir
character(len=120) :: out_dir
character(len=10) :: atmres,ocnres

integer :: binary_lake

print*,"Call routine read_nml."

call read_nml(ocean_mask_dir, lake_mask_dir, atmres,ocnres,out_dir,binary_lake)

if (trim(ocean_mask_dir) /= "/ocean/mask/dir") stop 2
if (trim(lake_mask_dir) /= "/lake/mask/dir") stop 4
if (trim(atmres) /= "C96") stop 6
if (trim(ocnres) /= "mx025") stop 8
if (trim(out_dir) /= "/out/dir") stop 8
if (binary_lake /= 1) stop 10

print*, "OK"

print*, "SUCCESS!"

end program read_namelist

0 comments on commit e17b8d8

Please sign in to comment.