gradient.f90 Source File


This file depends on

sourcefile~~gradient.f90~~EfferentGraph sourcefile~gradient.f90 gradient.f90 sourcefile~calculus.f90 calculus.f90 sourcefile~gradient.f90->sourcefile~calculus.f90 sourcefile~phys_consts.f90 phys_consts.F90 sourcefile~calculus.f90->sourcefile~phys_consts.f90 sourcefile~mesh.f90 mesh.f90 sourcefile~calculus.f90->sourcefile~mesh.f90 sourcefile~mesh.f90->sourcefile~phys_consts.f90

Contents

Source Code


Source Code

submodule (calculus) gradient

contains

module procedure grad3D1_curv_3
! grad3D1_curv_3(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 1-DIMENSION.  IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE - EXCEPT FOR THE GRID.
!-------STRUCTURE.
!-------
!-------FOR THIS AND FOLLOWING CURV DERIVATIVE PROCEDURES THE UPPER
!-------AND LOWER BOUNDS FOR DIFFERENTIATION CANNOT BE DETERMINED
!-------WITHOUT ADDITIONAL ARGUMENTS SINCE STRUCTURE X CANNOT BE
!-------BE TRIMMED IN THE SAME WAY AS A NORMAL ARRAY.  ESSENTIALLY
!-------THE INPUT ARRAY "F" AND GRID NEED TO BE INDEXED DIFFERENTLY, LEADING
!-------TO TWO SEPARATE SETS ON INDICES THROUGHOUT THIS AND SIMILAR ROUTINES.
!-------
!-------ONE ISSUE ADDRESSED HERE IS THAT THE METRIC FACTORS NEED TO KNOW
!-------WHAT PART OF THE GRID THAT THEY ARE BEING USED OVER...  IE
!-------IF ANY OF THESE IS FULL GRID THEN THE HALL VERSIONS SHOUDL
!-------SHOULD BE USED FOR THE METRIC FACTORS...
!------------------------------------------------------------

integer :: ix2,ix3,lx1,lx2,lx3

!    real(wp), dimension(1:size(f,1),1:size(f,2),1:size(f,3)) :: h1,h2,h3
!! local references to the metric factors to be used in the derivative
!    real(wp), dimension(1:size(f,1)) :: dx1
!! local reference to the backward difference
real(wp), dimension(:,:,:), pointer :: h1
!! local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx1
!! local reference to the backward difference

lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)


!! ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
  error stop '!!!  Inconsistent array and mesh sizes in grad3D1 gradient function.'
  !! just bail on it and let the user figure it out
end if


!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
!Can avoid wasting memory and copying of metric factor arrays by recoding with pointers
!Unfortunately a pointer is not gauranteed to be contiguous in memory so I'm not sure this is the way to go
if (lx3<=x%lx3+4) then
  h1=>x%h1(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
else if (lx3<=x%lx3all+4) then
  h1=>x%h1all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
  print *,   '! Accessing root-only grid information'
else
  error stop '!!!  Array size is larger full mesh.'
end if
dx1=>x%dx1(lbnd1:ubnd1)


!! NOW EXECUTE THE FINITE DIFFERENCES -
!! NOTE THAT LOOP INDICES ARE MEANT TO INDEX ARRAY BEING DIFFERENCED AND NOT THE MESH STRUCTURE,
!! WHICH USES INPUT BOUNDS.  TO KEEP THE CODE CLEAN I'VE ALIASED THE GRID VARS SO THAT THEY MAY BE ACCESSED BY LOOP INDEX.
do ix3=1,lx3
  do ix2=1,lx2
    grad3D1_curv_3(1,ix2,ix3) = (f(2,ix2,ix3)-f(1,ix2,ix3))/dx1(1)/h1(1,ix2,ix3)
    !! fwd diff. at beginning, note that h1 is cell-centered
    grad3D1_curv_3(2:lx1-1,ix2,ix3) = (f(3:lx1,ix2,ix3)-f(1:lx1-2,ix2,ix3)) &
                             /(dx1(3:lx1)+dx1(2:lx1-1))/h1(2:lx1-1,ix2,ix3)
    !! centered diff. in the middleq
    grad3D1_curv_3(lx1,ix2,ix3) = (f(lx1,ix2,ix3)-f(lx1-1,ix2,ix3))/dx1(lx1)/h1(lx1,ix2,ix3)
    !! backward diff. at end
  end do
end do
end procedure grad3D1_curv_3


module procedure grad3D1_curv_23
! grad3D1_curv_23(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 1-DIMENSION.  IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE - EXCEPT FOR THE GRID.
!-------STRUCTURE.
!-------
!-------FOR THIS AND FOLLOWING CURV DERIVATIVE PROCEDURES THE UPPER
!-------AND LOWER BOUNDS FOR DIFFERENTIATION CANNOT BE DETERMINED
!-------WITHOUT ADDITIONAL ARGUMENTS SINCE STRUCTURE X CANNOT BE
!-------BE TRIMMED IN THE SAME WAY AS A NORMAL ARRAY.  ESSENTIALLY
!-------THE INPUT ARRAY "F" AND GRID NEED TO BE INDEXED DIFFERENTLY, LEADING
!-------TO TWO SEPARATE SETS ON INDICES THROUGHOUT THIS AND SIMILAR ROUTINES.
!-------
!-------ONE ISSUE ADDRESSED HERE IS THAT THE METRIC FACTORS NEED TO KNOW
!-------WHAT PART OF THE GRID THAT THEY ARE BEING USED OVER...  IE
!-------IF ANY OF THESE IS FULL GRID THEN THE HALL VERSIONS SHOUDL
!-------SHOULD BE USED FOR THE METRIC FACTORS...
!------------------------------------------------------------

integer :: ix2,ix3,lx1,lx2,lx3

!    real(wp), dimension(1:size(f,1),1:size(f,2),1:size(f,3)) :: h1,h2,h3
!! local references to the metric factors to be used in the derivative
!    real(wp), dimension(1:size(f,1)) :: dx1
!! local reference to the backward difference
real(wp), dimension(:,:,:), pointer :: h1
!! local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx1
!! local reference to the backward difference

lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)


!ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
  error stop '!!!  Inconsistent array and mesh sizes in grad3D1 gradient function.'
  !! just bail on it and let the user figure it out
end if


!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
!Can avoid wasting memory and copying of metric factor arrays by recoding with pointers
!Unfortunately a pointer is not gauranteed to be contiguous in memory so I'm not sure this is the way to go
if (lx3<=x%lx3+4) then
  h1=>x%h1(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
else if (lx3<=x%lx3all+4) then
  h1=>x%h1all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
  print *,   '! Accessing root-only grid information'
else
  error stop '!!!  Array size is larger full mesh.'
end if
dx1=>x%dx1(lbnd1:ubnd1)


!! NOW EXECUTE THE FINITE DIFFERENCES
!! NOTE THAT LOOP INDICES ARE MEANT TO INDEX ARRAY BEING DIFFERENCED AND NOT THE MESH STRUCTURE,
!! WHICH USES INPUT BOUNDS.  TO KEEP THE CODE CLEAN I'VE ALIASED THE GRID VARS SO THAT THEY MAY BE ACCESSED BY LOOP INDEX.
do ix3=1,lx3
  do ix2=1,lx2
    grad3D1_curv_23(1,ix2,ix3) = (f(2,ix2,ix3)-f(1,ix2,ix3))/dx1(1)/h1(1,ix2,ix3)
    !! fwd diff. at beginning, note that h1 is cell-centered
    grad3D1_curv_23(2:lx1-1,ix2,ix3) = (f(3:lx1,ix2,ix3)-f(1:lx1-2,ix2,ix3)) &
                             /(dx1(3:lx1)+dx1(2:lx1-1))/h1(2:lx1-1,ix2,ix3)
    !! centered diff. in the middleq
    grad3D1_curv_23(lx1,ix2,ix3) = (f(lx1,ix2,ix3)-f(lx1-1,ix2,ix3))/dx1(lx1)/h1(lx1,ix2,ix3)
    !! backward diff. at end
  end do
end do
end procedure grad3D1_curv_23


module procedure grad3D2_curv_3
! grad3D2_curv_3(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 2-DIMENSION.  IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE
!------------------------------------------------------------

integer :: ix1,ix3,lx1,lx2,lx3

real(wp), dimension(:,:,:), pointer :: h2   !local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx2    !local reference to the backward difference

lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)

if (lx2>1) then    !if we have a singleton dimension then we are doing a 2D run and the derivatives in this direction are zero

  !ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
  if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
    error stop '!!!  Inconsistent array and mesh sizes in gradient function.'   !just bail on it and let the user figure it out
  end if


  !CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
  !INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
  if (lx3<=x%lx3+4) then
    h2=>x%h2(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
  else if (lx3<=x%lx3all+4) then
    h2=>x%h2all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
    print *,   '! Accessing root-only grid information'
  else
    error stop '!!!  Array size is larger full mesh.'
  end if
  dx2=>x%dx2(lbnd2:ubnd2)


  !DIFFERENCING
  do ix3=1,lx3
    do ix1=1,lx1
      grad3D2_curv_3(ix1,1,ix3)=(f(ix1,2,ix3)-f(ix1,1,ix3))/dx2(2)/h2(ix1,1,ix3)
      grad3D2_curv_3(ix1,2:lx2-1,ix3)=(f(ix1,3:lx2,ix3)-f(ix1,1:lx2-2,ix3)) &
                               /(dx2(3:lx2)+dx2(2:lx2-1))/h2(ix1,2:lx2-1,ix3)
      grad3D2_curv_3(ix1,lx2,ix3)=(f(ix1,lx2,ix3)-f(ix1,lx2-1,ix3))/dx2(lx2)/h2(ix1,lx2,lx3)
    end do
  end do
else
  grad3D2_curv_3=0._wp
end if
end procedure grad3D2_curv_3


module procedure grad3D2_curv_23
! grad3D2_curv_23(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 2-DIMENSION.  IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE
!------------------------------------------------------------

integer :: ix1,ix3,lx1,lx2,lx3

real(wp), dimension(:,:,:), pointer :: h2   !local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx2    !local reference to the backward difference

lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)

if (lx2>1) then    !if we have a singleton dimension then we are doing a 2D run and the derivatives in this direction are zero

  !ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
  if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
    error stop '!!!  Inconsistent array and mesh sizes in gradient function.'
    !! just bail on it and let the user figure it out
  end if


  !CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
  !INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
  if (lx3<=x%lx3+4) then     !this is a derivative over a slab region (subgrid)
    h2=>x%h2(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
    dx2=>x%dx2(lbnd2:ubnd2)
  else if (lx3<=x%lx3all+4) then
    !! if a larger dimension was specified for x3 then assume that we are differentiating over x2all and x3all
    h2=>x%h2all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
    dx2=>x%dx2all(lbnd2:ubnd2)
    print *,   '! Accessing root-only grid information, while taking derivative in 2-direction'
  else
    error stop '!!!  Array size is larger full mesh.'
  end if


  !DIFFERENCING
  do ix3=1,lx3
    do ix1=1,lx1
      grad3D2_curv_23(ix1,1,ix3)=(f(ix1,2,ix3)-f(ix1,1,ix3))/dx2(2)/h2(ix1,1,ix3)
      grad3D2_curv_23(ix1,2:lx2-1,ix3)=(f(ix1,3:lx2,ix3)-f(ix1,1:lx2-2,ix3)) &
                               /(dx2(3:lx2)+dx2(2:lx2-1))/h2(ix1,2:lx2-1,ix3)
      grad3D2_curv_23(ix1,lx2,ix3)=(f(ix1,lx2,ix3)-f(ix1,lx2-1,ix3))/dx2(lx2)/h2(ix1,lx2,lx3)
    end do
  end do
else
  grad3D2_curv_23=0._wp
end if
end procedure grad3D2_curv_23


module procedure grad3D3_curv_3
! grad3D3_curv_3(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 3-DIMENSION.  IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE
!-------
!-------AN EXTRA STEP IS NEEDED IN THIS ROUTINE SINCE WE HAVE
!-------TO DETERMINE WHETHER THIS IS A FULL-GRID OR SUBGRID
!-------DERIVATIVE.
!------------------------------------------------------------

integer :: ix1,ix2,lx1,lx2,lx3

real(wp), dimension(:,:,:), pointer :: h3   !local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx3    !local reference to the backward difference

lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)


!ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
  error stop '!!!  Inconsistent array and mesh sizes in gradient function.'   !just bail on it and let the user figure it out
end if


!CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
!INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
!Can avoid wasting memory and copying of metric factor arrays by recoding with pointers
!Unfortunately a pointer is not gauranteed to be contiguous in memory so I'm not sure this is the way to go
if (lx3<=x%lx3+4) then
  h3=>x%h3(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
  dx3=>x%dx3(lbnd3:ubnd3)
else if (lx3<=x%lx3all+4) then
  h3=>x%h3all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
  dx3=>x%dx3all(lbnd3:ubnd3)
  print *,   '! Accessing root-only grid information'
else
  error stop '!!!  Array size is larger than full mesh.'
end if


!FINITE DIFFERENCING
do ix2=1,lx2
  do ix1=1,lx1
    grad3D3_curv_3(ix1,ix2,1)=(f(ix1,ix2,2)-f(ix1,ix2,1))/dx3(2)/h3(ix1,ix2,1)
    grad3D3_curv_3(ix1,ix2,2:lx3-1)=(f(ix1,ix2,3:lx3)-f(ix1,ix2,1:lx3-2)) &
                             /(dx3(3:lx3)+dx3(2:lx3-1))/h3(ix1,ix2,2:lx3-1)
    grad3D3_curv_3(ix1,ix2,lx3)=(f(ix1,ix2,lx3)-f(ix1,ix2,lx3-1))/dx3(lx3)/h3(ix1,ix2,lx3)
  end do
end do

end procedure grad3D3_curv_3


module procedure grad3D3_curv_23
! grad3D3_curv_23(f,x,lbnd1,ubnd1,lbnd2,ubnd2,lbnd3,ubnd3)
!------------------------------------------------------------
!-------COMPUTE A 3D GRADIENT ALONG THE 3-DIMENSION.  IT IS EXPECTED THAT
!-------GHOST CELLS WILL HAVE BEEN TRIMMED FROM ARRAYS BEFORE
!-------THEY ARE PASSED INTO THIS ROUTINE
!-------
!-------AN EXTRA STEP IS NEEDED IN THIS ROUTINE SINCE WE HAVE
!-------TO DETERMINE WHETHER THIS IS A FULL-GRID OR SUBGRID
!-------DERIVATIVE.
!------------------------------------------------------------

integer :: ix1,ix2,lx1,lx2,lx3

real(wp), dimension(:,:,:), pointer :: h3   !local references to the metric factors to be used in the derivative
real(wp), dimension(:), pointer :: dx3    !local reference to the backward difference

lx1=size(f,1)
lx2=size(f,2)
lx3=size(f,3)


if (lx3>1) then    !only differentiate if we have non-singleton dimension, otherwise set to zero
  !ERROR CHECKING TO MAKE SURE DIFFRENCING IS DONE OVER A CONSISTENTLY-SIZED GRID
  if (lx1 /= ubnd1-lbnd1+1 .or. lx2 /= ubnd2-lbnd2+1 .or. lx3 /= ubnd3-lbnd3+1) then
    error stop '!!!  Inconsistent array and mesh sizes in gradient function.'   !just bail on it and let the user figure it out
  end if


  !CHOOSE THE METRIC FACTORS VARIABLES BASED ON THE SIZE OF THE X3-VARIABLE, ALSO RECAST SO THE
  !INDICES USED FOR F CAN ALSO BE USED IN THE METRIC FACTOR AND DX VARIABLE
  !Can avoid wasting memory and copying of metric factor arrays by recoding with pointers
  !Unfortunately a pointer is not gauranteed to be contiguous in memory so I'm not sure this is the way to go
  if (lx3<=x%lx3+4) then
    h3=>x%h3(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
    dx3=>x%dx3(lbnd3:ubnd3)
  else if (lx3<=x%lx3all+4) then
    h3=>x%h3all(lbnd1:ubnd1,lbnd2:ubnd2,lbnd3:ubnd3)
    dx3=>x%dx3all(lbnd3:ubnd3)
    print *,   '! Accessing root-only grid information while differentiating in x3'
  else
    error stop '!!!  Array size is larger than full mesh.'
  end if


  !FINITE DIFFERENCING
  do ix2=1,lx2
    do ix1=1,lx1
      grad3D3_curv_23(ix1,ix2,1)=(f(ix1,ix2,2)-f(ix1,ix2,1))/dx3(2)/h3(ix1,ix2,1)
      grad3D3_curv_23(ix1,ix2,2:lx3-1)=(f(ix1,ix2,3:lx3)-f(ix1,ix2,1:lx3-2)) &
                               /(dx3(3:lx3)+dx3(2:lx3-1))/h3(ix1,ix2,2:lx3-1)
      grad3D3_curv_23(ix1,ix2,lx3)=(f(ix1,ix2,lx3)-f(ix1,ix2,lx3-1))/dx3(lx3)/h3(ix1,ix2,lx3)
    end do
  end do
else
  grad3D3_curv_23=0._wp
end if

end procedure grad3D3_curv_23

end submodule gradient