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

  use, intrinsic :: iso_c_binding

  use dc_types, only: DP

  use IcGrid3D_FVM_Manager, only: &
    & IcGrid3D_FVM, IcGrid3D_FVM_Init

  use IcGrid2D_FVM_Manager, only: &
    & IcGrid2D_FVM

  implicit none
  type(c_ptr), intent(out) :: cptr
  type(c_ptr), value :: cptr_icgrid2D
  integer(c_int), value :: vertical_level_num

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

  allocate(ptr)
  call c_f_pointer(cptr_icgrid2D, ptr_icgrid2D)
  call IcGrid3D_FVM_Init(ptr, ptr_icgrid2D, vertical_level_num)

  cptr = c_loc(ptr)

end subroutine IcGrid3D_FVM_new

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

  use, intrinsic :: iso_c_binding

  use IcGrid3D_FVM_Manager, only: &
    & IcGrid3D_FVM, IcGrid3D_FVM_Final

  use dc_types, only: DP

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

  type(IcGrid3D_FVM), pointer :: ptr

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

  cptr = c_null_ptr

end subroutine IcGrid3D_FVM_del

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

  use, intrinsic :: iso_c_binding

  use IcGrid3D_FVM_Manager, only: &
    & IcGrid3D_FVM, get_icgrid2D

  use IcGrid2D_FVM_Manager, only: &
    & IcGrid2D_FVM

  implicit none

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

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

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

  cptr_icgrid2d = c_loc(ptr_icgrid2D)

end subroutine IcosahedralLorentzGrid_get_HorizontalGrid

function IcGrid3D_FVM_get_vertical_level_num( &
  & cptr &
  & ) result(vertical_level_num) &
  & bind(C, name='IcGrid3D_FVM_get_vertical_level_num')

  use, intrinsic :: iso_c_binding

  use IcGrid3D_FVM_Manager, only: &
    & IcGrid3D_FVM, get_vertical_level_num

  implicit none

  type(c_ptr), value :: cptr
  integer(c_int) :: vertical_level_num

  type(IcGrid3D_FVM), pointer :: ptr

  call c_f_pointer(cptr, ptr)
  vertical_level_num = get_vertical_level_num(ptr)

end function IcGrid3D_FVM_get_vertical_level_num

subroutine IcGrid3D_FVM_redistribute_verticalGrid( &
  & cptr, VMin, VMax, interval_ratio, n &
  & ) bind(C, name='IcGrid3D_FVM_redistribute_verticalGrid')

  use, intrinsic :: iso_c_binding

  use IcGrid3D_FVM_Manager, only: &
    & IcGrid3D_FVM, redistribute_verticalGrid

  use dc_types, only: DP

  implicit none
  type(c_ptr), value :: cptr
  real(DP), value :: VMin
  real(DP), value :: VMax
  integer(c_int), value :: n
  real(DP), intent(in) :: interval_ratio(n)

  type(IcGrid3D_FVM), pointer :: ptr

  call c_f_pointer(cptr, ptr)
  call redistribute_verticalGrid(ptr, VMin, VMax, interval_ratio(1:n))

end subroutine IcGrid3D_FVM_redistribute_verticalGrid
