mod_utility.f90 Source File

This File Depends On

sourcefile~~mod_utility.f90~~EfferentGraph sourcefile~mod_utility.f90 mod_utility.f90 sourcefile~mod_precision.f90 mod_precision.f90 sourcefile~mod_precision.f90->sourcefile~mod_utility.f90
Help

Files Dependent On This One

sourcefile~~mod_utility.f90~~AfferentGraph sourcefile~mod_utility.f90 mod_utility.f90 sourcefile~mod_grid.f90 mod_grid.f90 sourcefile~mod_utility.f90->sourcefile~mod_grid.f90 sourcefile~mod_spectrum.f90 mod_spectrum.f90 sourcefile~mod_utility.f90->sourcefile~mod_spectrum.f90 sourcefile~mod_domain.f90 mod_domain.f90 sourcefile~mod_grid.f90->sourcefile~mod_domain.f90 sourcefile~mod_spectrum.f90->sourcefile~mod_domain.f90 sourcefile~mod_time_integration.f90 mod_time_integration.f90 sourcefile~mod_spectrum.f90->sourcefile~mod_time_integration.f90 sourcefile~mod_source_functions.f90 mod_source_functions.f90 sourcefile~mod_spectrum.f90->sourcefile~mod_source_functions.f90 sourcefile~mod_domain.f90->sourcefile~mod_time_integration.f90
Help

Source Code


Source Code

!
! wavy - A spectral ocean wave modeling and development framework
! Copyright (c) 2017, Wavebit Scientific LLC
! All rights reserved.
!
! Licensed under the BSD-3 clause license. See LICENSE for details.
!
module mod_utility

use mod_precision,only:ik => intkind,rk => realkind

implicit none

private

public :: diff
public :: diff_periodic
public :: ones
public :: range
public :: tile
public :: zeros

interface diff
  module procedure :: diff_1d
  module procedure :: diff_2d
endinterface diff

interface diff_periodic
  module procedure :: diff_periodic_1d
  module procedure :: diff_periodic_2d
endinterface diff_periodic

interface ones
  module procedure :: ones_int
  module procedure :: ones_real
endinterface ones

interface range
  module procedure :: range_int
  module procedure :: range_real
endinterface range

interface tile
  module procedure :: tile_1d_int
  module procedure :: tile_1d_real
  module procedure :: tile_2d_int
  module procedure :: tile_2d_real
  module procedure :: tile_3d_int
  module procedure :: tile_3d_real
endinterface tile

interface zeros
  module procedure :: zeros_int
  module procedure :: zeros_real
endinterface zeros

!===============================================================================
contains



!-------------------------------------------------------------------------------
pure function diff_1d(x) result(dx)
  !! Returns a centered-difference of a 1-d array, with first order
  !! differencing applied for the boundary points. This procedure is overloaded
  !! by the generic procedure `diff`.
  real(kind=rk),dimension(:),intent(in)  :: x !! Input array
  real(kind=rk),dimension(:),allocatable :: dx
  integer(kind=ik) :: idm
  idm = size(x)
  allocate(dx(idm))
  if(idm == 0)then
    return
  elseif(idm == 1)then
    dx = 0
    return
  endif
  dx(2:idm-1) = 0.5_rk*(x(3:idm)-x(1:idm-2))
  dx(1) = x(2)-x(1)
  dx(idm) = x(idm)-x(idm-1)
endfunction diff_1d
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function diff_2d(x,dim) result(dx)
  !! Returns a centered-difference of a 2-d array along dimension dim, with
  !! first order differencing applied for the boundary points. This procedure is
  !! overloaded by the generic procedure `diff`.
  real(kind=rk),dimension(:,:),intent(in) :: x
    !! Input array
  integer(kind=ik),intent(in) :: dim
    !! Dimension along which to differentiate
  real(kind=rk),dimension(:,:),allocatable :: dx
  integer(kind=ik) :: idm,jdm
  idm = size(x,dim=1)
  jdm = size(x,dim=2)
  allocate(dx(idm,jdm))
  if(idm == 0)then
    return
  elseif(idm == 1)then
    dx = 0
    return
  endif
  if(dim == 1)then
    dx(2:idm-1,:) = 0.5_rk*(x(3:idm,:)-x(1:idm-2,:))
    dx(1,:) = x(2,:)-x(1,:)
    dx(idm,:) = x(idm,:)-x(idm-1,:)
  elseif(dim == 2)then
    dx(:,2:idm-1) = 0.5_rk*(x(:,3:idm)-x(:,1:idm-2))
    dx(:,1) = x(2,:)-x(:,1)
    dx(:,idm) = x(:,idm)-x(:,idm-1)
  else
    dx = 0
  endif
endfunction diff_2d
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function diff_periodic_1d(x) result(dx)
  !! Returns a centered-difference of a 1-d array with periodic boundary
  !! conditions. This procedure is overloaded by the generic procedure `diff`.
  real(kind=rk),dimension(:),intent(in)  :: x !! Input array
  real(kind=rk),dimension(:),allocatable :: dx
  integer(kind=ik) :: idm
  idm = size(x)
  allocate(dx(idm))
  if(idm == 0)then
    return
  elseif(idm == 1)then
    dx = 0
    return
  endif
  dx(2:idm-1) = 0.5_rk*(x(3:idm)-x(1:idm-2))
  dx(1) = 0.5_rk*(x(2)-x(idm))
  dx(idm) = 0.5_rk*(x(1)-x(idm-1))
endfunction diff_periodic_1d
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function diff_periodic_2d(x,dim) result(dx)
  !! Returns a centered-difference of a 2-d array along dimension dim, with
  !! periodic boundary conditions. This procedure is overloaded by the generic
  !! procedure `diff`.
  real(kind=rk),dimension(:,:),intent(in) :: x
    !! Input array
  integer(kind=ik),intent(in) :: dim
    !! Dimension along which to differentiate
  real(kind=rk),dimension(:,:),allocatable :: dx
  integer(kind=ik) :: idm,jdm
  idm = size(x,dim=1)
  jdm = size(x,dim=2)
  allocate(dx(idm,jdm))
  if(idm == 0)then
    return
  elseif(idm == 1)then
    dx = 0
    return
  endif
  if(dim == 1)then
    dx(2:idm-1,:) = 0.5_rk*(x(3:idm,:)-x(1:idm-2,:))
    dx(1,:) = 0.5_rk*(x(2,:)-x(idm,:))
    dx(idm,:) = 0.5_rk*(x(1,:)-x(idm-1,:))
  elseif(dim == 2)then
    dx(:,2:idm-1) = 0.5_rk*(x(:,3:idm)-x(:,1:idm-2))
    dx(:,1) = 0.5_rk*(x(:,2)-x(:,idm))
    dx(:,idm) = 0.5_rk*(x(:,1)-x(:,idm-1))
  else
    dx = 0
  endif
endfunction diff_periodic_2d
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function ones_int(length,kindflag) result(ones)
  !! Returns a 1-d array of integer ones. This procedure is overloaded by the
  !! generic procedure `ones`.
  integer(kind=ik),intent(in) :: length   !! Array length
  integer(kind=ik),intent(in) :: kindflag !! Array type
  integer(kind=ik),dimension(:),allocatable :: ones
  allocate(ones(length))
  ones = 1
endfunction ones_int
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function ones_real(length,kindflag) result(ones)
  !! Returns a 1-d array of floating-point ones. This procedure is overloaded by
  !! the generic procedure `ones`.
  integer(kind=ik),intent(in) :: length !! Array length
  real(kind=rk),intent(in) :: kindflag !! Array type
  real(kind=rk),dimension(:),allocatable :: ones
  allocate(ones(length))
  ones = 1._rk
endfunction ones_real
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function range_int(start,end,increment) result(range)
  !! Returns an array of integers given start, end, and increment values. If the
  !! increment argument is not passed, default increment is 1. This procedure is
  !! overloaded by the generic procedure `range`.
  integer(kind=ik),intent(in) :: start
    !! Start value of the array
  integer(kind=ik),intent(in) :: end
    !! End value of the array
  integer(kind=ik),intent(in),optional :: increment
    !! Array increment
  integer(kind=ik),dimension(:),allocatable :: range
  integer(kind=ik) :: i
  integer(kind=ik) :: increment_
  integer(kind=ik) :: length
  if(present(increment))then
    increment_ = increment
  else
    increment_ = 1
  endif
  length = (end-start)/increment_+1
  allocate(range(length))
  do concurrent(i = 1:length)
    range(i) = start+(i-1)*increment_
  enddo
endfunction range_int
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function range_real(start,end,increment) result(range)
  !! Returns an array of reals given start, end, and increment values. If the
  !! increment argument is not passed, default increment is 1. This procedure is
  !! overloaded by the generic procedure `range`.
  real(kind=rk),intent(in) :: start
    !! Start value of the array
  real(kind=rk),intent(in) :: end
    !! End value of the array
  real(kind=rk),intent(in),optional :: increment
    !! Array increment
  real(kind=rk),dimension(:),allocatable :: range
  real(kind=rk) :: increment_
  integer(kind=ik) :: i
  integer(kind=ik) :: length
  if(present(increment))then
    increment_ = increment
  else
    increment_ = 1
  endif
  length = int((end-start)/increment_)+1
  allocate(range(length))
  do concurrent(i = 1:length)
    range(i) = start+(i-1)*increment_
  enddo
endfunction range_real
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function tile_1d_int(array,n) result(tiled_array)
  !! Tiles the input array `n` times. Returns a tiled array that has rank equal
  !! to `size(shape(array))+1` and that has values equal to values of `array`,
  !! repeated `n` times. This version is for 1-d input array of integers. This
  !! procedure is overloaded by the generic procedure `tile`.
  integer(kind=ik),dimension(:),intent(in) :: array !! Input array
  integer(kind=ik),intent(in) :: n !! Number of times to copy input array
  integer(kind=ik),dimension(:,:),allocatable :: tiled_array
  integer(kind=ik) :: i
  allocate(tiled_array(size(array),n))
  do concurrent(i=1:n)
    tiled_array(:,i) = array(:)
  enddo
endfunction tile_1d_int
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function tile_1d_real(array,n) result(tiled_array)
  !! Tiles the input array `n` times. Returns a tiled array that has rank equal
  !! to `size(shape(array))+1` and that has values equal to values of `array`,
  !! repeated `n` times. This version is for 1-d input array of reals. This
  !! procedure is overloaded by the generic procedure `tile`.
  real(kind=rk),dimension(:),intent(in) :: array !! Input array
  integer(kind=ik),intent(in) :: n !! Number of times to copy input array
  real(kind=rk),dimension(:,:),allocatable :: tiled_array
  integer(kind=ik) :: i
  allocate(tiled_array(size(array),n))
  do concurrent(i=1:n)
    tiled_array(:,i) = array(:)
  enddo
endfunction tile_1d_real
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function tile_2d_int(array,n) result(tiled_array)
  !! Tiles the input array `n` times. Returns a tiled array that has rank equal
  !! to `size(shape(array))+1` and that has values equal to values of `array`,
  !! repeated `n` times. This version is for 2-d input array of integers. This
  !! procedure is overloaded by the generic procedure `tile`.
  integer(kind=ik),dimension(:,:),intent(in) :: array !! Input array
  integer(kind=ik),intent(in) :: n !! Number of times to copy input array
  integer(kind=ik),dimension(:,:,:),allocatable :: tiled_array
  integer(kind=ik) :: i
  allocate(tiled_array(size(array,dim=1),size(array,dim=2),n))
  do concurrent(i=1:n)
    tiled_array(:,:,i) = array(:,:)
  enddo
endfunction tile_2d_int
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function tile_2d_real(array,n) result(tiled_array)
  !! Tiles the input array `n` times. Returns a tiled array that has rank equal
  !! to `size(shape(array))+1` and that has values equal to values of `array`,
  !! repeated `n` times. This version is for 2-d input array of reals. This
  !! procedure is overloaded by the generic procedure `tile`.
  real(kind=rk),dimension(:,:),intent(in) :: array !! Input array
  integer(kind=ik),intent(in) :: n !! Number of times to copy input array
  real(kind=rk),dimension(:,:,:),allocatable :: tiled_array
  integer(kind=ik) :: i
  allocate(tiled_array(size(array,dim=1),size(array,dim=2),n))
  do concurrent(i=1:n)
    tiled_array(:,:,i) = array(:,:)
  enddo
endfunction tile_2d_real
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function tile_3d_int(array,n) result(tiled_array)
  !! Tiles the input array `n` times. Returns a tiled array that has rank equal
  !! to `size(shape(array))+1` and that has values equal to values of `array`,
  !! repeated `n` times. This version is for 3-d input array of integers. This
  !! procedure is overloaded by the generic procedure `tile`.
  integer(kind=ik),dimension(:,:,:),intent(in) :: array !! Input array
  integer(kind=ik),intent(in) :: n !! Number of times to copy input array
  integer(kind=ik),dimension(:,:,:,:),allocatable :: tiled_array
  integer(kind=ik) :: i
  allocate(tiled_array(size(array,dim=1),size(array,dim=2),size(array,dim=3),n))
  do concurrent(i=1:n)
    tiled_array(:,:,:,i) = array(:,:,:)
  enddo
endfunction tile_3d_int
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function tile_3d_real(array,n) result(tiled_array)
  !! Tiles the input array `n` times. Returns a tiled array that has rank equal
  !! to `size(shape(array))+1` and that has values equal to values of `array`,
  !! repeated `n` times. This version is for 3-d input array of reals. This
  !! procedure is overloaded by the generic procedure `tile`.
  real(kind=rk),dimension(:,:,:),intent(in) :: array !! Input array
  integer(kind=ik),intent(in) :: n !! Number of times to copy input array
  real(kind=rk),dimension(:,:,:,:),allocatable :: tiled_array
  integer(kind=ik) :: i
  allocate(tiled_array(size(array,dim=1),size(array,dim=2),size(array,dim=3),n))
  do concurrent(i=1:n)
    tiled_array(:,:,:,i) = array(:,:,:)
  enddo
endfunction tile_3d_real
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function zeros_int(length,kindflag) result(zeros)
  !! Returns a 1-d array of integer zeros. This procedure is overloaded by the
  !! generic procedure `zeros`.
  integer(kind=ik),intent(in) :: length !! Array length
  integer(kind=ik),intent(in) :: kindflag !! Array type
  integer(kind=ik),dimension(:),allocatable :: zeros
  allocate(zeros(length))
  zeros = 0
endfunction zeros_int
!-------------------------------------------------------------------------------



!-------------------------------------------------------------------------------
pure function zeros_real(length,kindflag) result(zeros)
  !! Returns a 1-d array of floating-point zeros. This procedure is overloaded by
  !! the generic procedure `zeros`.
  integer(kind=ik),intent(in) :: length !! Array length
  real(kind=rk),intent(in) :: kindflag !! Array type
  real(kind=rk),dimension(:),allocatable :: zeros
  allocate(zeros(length))
  zeros = 0._rk
endfunction zeros_real
!-------------------------------------------------------------------------------
endmodule mod_utility