io_base.f90 Source File


This file depends on

sourcefile~~io_base.f90~~EfferentGraph sourcefile~io_base.f90 io_base.f90 sourcefile~backend.f90~2 backend.f90 sourcefile~io_base.f90->sourcefile~backend.f90~2 sourcefile~common.f90~3 common.f90 sourcefile~io_base.f90->sourcefile~common.f90~3 sourcefile~field.f90 field.f90 sourcefile~io_base.f90->sourcefile~field.f90 sourcefile~backend.f90~2->sourcefile~common.f90~3 sourcefile~backend.f90~2->sourcefile~field.f90 sourcefile~allocator.f90 allocator.f90 sourcefile~backend.f90~2->sourcefile~allocator.f90 sourcefile~mesh.f90 mesh.f90 sourcefile~backend.f90~2->sourcefile~mesh.f90 sourcefile~poisson_fft.f90~2 poisson_fft.f90 sourcefile~backend.f90~2->sourcefile~poisson_fft.f90~2 sourcefile~tdsops.f90~2 tdsops.f90 sourcefile~backend.f90~2->sourcefile~tdsops.f90~2 sourcefile~mpi.f90 mpi.f90 sourcefile~common.f90~3->sourcefile~mpi.f90 sourcefile~field.f90->sourcefile~common.f90~3 sourcefile~allocator.f90->sourcefile~common.f90~3 sourcefile~allocator.f90->sourcefile~field.f90 sourcefile~mesh.f90->sourcefile~common.f90~3 sourcefile~mesh.f90->sourcefile~field.f90 sourcefile~mesh.f90->sourcefile~mpi.f90 sourcefile~decomp_dummy.f90 decomp_dummy.f90 sourcefile~mesh.f90->sourcefile~decomp_dummy.f90 sourcefile~mesh_content.f90 mesh_content.f90 sourcefile~mesh.f90->sourcefile~mesh_content.f90 sourcefile~poisson_fft.f90~2->sourcefile~common.f90~3 sourcefile~poisson_fft.f90~2->sourcefile~field.f90 sourcefile~poisson_fft.f90~2->sourcefile~mesh.f90 sourcefile~poisson_fft.f90~2->sourcefile~tdsops.f90~2 sourcefile~tdsops.f90~2->sourcefile~common.f90~3 sourcefile~decomp_dummy.f90->sourcefile~mesh_content.f90 sourcefile~mesh_content.f90->sourcefile~common.f90~3

Files dependent on this one

sourcefile~~io_base.f90~~AfferentGraph sourcefile~io_base.f90 io_base.f90 sourcefile~io.f90 io.f90 sourcefile~io.f90->sourcefile~io_base.f90 sourcefile~io.f90~2 io.f90 sourcefile~io.f90~2->sourcefile~io_base.f90 sourcefile~io_field_utils.f90 io_field_utils.f90 sourcefile~io_field_utils.f90->sourcefile~io_base.f90 sourcefile~solver.f90 solver.f90 sourcefile~io_field_utils.f90->sourcefile~solver.f90 sourcefile~io_session.f90 io_session.f90 sourcefile~io_session.f90->sourcefile~io_base.f90 sourcefile~io_session.f90->sourcefile~io.f90 sourcefile~checkpoint_manager.f90 checkpoint_manager.f90 sourcefile~checkpoint_manager.f90->sourcefile~io.f90 sourcefile~checkpoint_manager.f90->sourcefile~io_field_utils.f90 sourcefile~checkpoint_manager.f90->sourcefile~io_session.f90 sourcefile~checkpoint_state.f90 checkpoint_state.f90 sourcefile~checkpoint_manager.f90->sourcefile~checkpoint_state.f90 sourcefile~stats.f90 stats.f90 sourcefile~checkpoint_manager.f90->sourcefile~stats.f90 sourcefile~checkpoint_manager.f90->sourcefile~solver.f90 sourcefile~checkpoint_state.f90->sourcefile~io_session.f90 sourcefile~ibm.f90 ibm.f90 sourcefile~ibm.f90->sourcefile~io_session.f90 sourcefile~snapshot_manager.f90 snapshot_manager.f90 sourcefile~snapshot_manager.f90->sourcefile~io.f90 sourcefile~snapshot_manager.f90->sourcefile~io_field_utils.f90 sourcefile~snapshot_manager.f90->sourcefile~io_session.f90 sourcefile~snapshot_manager.f90->sourcefile~solver.f90 sourcefile~stats.f90->sourcefile~io_session.f90 sourcefile~stats.f90->sourcefile~solver.f90 sourcefile~io_manager.f90 io_manager.f90 sourcefile~io_manager.f90->sourcefile~checkpoint_manager.f90 sourcefile~io_manager.f90->sourcefile~checkpoint_state.f90 sourcefile~io_manager.f90->sourcefile~snapshot_manager.f90 sourcefile~io_manager.f90->sourcefile~stats.f90 sourcefile~io_manager.f90->sourcefile~solver.f90 sourcefile~solver.f90->sourcefile~ibm.f90 sourcefile~base_case.f90 base_case.f90 sourcefile~base_case.f90->sourcefile~io_manager.f90 sourcefile~base_case.f90->sourcefile~solver.f90 sourcefile~monitoring.f90 monitoring.f90 sourcefile~base_case.f90->sourcefile~monitoring.f90 sourcefile~postprocess.f90 postprocess.f90 sourcefile~base_case.f90->sourcefile~postprocess.f90 sourcefile~channel.f90 channel.f90 sourcefile~channel.f90->sourcefile~solver.f90 sourcefile~channel.f90->sourcefile~base_case.f90 sourcefile~cylinder.f90 cylinder.f90 sourcefile~cylinder.f90->sourcefile~solver.f90 sourcefile~cylinder.f90->sourcefile~base_case.f90 sourcefile~generic.f90 generic.f90 sourcefile~generic.f90->sourcefile~solver.f90 sourcefile~generic.f90->sourcefile~base_case.f90 sourcefile~monitoring.f90->sourcefile~solver.f90 sourcefile~postprocess.f90->sourcefile~solver.f90 sourcefile~tgv.f90 tgv.f90 sourcefile~tgv.f90->sourcefile~solver.f90 sourcefile~tgv.f90->sourcefile~base_case.f90 sourcefile~abl.f90~2 abl.f90 sourcefile~abl.f90~2->sourcefile~base_case.f90 sourcefile~xcompact.f90 xcompact.f90 sourcefile~xcompact.f90->sourcefile~base_case.f90 sourcefile~xcompact.f90->sourcefile~channel.f90 sourcefile~xcompact.f90->sourcefile~cylinder.f90 sourcefile~xcompact.f90->sourcefile~generic.f90 sourcefile~xcompact.f90->sourcefile~tgv.f90 sourcefile~xcompact.f90->sourcefile~abl.f90~2

Source Code

module m_io_base
!! @brief Provides the abstract base types and interfaces for the session-based
!! I/O architecture.
!!
!! @details This internal module defines the fundamental building blocks of
!! the I/O system. It establishes a polymorphic layer that allows the
!! high-level user session to interact with various I/O backends through a
!! consistent interface.
!!
!! The architecture is designed in distinct layers:
!! User code
!! - interacts only with the Session layer
!!
!! Session layer (`m_io_session`)
!! - manages all I/O complexity (file handles, state, etc.)
!! - instantiates the I/O backend selected at compile-time
!! - provides `reader_session_t` and `writer_session_t` for users
!!
!! Backend layer (`m_io_backend`)
!! - concrete implementation of an I/O backed (e.g., ADIOS2)
!! - extends the abstract base types defined in this module
!!
!! Base layer (`m_io_base`, this module)
!! - provides abstract `io_reader_t`, `io_writer_t` and `io_file_t` types
!! - deferred bindings make every backend implement the full interface at
!!   compile time; only optional capabilities have default implementations
!!
!! @note This is an internal module and should not be used directly by users.
!! The sole public interface for I/O is the high-level session API provided in
!! `m_io_session`.

  use m_common, only: dp, i8
  use m_field, only: field_t
  use m_base_backend, only: base_backend_t

  implicit none

  private
  public :: io_reader_t, io_writer_t, io_file_t
  public :: io_mode_read, io_mode_write

  integer, parameter :: io_mode_read = 1
  integer, parameter :: io_mode_write = 2

  !> Base file handle for I/O operations
  type, abstract :: io_file_t
  contains
    procedure(file_op), deferred :: close
    procedure(file_op), deferred :: begin_step
    procedure(file_op), deferred :: end_step
    procedure :: is_file_functional => base_is_file_functional
  end type io_file_t

  !> Base I/O reader type for polymorphic usage
  type, abstract :: io_reader_t
  contains
    procedure(reader_init), deferred :: init
    procedure(reader_open), deferred :: open
    procedure(reader_finalise), deferred :: finalise
    ! Generic interfaces for session usage
    generic :: read_data => read_data_i8, read_data_integer, read_data_real, &
      read_data_array_3d
    procedure(read_data_i8), deferred :: read_data_i8
    procedure(read_data_integer), deferred :: read_data_integer
    procedure(read_data_real), deferred :: read_data_real
    procedure(read_data_array_3d), deferred :: read_data_array_3d
  end type io_reader_t

  !> Base I/O writer type for polymorphic usage
  type, abstract :: io_writer_t
  contains
    procedure(writer_init), deferred :: init
    procedure(writer_open), deferred :: open
    procedure(writer_finalise), deferred :: finalise
    procedure :: supports_device_field_write => &
      base_supports_device_field_write
    generic :: write_data => write_data_i8, write_data_integer, &
      write_data_real, &
      write_data_array_3d
    procedure(write_data_i8), deferred :: write_data_i8
    procedure(write_data_integer), deferred :: write_data_integer
    procedure(write_data_real), deferred :: write_data_real
    procedure(write_data_array_3d), deferred :: write_data_array_3d
    procedure(write_field_from_solver), deferred :: write_field_from_solver
    generic :: write_attribute => write_attribute_string, &
      write_attribute_array_1d_real
    procedure(write_attribute_string), deferred :: write_attribute_string
    procedure(write_attribute_array_1d_real), deferred :: &
      write_attribute_array_1d_real
  end type io_writer_t

  abstract interface
    subroutine file_op(self)
      import :: io_file_t
      class(io_file_t), intent(inout) :: self
    end subroutine file_op

    subroutine reader_init(self, comm, name)
      import :: io_reader_t
      class(io_reader_t), intent(inout) :: self
      integer, intent(in) :: comm
      character(len=*), intent(in) :: name
    end subroutine reader_init

    function reader_open(self, filename, mode, comm) result(file_handle)
      import :: io_reader_t, io_file_t
      class(io_reader_t), intent(inout) :: self
      character(len=*), intent(in) :: filename
      integer, intent(in) :: mode
      integer, intent(in) :: comm
      class(io_file_t), allocatable :: file_handle
    end function reader_open

    subroutine reader_finalise(self)
      import :: io_reader_t
      class(io_reader_t), intent(inout) :: self
    end subroutine reader_finalise

    subroutine read_data_i8(self, variable_name, value, file_handle)
      import :: io_reader_t, io_file_t, i8
      class(io_reader_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      integer(i8), intent(out) :: value
      class(io_file_t), intent(inout) :: file_handle
    end subroutine read_data_i8

    subroutine read_data_integer(self, variable_name, value, file_handle)
      import :: io_reader_t, io_file_t
      class(io_reader_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      integer, intent(out) :: value
      class(io_file_t), intent(inout) :: file_handle
    end subroutine read_data_integer

    subroutine read_data_real(self, variable_name, value, file_handle)
      import :: io_reader_t, io_file_t, dp
      class(io_reader_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      real(dp), intent(out) :: value
      class(io_file_t), intent(inout) :: file_handle
    end subroutine read_data_real

    subroutine read_data_array_3d( &
      self, variable_name, array, file_handle, &
      shape_dims, start_dims, count_dims &
      )
      import :: io_reader_t, io_file_t, dp, i8
      class(io_reader_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      real(dp), intent(inout) :: array(:, :, :)
      class(io_file_t), intent(inout) :: file_handle
      integer(i8), intent(in), optional :: shape_dims(3)
      integer(i8), intent(in), optional :: start_dims(3)
      integer(i8), intent(in), optional :: count_dims(3)
    end subroutine read_data_array_3d

    subroutine writer_init(self, comm, name)
      import :: io_writer_t
      class(io_writer_t), intent(inout) :: self
      integer, intent(in) :: comm
      character(len=*), intent(in) :: name
    end subroutine writer_init

    function writer_open(self, filename, mode, comm) result(file_handle)
      import :: io_writer_t, io_file_t
      class(io_writer_t), intent(inout) :: self
      character(len=*), intent(in) :: filename
      integer, intent(in) :: mode
      integer, intent(in) :: comm
      class(io_file_t), allocatable :: file_handle
    end function writer_open

    subroutine writer_finalise(self)
      import :: io_writer_t
      class(io_writer_t), intent(inout) :: self
    end subroutine writer_finalise

    subroutine write_data_i8(self, variable_name, value, file_handle)
      import :: io_writer_t, io_file_t, i8
      class(io_writer_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      integer(i8), intent(in) :: value
      class(io_file_t), intent(inout) :: file_handle
    end subroutine write_data_i8

    subroutine write_data_integer(self, variable_name, value, file_handle)
      import :: io_writer_t, io_file_t
      class(io_writer_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      integer, intent(in) :: value
      class(io_file_t), intent(inout) :: file_handle
    end subroutine write_data_integer

    subroutine write_data_real(self, variable_name, value, file_handle, &
                               use_sp)
      import :: io_writer_t, io_file_t, dp
      class(io_writer_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      real(dp), intent(in) :: value
      class(io_file_t), intent(inout) :: file_handle
      logical, intent(in), optional :: use_sp
    end subroutine write_data_real

    subroutine write_data_array_3d( &
      self, variable_name, array, file_handle, &
      shape_dims, start_dims, count_dims, use_sp &
      )
      import :: io_writer_t, io_file_t, dp, i8
      class(io_writer_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      real(dp), intent(in) :: array(:, :, :)
      class(io_file_t), intent(inout) :: file_handle
      integer(i8), intent(in) :: shape_dims(3)
      integer(i8), intent(in) :: start_dims(3)
      integer(i8), intent(in) :: count_dims(3)
      logical, intent(in), optional :: use_sp
    end subroutine write_data_array_3d

    subroutine write_field_from_solver( &
      self, variable_name, field, file_handle, backend, &
      shape_dims, start_dims, count_dims, use_sp &
      )
      !! Write the first count_dims points of a solver field. Backends
      !! may write device-resident fields without staging through host
      !! memory; `backend` provides the layout-aware packing for that.
      import :: io_writer_t, io_file_t, field_t, base_backend_t, i8
      class(io_writer_t), intent(inout) :: self
      character(len=*), intent(in) :: variable_name
      class(field_t), intent(in) :: field
      class(io_file_t), intent(inout) :: file_handle
      class(base_backend_t), intent(inout) :: backend
      integer(i8), intent(in) :: shape_dims(3)
      integer(i8), intent(in) :: start_dims(3)
      integer(i8), intent(in) :: count_dims(3)
      logical, intent(in), optional :: use_sp
    end subroutine write_field_from_solver

    subroutine write_attribute_string( &
      self, attribute_name, value, file_handle &
      )
      import :: io_writer_t, io_file_t
      class(io_writer_t), intent(inout) :: self
      character(len=*), intent(in) :: attribute_name
      character(len=*), intent(in) :: value
      class(io_file_t), intent(inout) :: file_handle
    end subroutine write_attribute_string

    subroutine write_attribute_array_1d_real( &
      self, attribute_name, values, file_handle &
      )
      import :: io_writer_t, io_file_t, dp
      class(io_writer_t), intent(inout) :: self
      character(len=*), intent(in) :: attribute_name
      real(dp), intent(in) :: values(:)
      class(io_file_t), intent(inout) :: file_handle
    end subroutine write_attribute_array_1d_real
  end interface

contains

  logical function base_supports_device_field_write(self, field, backend)
    !! Default capability: fields are always staged through host memory.
    class(io_writer_t), intent(in) :: self
    class(field_t), intent(in) :: field
    class(base_backend_t), intent(in) :: backend
    base_supports_device_field_write = .false.
  end function base_supports_device_field_write

  function base_is_file_functional(self) result(is_functional)
    class(io_file_t), intent(in) :: self
    logical :: is_functional
    is_functional = .true.
  end function base_is_file_functional

end module m_io_base