subroutine check_range(values, name, range, index, closed)
! Check if the real array values is within (/lower, upper/) range and terminate
! with name if not. values must be a 1D array but a single
! value can also be checked by passing (/value/) and an optional index to report.
! The closed optional argument specifies the inclusion/exclusion of the bounds:
! closed="l"/"u"/"n" means lower/upper/neither is included, default is both.
! Examples:
! call check_range((/1., 2., 3./), "array", (/0., 2./))
! call check_range((/2./), "val", (/0., 2./), closed="n")
! call check_range((/3./), "array", (/0., 2./), index=100)
real(dp), intent(in) :: values(:)
character(*), intent(in) :: name
real(dp), intent(in) :: range(2)
integer, intent(in), optional :: index
character(len=1), intent(in), optional :: closed
integer i, nv, counter
real(dp) va
logical clsd(2)
if (range(1) >= range(2)) &
call log_error("check_range", "range is not (/lower, upper/) values", reals=range)
clsd = .True.
if (present(closed)) then
if (closed == "n") clsd = .False.
if (closed == "l") clsd(2) = .False.
if (closed == "u") clsd(1) = .False.
end if
counter = 0
nv = size(values)
do i = 1, nv
va = values(i)
! check range depending on range closure
if ((clsd(1) .and. va < range(1)) .or. (.not.clsd(1) .and. va <= range(1)) .or. &
(clsd(2) .and. va > range(2)) .or. (.not.clsd(2) .and. va >= range(2))) then
if (nv > 1) &
call log_warn('check_range', name, i1=i, real=va)
counter = counter + 1
endif
end do
! Array with counted out of range values, indeces reported above
if (counter > 0 .and. nv > 1) call out_of_range_error(name, range, counter=counter)
! Single value with index
if (counter == 1 .and. present(index)) &
call out_of_range_error(name, range, va, index=index)
! Single value without index
if (counter == 1) call out_of_range_error(name, range, values(1))
end subroutine check_range