mod_get_indices.f08 Source File


Contents

Source Code


Source Code

!=================================================================
!> Module defining convenient index retrieval functions on various arrays.
module mod_get_indices
  implicit none

  private

  !> interface to retrieve the index of an element in an array.
   !! @note: replace get_index by `findloc` once we drop support for gfortran<9 @endnote
  interface get_index
    module procedure find_index_in_character_array
    module procedure find_indices_in_character_array
  end interface get_index


  interface get_subblock_index
    module procedure transform_state_variable_to_subblock_index
  end interface

  public :: get_index
  public :: get_subblock_index

contains

  !> Function to locate the index of a given character in a character array.
  !! Iterates over the elements and returns on the first hit, if no match
  !! was found zero is returned.
  pure function find_index_in_character_array(name, array) result(match_idx)
    !> the name to search for
    character(len=*), intent(in)  :: name
    !> array with the names to search in
    character(len=*), intent(in)  :: array(:)
    !> index of first match
    integer :: match_idx
    integer :: i

    match_idx = 0
    do i = 1, size(array)
      if (array(i) == trim(adjustl(name))) then
        match_idx = i
        exit
      end if
    end do
  end function find_index_in_character_array


  !> Function to locate the indices of an array of characters in another
  !! character array. Returns the indices of the first hit, it no match was
  !! found zero is returned.
  pure function find_indices_in_character_array(names, array) result(match_idxs)
    !> the names to search for
    character(len=*), intent(in)  :: names(:)
    !> array in which to sarch in
    character(len=*), intent(in)  :: array(:)
    !> index of first matches
    integer :: match_idxs(size(names))
    integer :: i

    do i = 1, size(names)
      match_idxs(i) = find_index_in_character_array(names(i), array)
    end do
  end function find_indices_in_character_array


  !> Transforms a given array of state variables to subblock indices.
  !! If `odd` is `.true.` returns the odd indices, otherwise the even indices.
  !! If `edge` equals `"left"`, returns the indices corresponding to the left boundary
  !! block, if `edge` equals `"right"` returns indices for the right boundary block.
  function transform_state_variable_to_subblock_index( &
    variables, state_vector, dim_subblock, odd, edge &
  ) result(idxs)
    use mod_logging, only: logger, str

    !> array of state vector variable names
    character(len=*), intent(in)  :: variables(:)
    !> state vector to consider
    character(len=*), intent(in)  :: state_vector(:)
    !> dimension of the subblock
    integer, intent(in)  :: dim_subblock
    !> uses odd indices if .true. and even if .false.
    logical, intent(in) :: odd
    !> which edge to consider, `"left"` for left boundary and `"right"` for right one
    character(len=*), intent(in)  :: edge
    !> integer array containing the corresponding subblock indices
    integer, allocatable :: idxs(:)

    idxs = get_index(variables, state_vector)
    idxs = 2 * pack(idxs, idxs > 0)

    if (odd) idxs = idxs - 1
    if (edge == "right") idxs = idxs + dim_subblock
    if (size(idxs) == 0) then
      call logger%error( &
        "could not retrieve subblock indices for any variable in " // str(variables) &
        // " for state vector " // str(state_vector) &
      )
      return
    end if
  end function transform_state_variable_to_subblock_index

end module mod_get_indices