subroutine IcosahedralLorentzGrid_new( &
  & cptr, glevel, ic_base_radius, vertical_layer_num, mpi_flag &
  & ) bind(C, name='IcosahedralLorentzGrid_new')

  use, intrinsic :: iso_c_binding

  use dc_types, only: DP

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, IcosahedralLorentzGrid_Init

  use CBinding_Utility, only: c_f_logical

  implicit none

  type(c_ptr), intent(out) :: cptr
  integer(c_int), value :: glevel
  real(DP), value :: ic_base_radius
  integer(c_int), value :: vertical_layer_num
  logical(c_bool), value :: mpi_flag

  type(IcosahedralLorentzGrid), pointer :: ptr

  allocate(ptr)

  call IcosahedralLorentzGrid_Init( &
    & ptr, glevel, ic_base_radius, vertical_layer_num, &
    & c_f_logical(mpi_flag) )

  cptr = c_loc(ptr)

end subroutine IcosahedralLorentzGrid_new

subroutine IcosahedralLorentzGrid_del( &
  & cptr &
  & )  bind(C, name='IcosahedralLorentzGrid_del')

  use, intrinsic :: iso_c_binding

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, IcosahedralLorentzGrid_Final

  implicit none
  type(c_ptr), intent(inout) :: cptr

  type(IcosahedralLorentzGrid), pointer :: ptr

  call c_f_pointer(cptr, ptr)
  call IcosahedralLorentzGrid_Final(ptr)
  deallocate(ptr)

  cptr = c_null_ptr

end subroutine IcosahedralLorentzGrid_del

subroutine IcosahedralLorentzGrid_prepare_DerivateTool( &
  & cptr &
  & ) bind(C, name='IcosahedralLorentzGrid_prepare_DerivateTool')

  use, intrinsic :: iso_c_binding

  use dc_types, only: DP

  use Field_IcGrid2D_Manager, only: &
    & Field_IcGrid2D

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, prepare_DerivateTool

  implicit none
  type(c_ptr), value :: cptr

  type(IcosahedralLorentzGrid), pointer :: ptr

  call c_f_pointer(cptr, ptr)
  call prepare_DerivateTool(ptr)

end subroutine IcosahedralLorentzGrid_prepare_DerivateTool

subroutine IcosahedralLorentzGrid_prepare_TerrainFollowingCoordinate( &
  & cptr, cptr_Zs, Z_T &
  & ) bind(C, name='IcosahedralLorentzGrid_prepare_TerrainFollowingCoordinate')

  use, intrinsic :: iso_c_binding

  use dc_types, only: DP

  use Field_IcGrid2D_Manager, only: &
    & Field_IcGrid2D

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, prepare_TerrainFollowingCoordinate

  implicit none
  type(c_ptr), value :: cptr
  type(c_ptr), value :: cptr_Zs
  real(DP), value :: Z_T

  type(IcosahedralLorentzGrid), pointer :: ptr
  type(Field_IcGrid2D), pointer :: ptr_Zs

  call c_f_pointer(cptr, ptr)
  call c_f_pointer(cptr_Zs, ptr_Zs)
  call prepare_TerrainFollowingCoordinate(ptr, ptr_Zs, Z_T)

end subroutine IcosahedralLorentzGrid_prepare_TerrainFollowingCoordinate

subroutine IcosahedralLorentzGrid_get_TerrainFollowingCoordinate( &
  & cptr, lorentzGrid_LevelKind, cptr_tfcoord &
  & ) bind(C, name='IcosahedralLorentzGrid_get_TerrainFollowingCoordinate')

  use, intrinsic :: iso_c_binding

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, get_TerrainFollowingCoordinate

  use TFCoord_IcGrid3D_helper, only: &
    & TFCoord_IcGrid3D

  implicit none

  type(c_ptr), value :: cptr
  integer(c_int), value :: lorentzGrid_LevelKind
  type(c_ptr), intent(out) :: cptr_tfcoord

  type(IcosahedralLorentzGrid), pointer :: ptr
  type(TFCoord_IcGrid3D), pointer :: ptr_tfcoord

  call c_f_pointer(cptr, ptr)
  ptr_tfcoord => get_TerrainFollowingCoordinate(ptr, lorentzGrid_LevelKind)

  cptr_tfcoord = c_loc(ptr_tfcoord)

end subroutine IcosahedralLorentzGrid_get_TerrainFollowingCoordinate

subroutine IcosahedralLorentzGrid_get_HorizontalGrid( &
  & cptr, cptr_icgrid2D &
  & ) bind(C, name='IcosahedralLorentzGrid_get_HorizontalGrid')

  use, intrinsic :: iso_c_binding

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, get_HorizontalGrid

  use IcGrid2D_FVM_Manager, only: &
    & IcGrid2D_FVM, get_glevel

  implicit none

  type(c_ptr), value :: cptr
  type(c_ptr), intent(out) :: cptr_icgrid2d

  type(IcosahedralLorentzGrid), pointer :: ptr
  type(IcGrid2D_FVM), pointer :: ptr_icgrid2D

  call c_f_pointer(cptr, ptr)
  ptr_icgrid2D => get_HorizontalGrid(ptr)

  cptr_icgrid2d = c_loc(ptr_icgrid2D)

end subroutine IcosahedralLorentzGrid_get_HorizontalGrid


subroutine IcosahedralLorentzGrid_get_HVIcGrid3D( &
  & cptr, cptr_icgrid3D, lorentzGrid_LevelKind &
  & ) bind(C, name='IcosahedralLorentzGrid_get_HVIcGrid3D')

  use, intrinsic :: iso_c_binding

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, get_HVIcGrid3D

  use IcGrid3D_FVM_Manager, only: &
    & IcGrid3D_FVM

  implicit none

  type(c_ptr), value :: cptr
  integer(c_int), value :: lorentzGrid_LevelKind
  type(c_ptr), intent(out) :: cptr_icgrid3d

  type(IcosahedralLorentzGrid), pointer :: ptr
  type(IcGrid3D_FVM), pointer :: ptr_icgrid3D

  call c_f_pointer(cptr, ptr)
  ptr_icgrid3D => get_HVIcGrid3D(ptr, lorentzGrid_LevelKind)

  cptr_icgrid3d = c_loc(ptr_icgrid3D)

end subroutine IcosahedralLorentzGrid_get_HVIcGrid3D

subroutine IcosahedralLorentzGrid_get_VerticalDerivateTool( &
  & cptr, lorentzGrid_LevelKind, cptr_derivate &
  & ) bind(C, name='IcosahedralLorentzGrid_get_VerticalDerivateTool')

  use, intrinsic :: iso_c_binding

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, get_VerticalDerivateTool

  use VDerivate_Field_IcGrid3D_Manager, only: &
    & VDerivate_Field_IcGrid3D

  implicit none

  type(c_ptr), value :: cptr
  integer(c_int), value :: lorentzGrid_LevelKind
  type(c_ptr), intent(out) :: cptr_derivate

  type(IcosahedralLorentzGrid), pointer :: ptr
  type(VDerivate_Field_IcGrid3D), pointer :: ptr_derivate

  call c_f_pointer(cptr, ptr)
  ptr_derivate => get_VerticalDerivateTool(ptr, lorentzGrid_LevelKind)

  cptr_derivate = c_loc(ptr_derivate)

end subroutine IcosahedralLorentzGrid_get_VerticalDerivateTool


subroutine IcosahedralLorentzGrid_get_HorizontalDerivateTool( &
  & cptr, cptr_derivate &
  & ) bind(C, name='IcosahedralLorentzGrid_get_HorizontalDerivateTool')

  use, intrinsic :: iso_c_binding

  use IcosahedralLorentzGrid_Manager, only: &
    & IcosahedralLorentzGrid, get_HorizontalDerivateTool

  use Derivate_Field_IcGrid2D_Manager, only: &
    & Derivate_Field_IcGrid2D

  implicit none

  type(c_ptr), value :: cptr
  type(c_ptr), intent(out) :: cptr_derivate

  type(IcosahedralLorentzGrid), pointer :: ptr
  type(Derivate_Field_IcGrid2D), pointer :: ptr_derivate

  call c_f_pointer(cptr, ptr)
  ptr_derivate => get_HorizontalDerivateTool(ptr)

  cptr_derivate = c_loc(ptr_derivate)

end subroutine IcosahedralLorentzGrid_get_HorizontalDerivateTool
