Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3f1da61
src/offline/cable_mpi.F90: STOP when MPI is unavailable in mpi_grp_abort
SeanBryan51 Oct 8, 2025
4620bf6
src/offline/cable_mpi.F90: Add legacy communicator procedure overload…
SeanBryan51 Oct 15, 2025
441909b
src/offline/cable_mpi.F90: add mpi_grp_split
SeanBryan51 Oct 27, 2025
d1fea58
Replace abort with cable_abort
SeanBryan51 Oct 8, 2025
a4944ca
Add PIO as an optional dependency
SeanBryan51 Oct 27, 2025
ba5610a
Add parallel I/O abstraction
SeanBryan51 Oct 27, 2025
ad45ef5
Temporary commit (to remove): add unit tests
SeanBryan51 Oct 27, 2025
ef5f448
Add parallel I/O decomp utilities
SeanBryan51 Oct 7, 2025
1b31f68
Allow for selection of legacy MPI or parallel I/O at runtime
SeanBryan51 Oct 27, 2025
0a59cfa
Pass in mpi_grp to the serial and master drivers
SeanBryan51 Oct 27, 2025
362e82b
Introduce global structure variables
SeanBryan51 Oct 12, 2025
d21221a
Introduce local structure variables
SeanBryan51 Oct 27, 2025
a18d437
Add data structure for I/O decompositions
SeanBryan51 Oct 27, 2025
0fc8f64
src/offline/cable_mpimaster_stub.F90: update stub to accept mpi_grp_m…
SeanBryan51 Nov 11, 2025
dfe8a40
src/offline/cable_io_decomp.F90: add int32 and real64 decompositions
SeanBryan51 Nov 11, 2025
781b01d
src/util/netcdf/cable_netcdf_decomp_util.F90: add missing allocations
SeanBryan51 Nov 12, 2025
cbb490e
src/util/netcdf/cable_netcdf.F90: add overloads for put_att and get_att
SeanBryan51 Nov 18, 2025
4cf8d46
src/util/netcdf/cable_netcdf.F90: add redef
SeanBryan51 Dec 8, 2025
6c756eb
src/util/netcdf/cable_netcdf.F90: make dim_names optional
SeanBryan51 Dec 9, 2025
38a9532
src/util/netcdf/cable_netcdf.F90: Add iotype and mode arguments
SeanBryan51 Dec 9, 2025
1fae295
src/util/netcdf/cable_netcdf.F90: Add inq_var_ndims procedure
SeanBryan51 Jan 13, 2026
d7d1dc7
src/offline/cable_parameters.F90: Add comment on init_local_structure…
SeanBryan51 Jan 20, 2026
71af51d
Move `range_abort` from cable_abort.F90 to cable_checks.F90
SeanBryan51 Nov 24, 2025
129d746
src/offline/cable_io_decomp.F90: fix dim specification for 2D patch v…
SeanBryan51 Dec 1, 2025
2b40af7
tests/test_cable_netcdf.F90: specify NetCDF4 format in tests
SeanBryan51 Feb 27, 2026
ce90657
Remove select rank as this is a fortran 2018 feature
SeanBryan51 Feb 27, 2026
182f1d4
src/util/netcdf/nf90/cable_netcdf_nf90.F90: Allocate on decompositio…
SeanBryan51 Feb 27, 2026
e84c25e
Temporary commit: Add parallelio library built with openmpi/4.0.7 to …
SeanBryan51 Mar 1, 2026
c0f1c8e
src/util/netcdf/pio/cable_netcdf_pio.F90: Add optional PIO namelist s…
SeanBryan51 Feb 28, 2026
d84356a
cable_netcdf_decomp_t should be abstract
SeanBryan51 Mar 4, 2026
e9bb8bf
Add base mode IO type
SeanBryan51 Mar 4, 2026
f822f68
tests/fixtures.F90: Remove max string length constant
SeanBryan51 Mar 4, 2026
2023d24
src/util/netcdf/cable_netcdf_decomp_util.F90: Remove max string lengt…
SeanBryan51 Mar 4, 2026
7cde2a7
src/util/netcdf/cable_netcdf.F90: Remove string length constants
SeanBryan51 Mar 4, 2026
3be3f14
src/util/netcdf/nf90/cable_netcdf_nf90.F90: Remove CABLE_NETCDF_MAX_RANK
SeanBryan51 Mar 4, 2026
883ddc9
src/util/netcdf/cable_netcdf.F90: Remove CABLE_NETCDF_MAX_RANK
SeanBryan51 Mar 4, 2026
a56762d
src/util/netcdf/cable_netcdf.F90: Add API documentation
SeanBryan51 Mar 4, 2026
a7f73e4
src/util/netcdf/cable_netcdf_stub_types.F90: Documentation
SeanBryan51 Mar 5, 2026
dffe1e6
src/util/netcdf/pio/cable_netcdf_pio.F90: Documentation & code format…
SeanBryan51 Mar 5, 2026
e516f1f
src/util/netcdf/nf90/cable_netcdf_nf90.F90: Documentation & code form…
SeanBryan51 Mar 5, 2026
bbb1b5c
src/util/netcdf/nf90/cable_netcdf_nf90.F90: Remove redundant type com…
SeanBryan51 Mar 5, 2026
e5d3508
src/util/netcdf/nf90/cable_netcdf_nf90.F90: Documentation
SeanBryan51 Mar 5, 2026
665e0f0
src/util/netcdf/pio/cable_netcdf_pio_stub.F90: Documentation & clean up
SeanBryan51 Mar 5, 2026
68b4512
src/util/netcdf/cable_netcdf_internal.F90: Documentation
SeanBryan51 Mar 5, 2026
164bdeb
src/util/netcdf/cable_netcdf_decomp_util.F90: Documentation
SeanBryan51 Mar 5, 2026
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
76 changes: 74 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,43 @@ project(
)

option(CABLE_MPI "Build the MPI executable" OFF)
option(CABLE_TESTS "Build CABLE tests" OFF)

# third party libs
if(CABLE_MPI)
find_package(MPI REQUIRED COMPONENTS Fortran)
find_package(PIO COMPONENTS Fortran QUIET)
if(TARGET PIO::PIO_Fortran)
message(STATUS "Found PIO_Fortran: ${PIO_DIR}")
endif()
endif()
find_package(PkgConfig REQUIRED)
pkg_check_modules(NETCDF REQUIRED IMPORTED_TARGET "netcdf-fortran")

if(CABLE_TESTS)
enable_testing()
include(FetchContent)
if(CABLE_MPI)
option(FORTUNO_WITH_MPI "Fortuno: whether to build the MPI interface" ON)
FetchContent_Declare(
FortunoMPI
GIT_REPOSITORY https://github.com/fortuno-repos/fortuno
GIT_TAG main
)
FetchContent_MakeAvailable(FortunoMPI)
set(fortuno_libs Fortuno::fortuno_mpi)
else()
option(FORTUNO_WITH_MPI "Fortuno: whether to build the MPI interface" OFF)
FetchContent_Declare(Fortuno
GIT_REPOSITORY https://github.com/fortuno-repos/fortuno
GIT_TAG main
FIND_PACKAGE_ARGS CONFIG
)
FetchContent_MakeAvailable(Fortuno)
set(fortuno_libs Fortuno::fortuno_serial)
endif ()
endif()

set(CABLE_Intel_Fortran_FLAGS -fp-model precise)
set(CABLE_Intel_Fortran_FLAGS_DEBUG -O0 -g -traceback -fpe0)
set(CABLE_Intel_Fortran_FLAGS_RELEASE -O2)
Expand Down Expand Up @@ -239,6 +268,7 @@ else()
src/util/cable_common.F90
src/shared/casa_offline_inout.F90
src/shared/casa_ncdf.F90
src/offline/cable_io_decomp.F90
src/offline/cable_iovars.F90
src/offline/cable_surface_types.F90
src/offline/cable_define_types.F90
Expand Down Expand Up @@ -271,13 +301,26 @@ else()
src/offline/spincasacnp.F90
src/util/cable_climate_type_mod.F90
src/util/masks_cbl.F90
src/util/cable_array_utils.F90
src/util/netcdf/cable_netcdf_decomp_util.F90
src/util/netcdf/cable_netcdf.F90
src/util/netcdf/cable_netcdf_internal.F90
src/util/netcdf/cable_netcdf_stub_types.F90
src/util/netcdf/nf90/cable_netcdf_nf90.F90
)

target_link_libraries(cable_common PRIVATE PkgConfig::NETCDF)

if(CABLE_MPI)
target_compile_definitions(cable_common PRIVATE __MPI__)
target_link_libraries(cable_common PRIVATE MPI::MPI_Fortran)
target_compile_definitions(cable_common PRIVATE __MPI__)
target_link_libraries(cable_common PRIVATE MPI::MPI_Fortran)
endif()

if(TARGET PIO::PIO_Fortran)
target_link_libraries(cable_common PRIVATE PIO::PIO_Fortran)
target_sources(cable_common PRIVATE src/util/netcdf/pio/cable_netcdf_pio.F90)
else()
target_sources(cable_common PRIVATE src/util/netcdf/pio/cable_netcdf_pio_stub.F90)
endif()

if(CABLE_MPI)
Expand All @@ -302,4 +345,33 @@ else()
install(TARGETS cable RUNTIME)
endif()

if (CABLE_TESTS)
add_executable(
cable-tests
tests/cable_tests.F90
tests/fixtures.F90
tests/utils/file_utils.F90
tests/test_cable_netcdf.F90
)
if(CABLE_MPI)
target_sources(cable-tests PRIVATE tests/fortuno_interface_mpi.f90)
else()
target_sources(cable-tests PRIVATE tests/fortuno_interface_serial.f90)
endif()
target_link_libraries(cable-tests PRIVATE cable_common ${fortuno_libs})
if(CABLE_MPI)
add_test(NAME cable-tests-serial
COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 1 $<TARGET_FILE:cable-tests> ~parallel
)
set_tests_properties(cable-tests-serial PROPERTIES PROCESSORS 1)
add_test(NAME cable-tests-parallel
COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 4 $<TARGET_FILE:cable-tests> parallel
)
set_tests_properties(cable-tests-parallel PROPERTIES PROCESSORS 4)
else()
add_test(NAME cable-tests-serial
COMMAND $<TARGET_FILE:cable-tests> ~parallel
)
endif()
endif()
endif()
25 changes: 23 additions & 2 deletions build.bash
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ options below will be passed to CMake when generating the build system.
Options:
-c, --clean Delete build directory before invoking CMake.
-m, --mpi Compile MPI executable.
-p, --parallelio
Enable parallel I/O support. This flag requires that --mpi is
also set.
-C, --compiler <compiler>
Specify the compiler to use.
-n, --ncpus <ncpus>
Expand Down Expand Up @@ -63,6 +66,9 @@ while [ ${#} -gt 0 ]; do
mpi=1
cmake_args+=(-DCABLE_MPI="ON")
;;
-p|--parallelio)
pio=1
;;
-l|--library)
build_args+=(--target cable_science)
cmake_args+=(-DCABLE_LIBRARY="ON")
Expand Down Expand Up @@ -98,9 +104,15 @@ if hostname -f | grep gadi.nci.org.au > /dev/null; then
module add netcdf/4.6.3
case ${compiler} in
intel)
module add intel-compiler/2019.5.281
module add intel-compiler-llvm/2025.2.0
compiler_lib_install_dir=Intel
[[ -n ${mpi} ]] && module add intel-mpi/2019.5.281
[[ -n ${mpi} ]] && module load openmpi/4.0.7
# This is required so that the Parallel IO library is discoverable
# via CMake's `find_package` mechanism:
# TODO(Sean): This install of Parallel IO is specific to
# openmpi/4.0.7. We need a better way to provide this library on
# Gadi.
[[ -n ${pio} ]] && prepend_path CMAKE_PREFIX_PATH "/g/data/tm70/sb8430/spack/1.1/release/linux-x86_64/parallelio-2.6.8-txnbfehdnpwm3vrtp627cab26f7gcrss"
;;
gnu)
module add gcc/13.2.0
Expand All @@ -123,6 +135,15 @@ if hostname -f | grep gadi.nci.org.au > /dev/null; then
prepend_path CMAKE_PREFIX_PATH "${OPENMPI_BASE}/include/${compiler_lib_install_dir}"
fi

if [[ -n ${pio} ]]; then
# The NetCDF Fortran version must be consistent with the version used in Parallel IO
# TODO(Sean): we need a better way to provide these libraries on Gadi
prepend_path CMAKE_PREFIX_PATH "/g/data/tm70/sb8430/spack/1.1/release/linux-x86_64/netcdf-c-4.9.3-lqagnkvmdyriatt6sq2vw5cmt5nfbabz"
prepend_path PKG_CONFIG_PATH "/g/data/tm70/sb8430/spack/1.1/release/linux-x86_64/netcdf-c-4.9.3-lqagnkvmdyriatt6sq2vw5cmt5nfbabz/lib/pkgconfig"
prepend_path CMAKE_PREFIX_PATH "/g/data/tm70/sb8430/spack/1.1/release/linux-x86_64/netcdf-fortran-4.6.2-qs6grg5wgm3anh5gmcmlwxelrzexc6v5"
prepend_path PKG_CONFIG_PATH "/g/data/tm70/sb8430/spack/1.1/release/linux-x86_64/netcdf-fortran-4.6.2-qs6grg5wgm3anh5gmcmlwxelrzexc6v5/lib/pkgconfig"
fi

elif hostname -f | grep -E '(mc16|mcmini)' > /dev/null; then
: "${compiler:=gnu}"

Expand Down
138 changes: 26 additions & 112 deletions src/offline/cable_abort.F90
Original file line number Diff line number Diff line change
Expand Up @@ -20,55 +20,37 @@

MODULE cable_abort_module

USE cable_IO_vars_module, ONLY: check, logn
IMPLICIT NONE

CONTAINS
USE iso_fortran_env, ONLY: error_unit
USE cable_mpi_mod, ONLY: mpi_grp_t

!==============================================================================
!
! Name: abort
!
! Purpose: Prints an error message and stops the code
!
! CALLed from: get_default_inits
! get_restart_data
! get_default_lai
! open_met_file
! get_met_data
! load_parameters
! open_output_file
! write_output
! read_gridinfo
! countpatch
! get_type_parameters
! readpar_i
! readpar_r
! readpar_rd
! readpar_r2
! readpar_r2d
! define_output_variable_r1
! define_output_variable_r2
! define_output_parameter_r1
! define_output_parameter_r2
! write_output_variable_r1
! write_output_variable_r2
! write_output_parameter_r1
! write_output_parameter_r1d
! write_output_parameter_r2
! write_output_parameter_r2d
!
!==============================================================================
IMPLICIT NONE

SUBROUTINE abort(message)
TYPE(mpi_grp_t), PRIVATE :: mpi_grp_global

! Input arguments
CHARACTER(LEN=*), INTENT(IN) :: message
CONTAINS

WRITE (*, *) message
STOP 1
SUBROUTINE cable_abort_module_init(mpi_grp)
!! Initialise abort module
TYPE(mpi_grp_t), intent(in) :: mpi_grp
mpi_grp_global = mpi_grp
END SUBROUTINE

SUBROUTINE cable_abort(message, file, line)
!! Print the error message and stop the code
CHARACTER(LEN=*), INTENT(IN) :: message !! Error message
CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: file
INTEGER, INTENT(IN), OPTIONAL :: line
CHARACTER(5) :: line_string

IF (present(file) .AND. present(line)) THEN
WRITE (line_string, "(I5)") line
WRITE (error_unit, *) file // ":" // trim(adjustl(line_string)) // ": " // message
ELSE
WRITE (error_unit, *) message
END IF
call mpi_grp_global%abort()

END SUBROUTINE abort
END SUBROUTINE

!==============================================================================
!
Expand Down Expand Up @@ -123,72 +105,4 @@ SUBROUTINE nc_abort(ok, message)

END SUBROUTINE nc_abort

!==============================================================================
!
! Name: range_abort
!
! Purpose: Prints an error message and localisation information then stops the
! code
!
! CALLed from: write_output_variable_r1
! write_output_variable_r2
!
! MODULEs used: cable_def_types_mod
! cable_IO_vars_module
!
!==============================================================================

SUBROUTINE range_abort(vname, ktau, met, value, var_range, i, xx, yy)

USE cable_def_types_mod, ONLY: met_type
USE cable_IO_vars_module, ONLY: latitude, longitude, &
landpt, lat_all, lon_all

! Input arguments
CHARACTER(LEN=*), INTENT(IN) :: vname

INTEGER, INTENT(IN) :: &
ktau, & ! time step
i ! tile number along mp

REAL, INTENT(IN) :: &
xx, & ! coordinates of erroneous grid square
yy ! coordinates of erroneous grid square

TYPE(met_type), INTENT(IN) :: met ! met data

REAL(4), INTENT(IN) :: value ! value deemed to be out of range

REAL, INTENT(IN) :: var_range(2) ! appropriate var range

INTEGER :: iunit

IF (check%exit) THEN
iunit = 6
ELSE
iunit = logn ! warning
END IF

WRITE (iunit, *) "in SUBR range_abort: Out of range"
WRITE (iunit, *) "for var ", vname ! error from subroutine

! patch(i)%latitude, patch(i)%longitude
WRITE (iunit, *) 'Site lat, lon:', xx, yy
WRITE (iunit, *) 'Output timestep', ktau, &
', or ', met%hod(i), ' hod, ', &
INT(met%doy(i)), 'doy, ', &
INT(met%year(i))

WRITE (iunit, *) 'Specified acceptable range (cable_checks.f90):', &
var_range(1), 'to', var_range(2)

WRITE (iunit, *) 'Value:', value

IF (check%exit) THEN
STOP
END IF

END SUBROUTINE range_abort

!==============================================================================
END MODULE cable_abort_module
51 changes: 49 additions & 2 deletions src/offline/cable_checks.F90
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ MODULE cable_checks_module
! particular sections of the code - largely for diagnostics/fault finding.
! rh_sh - converts relative to sensible humidity if met file units require it
!
USE cable_IO_vars_module, ONLY: patch
USE cable_abort_module, ONLY: range_abort
USE iso_fortran_env, ONLY: error_unit
USE cable_IO_vars_module, ONLY: patch, check, logn
USE cable_abort_module, ONLY: cable_abort
USE cable_def_types_mod
USE cable_common_module, ONLY: cable_user

Expand Down Expand Up @@ -212,6 +213,52 @@ MODULE cable_checks_module

CONTAINS

SUBROUTINE range_abort(vname, ktau, met, value, var_range, i, xx, yy)
!! Prints an error message and localisation information then stops the code

CHARACTER(LEN=*), INTENT(IN) :: vname

INTEGER, INTENT(IN) :: &
ktau, & ! time step
i ! tile number along mp

REAL, INTENT(IN) :: &
xx, & ! coordinates of erroneous grid square
yy ! coordinates of erroneous grid square

TYPE(met_type), INTENT(IN) :: met ! met data

REAL(4), INTENT(IN) :: value ! value deemed to be out of range

REAL, INTENT(IN) :: var_range(2) ! appropriate var range

INTEGER :: iunit

IF (check%exit) THEN
iunit = error_unit
ELSE
iunit = logn ! warning
END IF

WRITE (iunit, *) "in SUBR range_abort: Out of range"
WRITE (iunit, *) "for var ", vname ! error from subroutine

! patch(i)%latitude, patch(i)%longitude
WRITE (iunit, *) 'Site lat, lon:', xx, yy
WRITE (iunit, *) 'Output timestep', ktau, &
', or ', met%hod(i), ' hod, ', &
INT(met%doy(i)), 'doy, ', &
INT(met%year(i))

WRITE (iunit, *) 'Specified acceptable range (cable_checks.f90):', &
var_range(1), 'to', var_range(2)

WRITE (iunit, *) 'Value:', value

IF (check%exit) CALL cable_abort("Aborting...")

END SUBROUTINE range_abort

SUBROUTINE check_range_d1(vname, parameter_r1, parameter_range, ktau, met)

CHARACTER(LEN=*) :: vname
Expand Down
Loading