Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 57 additions & 6 deletions components/lfric-xios/source/lfric_xios_read_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ module lfric_xios_read_mod
use constants_mod, only: i_def, l_def, str_def, r_def, rmdi, &
LARGE_DP_NEGATIVE
use lfric_xios_constants_mod, only: dp_xios
use key_value_mod, only: abstract_value_type
use io_value_mod, only: io_value_type
use integer_io_value_mod, only: integer_io_value_type
use field_mod, only: field_type, field_proxy_type
use field_real32_mod, only: field_real32_type, field_real32_proxy_type
use field_real64_mod, only: field_real64_type, field_real64_proxy_type
Expand Down Expand Up @@ -61,11 +63,18 @@ module lfric_xios_read_mod
private
public :: checkpoint_read_xios, &
checkpoint_read_value, &
checkpoint_read_r_def_value, &
checkpoint_read_integer_value, &
read_field_generic, &
read_state, &
read_checkpoint, &
read_field_time_var

interface checkpoint_read_value
procedure :: checkpoint_read_r_def_value
procedure :: checkpoint_read_integer_value
end interface checkpoint_read_value

contains

!> @brief I/O handler for reading an XIOS netcdf checkpoint
Expand Down Expand Up @@ -112,17 +121,55 @@ subroutine checkpoint_read_xios(xios_field_name, file_name, field_proxy)

end subroutine checkpoint_read_xios

!> @brief Read the data from an XIOS checkpoint file into the io_value
!> @brief Read r_def data from an XIOS checkpoint file into the io_value
!> @param[in,out] io_value The io_value to read data into
!> @param[in] value_name The id defined in the XIOS context
!>
subroutine checkpoint_read_value(io_value, value_name)
subroutine checkpoint_read_r_def_value(io_value, value_name)
class(io_value_type), intent(inout) :: io_value
character(*), optional, intent(in) :: value_name
character(str_def) :: restart_id
integer(i_def) :: array_dims
integer(tik) :: timing_id
real(dp_xios), allocatable :: dp_equiv(:)

if ( LPROF ) call start_timing(timing_id, 'lfric_xios.chkpt_readrv')

if(present(value_name)) then
restart_id = trim(value_name)
else
restart_id = "restart_" // trim(io_value%io_id)
end if
array_dims = size(io_value%data)

if ( xios_is_valid_field(trim(restart_id)) ) then
allocate(dp_equiv(array_dims))
call xios_recv_field( trim(restart_id), &
dp_equiv(1:array_dims) )
io_value%data = real(dp_equiv,r_def)
deallocate(dp_equiv)
else
call log_event( 'No XIOS field with id="'//trim(restart_id)//'" is defined', &
LOG_LEVEL_ERROR )
end if

if ( LPROF ) call stop_timing(timing_id, 'lfric_xios.chkpt_readrv')

end subroutine checkpoint_read_r_def_value

!> @brief Read int data from an XIOS checkpoint file into the io_value
!> @param[in,out] io_value The io_value to read data into
!> @param[in] value_name The id defined in the XIOS context
!>
subroutine checkpoint_read_integer_value(io_value, value_name)
class(integer_io_value_type), intent(inout) :: io_value
character(*), optional, intent(in) :: value_name
character(str_def) :: restart_id
integer(i_def) :: array_dims
integer(tik) :: timing_id
real(dp_xios), allocatable :: dp_equiv(:)

if ( LPROF ) call start_timing(timing_id, 'lfric_xios.chkpt_readv')
if ( LPROF ) call start_timing(timing_id, 'lfric_xios.chkpt_readiv')

if(present(value_name)) then
restart_id = trim(value_name)
Expand All @@ -132,15 +179,19 @@ subroutine checkpoint_read_value(io_value, value_name)
array_dims = size(io_value%data)

if ( xios_is_valid_field(trim(restart_id)) ) then
allocate(dp_equiv(array_dims))
call xios_recv_field( trim(restart_id), &
io_value%data(1:array_dims) )
dp_equiv(1:array_dims) )
io_value%data = int(dp_equiv,i_def)
deallocate(dp_equiv)
else
call log_event( 'No XIOS field with id="'//trim(restart_id)//'" is defined', &
LOG_LEVEL_ERROR )
end if
if ( LPROF ) call stop_timing(timing_id, 'lfric_xios.chkpt_readv')

end subroutine checkpoint_read_value
if ( LPROF ) call stop_timing(timing_id, 'lfric_xios.chkpt_readiv')

end subroutine checkpoint_read_integer_value

!> @brief Post-processing after reading field data
!> @details Performs a halo swap if necessary
Expand Down
128 changes: 105 additions & 23 deletions components/lfric-xios/source/lfric_xios_write_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module lfric_xios_write_mod
use field_real32_mod, only: field_real32_type, field_real32_proxy_type
use field_real64_mod, only: field_real64_type, field_real64_proxy_type
use io_value_mod, only: io_value_type
use integer_io_value_mod, only: integer_io_value_type
use key_value_mod, only: key_value_type, abstract_key_value_type, &
abstract_value_type
use key_value_collection_mod, &
Expand Down Expand Up @@ -67,39 +68,74 @@ module lfric_xios_write_mod
write_field_generic, &
write_empty_field, &
checkpoint_write_value, &
checkpoint_write_r_def_value, &
checkpoint_write_integer_value, &
write_value_generic, &
write_state, &
write_checkpoint, &
create_checkpoint_list

interface checkpoint_write_value
procedure :: checkpoint_write_r_def_value
procedure :: checkpoint_write_integer_value
end interface checkpoint_write_value

contains

!> @brief Write io_value data via XIOS
!> @details This routine assumes there is a XIOS field defined
!> with a field id the same as the io_value id
!> @param[in,out] io_value The io_value to write data from
!> @param[in] io_value The io_value to write data from
!> @param[in] value_name The id defined in the XIOS context
!>
subroutine write_value_generic(io_value, value_name)
class(io_value_type), intent(inout) :: io_value
class(abstract_value_type), intent(in) :: io_value
character(*), optional, intent(in) :: value_name

integer(i_def) :: array_dims
character(:), allocatable :: value_id
integer(i_def) :: array_dims
character(:), allocatable :: value_id
real(dp_xios), allocatable :: dp_equiv(:)

if (present(value_name)) then
value_id = value_name
else
value_id = io_value%io_id
end if
select type(io_value)
type is (io_value_type)
if (present(value_name)) then
value_id = value_name
else
value_id = io_value%io_id
end if

array_dims = size(io_value%data)
if ( xios_is_valid_field(trim(value_id)) ) then
call xios_send_field( trim(value_id), &
reshape(io_value%data, (/ 1, array_dims /)) )
else
call log_event( 'No XIOS field with id="'//trim(io_value%io_id)//'" is defined', &
LOG_LEVEL_ERROR )
end if
array_dims = size(io_value%data)
if ( xios_is_valid_field(trim(value_id)) ) then
! Support 32-bit and 64-bit input by converting to XIOS real kind
allocate(dp_equiv(array_dims))
dp_equiv = real(io_value%data, dp_xios)
call xios_send_field( trim(value_id), &
reshape(dp_equiv, (/ 1, array_dims /)) )
deallocate(dp_equiv)
else
call log_event( 'No XIOS field with id="'//trim(io_value%io_id)//'" is defined', &
LOG_LEVEL_ERROR )
end if
type is (integer_io_value_type)
if (present(value_name)) then
value_id = value_name
else
value_id = io_value%io_id
end if

array_dims = size(io_value%data)
if ( xios_is_valid_field(trim(value_id)) ) then
! Integers must be converted to XIOS real kind
allocate(dp_equiv(array_dims))
dp_equiv = real(io_value%data,dp_xios)
call xios_send_field( trim(value_id), &
reshape(dp_equiv, (/ 1, array_dims /)) )
deallocate(dp_equiv)
else
call log_event( 'No XIOS field with id="'//trim(io_value%io_id)//'" is defined', &
LOG_LEVEL_ERROR )
end if
end select

end subroutine write_value_generic

Expand Down Expand Up @@ -181,17 +217,52 @@ subroutine write_empty_field(field_name, field_proxy)

end subroutine write_empty_field

!> @brief Checkpoint an io_value with XIOS
!> @brief Checkpoint an r_def io_value with XIOS
!> @details This routine assumes there is an XIOS field
!> with the "checkpoint_" prefix
!> @param[in] io_value The io_value to write data from
!> @param[in] value_name The id defined in the XIOS context
!>
subroutine checkpoint_write_r_def_value(io_value, value_name)
class(io_value_type), intent(in) :: io_value
character(*), optional, intent(in) :: value_name

character(str_def) :: checkpoint_id
integer(i_def) :: array_dims
real(dp_xios), allocatable :: dp_equiv(:)

if(present(value_name)) then
checkpoint_id = trim(value_name)
else
checkpoint_id = trim(io_value%io_id)
end if
array_dims = size(io_value%data)
if ( xios_is_valid_field(trim(checkpoint_id)) ) then
allocate(dp_equiv(array_dims))
dp_equiv = real(io_value%data, dp_xios)
call xios_send_field( trim(checkpoint_id), &
reshape(dp_equiv, (/ 1, array_dims /)) )
deallocate(dp_equiv)
else
call log_event( 'No XIOS field with id="'//trim(checkpoint_id)//'" is defined', &
LOG_LEVEL_ERROR )
end if

end subroutine checkpoint_write_r_def_value

!> @brief Checkpoint an integer io_value with XIOS
!> @details This routine assumes there is an XIOS field
!> with the "checkpoint_" prefix
!> @param[in,out] io_value The io_value to write data from
!> @param[in] io_value The io_value to write data from
!> @param[in] value_name The id defined in the XIOS context
!>
subroutine checkpoint_write_value(io_value, value_name)
class(io_value_type), intent(inout) :: io_value
subroutine checkpoint_write_integer_value(io_value, value_name)
class(integer_io_value_type), intent(in) :: io_value
character(*), optional, intent(in) :: value_name

character(str_def) :: checkpoint_id
integer(i_def) :: array_dims
real(dp_xios), allocatable :: dp_equiv(:)

if(present(value_name)) then
checkpoint_id = trim(value_name)
Expand All @@ -200,14 +271,17 @@ subroutine checkpoint_write_value(io_value, value_name)
end if
array_dims = size(io_value%data)
if ( xios_is_valid_field(trim(checkpoint_id)) ) then
allocate(dp_equiv(array_dims))
dp_equiv = real(io_value%data, dp_xios)
call xios_send_field( trim(checkpoint_id), &
reshape(io_value%data, (/ 1, array_dims /)) )
reshape(dp_equiv, (/ 1, array_dims /)) )
deallocate(dp_equiv)
else
call log_event( 'No XIOS field with id="'//trim(checkpoint_id)//'" is defined', &
LOG_LEVEL_ERROR )
end if

end subroutine checkpoint_write_value
end subroutine checkpoint_write_integer_value

!> @brief I/O handler for writing an XIOS netcdf checkpoint
!> @details Note this routine accepts a filename but doesn't use it - this is
Expand Down Expand Up @@ -482,6 +556,14 @@ subroutine write_checkpoint( fields, values, clock, checkpoint_stem_name, &
call io_value_object%write_checkpoint( &
trim(field_prefix) // trim(io_value_object%io_id))
end if
type is (integer_io_value_type)
if(io_value_object%can_write_checkpoint()) then
call log_event( 'Writing checkpoint for ' // &
trim(io_value_object%io_id), &
LOG_LEVEL_INFO )
call io_value_object%write_checkpoint( &
trim(field_prefix) // trim(io_value_object%io_id))
end if
end select
end select
end do
Expand Down
Loading
Loading