lib_friction_correlations.f90 Source File


This file depends on

sourcefile~~lib_friction_correlations.f90~~EfferentGraph sourcefile~lib_friction_correlations.f90 lib_friction_correlations.f90 sourcefile~krn_global_tools.f90 krn_global_tools.f90 sourcefile~lib_friction_correlations.f90->sourcefile~krn_global_tools.f90 sourcefile~lib_input.f90 lib_input.F90 sourcefile~lib_friction_correlations.f90->sourcefile~lib_input.f90 sourcefile~lib_input.f90->sourcefile~krn_global_tools.f90

Files dependent on this one

sourcefile~~lib_friction_correlations.f90~~AfferentGraph sourcefile~lib_friction_correlations.f90 lib_friction_correlations.f90 sourcefile~cmp_channel_init.f90 cmp_channel_init.f90 sourcefile~cmp_channel_init.f90->sourcefile~lib_friction_correlations.f90 sourcefile~cmp_channel_calc.f90 cmp_channel_calc.f90 sourcefile~cmp_channel_calc.f90->sourcefile~cmp_channel_init.f90 sourcefile~cmp_channel_source_terms.f90 cmp_channel_source_terms.f90 sourcefile~cmp_channel_calc.f90->sourcefile~cmp_channel_source_terms.f90 sourcefile~cmp_channel_flux.f90 cmp_channel_flux.f90 sourcefile~cmp_channel_flux.f90->sourcefile~cmp_channel_init.f90 sourcefile~cmp_channel_source_terms.f90->sourcefile~cmp_channel_init.f90 sourcefile~reims.f90 reims.f90 sourcefile~reims.f90->sourcefile~cmp_channel_calc.f90 sourcefile~reims.f90->sourcefile~cmp_channel_flux.f90

Source Code

! Copyright (c) 2020-2026 Damien Furfaro & Jacek Kosek
! SPDX-License-Identifier: LGPL-2.0-or-later

module lib_friction_correlations_m
  use krn_global_tools_m
  use iso_c_binding
  use fortran_yaml_c  
  use lib_input_m
  implicit none

  type friction_t
      character(:), allocatable :: friction_corr
      type(c_ptr) :: frict_cfg = C_NULL_PTR
      procedure(itf_1var), pointer, nopass :: frict => friction_correlation_not_implemented
      procedure(itf_1var), pointer, nopass :: frict_der => null()
  contains
      procedure :: friction     => friction_correlation
      procedure :: friction_der => friction_correlation_der  
  end type friction_t
  type(friction_t), allocatable, target :: frictions(:)     

  abstract interface
    function init_friction_ext_if(cfg_len,cfg_str,c_pt,frict_ptr) bind(C)
      import :: c_int, c_ptr, c_funptr, dp
      integer(c_int), value :: cfg_len
      character(*)    :: cfg_str 
      type(c_ptr)     :: c_pt      
      type(c_funptr)  :: frict_ptr
      logical         :: init_friction_ext_if      
    end function 
  end interface

  procedure(init_friction_ext_if), pointer :: init_friction_ext  => null()  

  type blasius_cfg_t  
     real(dp) :: alpha, beta
  end type blasius_cfg_t  

  type katheder_cfg_t
     real(dp) :: alpha, beta, VoidFr, Re_min
  end type katheder_cfg_t
  
  type central_spiral_cfg_t  
     real(dp) :: alpha, beta
  end type central_spiral_cfg_t  
            
  contains

    subroutine load_frictions(cfgs)
        class(input_t), intent(in) :: cfgs(:)
        
        character(20)  :: names(3) = ['blasius','katheder','central_spiral']
        integer        :: i
        type(c_funptr) :: init_friction_ext_ptr

        do i = 1, size(lib_handles)     
            init_friction_ext_ptr = GetProcAddress(lib_handles(i), 'init_friction_ext' // c_null_char)
            if (c_associated(init_friction_ext_ptr)) then
                call c_f_procpointer(init_friction_ext_ptr, init_friction_ext)
                exit
            endif
        enddo

        allocate(frictions(size(cfgs) + size(names)))
        do i = 1, size(cfgs)
            call set_friction_correlation(frictions(i), cfgs(i), '')
        enddo 
        do i = 1, size(names)
            call set_friction_correlation(frictions(size(cfgs)+i), empty_cfg(), names(i))
        enddo 
    end subroutine load_frictions


    subroutine set_friction_correlation(fct, cfg, built_in_name)
        type(friction_t), intent(inout) :: fct
        class(input_t),   intent(in)    :: cfg
        character(*),     intent(in)    :: built_in_name
        
        type(c_funptr) :: frict_ptr
        integer  :: i

        character(:), allocatable :: cfg_str
        type(str_ptr), allocatable :: keys(:)
        type(c_ptr) :: c_cfg
        c_cfg = C_NULL_PTR

        fct%friction_corr = cfg%str('friction',trim(built_in_name))
        select case (cfg%str('base',fct%friction_corr))
        case('blasius')
            call friction_factor_blasius_init(cfg, c_cfg)
            fct%frict_cfg      =  c_cfg
            fct%frict          => friction_factor_blasius
            fct%frict_der      => friction_factor_blasius_der
        case('katheder')
            call friction_factor_katheder_init(cfg, c_cfg)
            fct%frict_cfg      =  c_cfg
            fct%frict          => friction_factor_katheder
            fct%frict_der      => friction_factor_katheder_der
        case('central_spiral')
            call friction_factor_central_spiral_init(cfg, c_cfg)
            fct%frict_cfg      =  c_cfg
            fct%frict          => friction_factor_central_spiral
            fct%frict_der      => friction_factor_central_spiral_der
        end select

        if(.not. associated(init_friction_ext)) return

        ! serialization
        keys = cfg%keys1d()
        cfg_str = ''
        do i = 1, size(keys)
            cfg_str =  cfg_str // keys(i)%p // c_null_char // cfg%str(keys(i)%p) // c_null_char
        end do

        frict_ptr = C_NULL_FUNPTR
        if(.not. init_friction_ext(len(cfg_str), cfg_str, c_cfg, frict_ptr)) return  

        if(c_associated(frict_ptr)) then
            call c_f_procpointer(frict_ptr, fct%frict)
            fct%frict_cfg = c_cfg
        endif        
    end subroutine set_friction_correlation


   subroutine friction_init(me,cfg)
        class(friction_t), pointer, intent(inout) :: me
        class(input_t), target, intent(in) :: cfg
    
        integer :: i
        character(:), allocatable :: fct   
        
        fct=cfg%str('friction')
        do i=1,size(frictions)
            if(fct==frictions(i)%friction_corr) me => frictions(i)
        enddo
        if(.NOT.associated(me)) error stop fct//'friction does not exist'
   end subroutine friction_init   


  subroutine friction_factor_blasius_init(cfg,c_pt)  
      class(input_t), target, intent(in) :: cfg
      type(c_ptr), intent(out) :: c_pt
      type(blasius_cfg_t), pointer :: blasius_ptr ! fortran pointer

      allocate(blasius_ptr)
      blasius_ptr%alpha = cfg%dbl('alpha',0.079_dp)      
      blasius_ptr%beta  = cfg%dbl('beta',0.250_dp)     

      c_pt = c_loc(blasius_ptr) ! translates fortran pointer to C pointer
  end subroutine friction_factor_blasius_init      

   
  function friction_factor_blasius(c_pt,Re) result(friction) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: Re
      real(dp) :: friction  
      real(dp) :: Remin
      type(blasius_cfg_t), pointer :: blasius_ptr
      call c_f_pointer(c_pt,blasius_ptr)      
  
      Remin=10.0_dp  
      if(Re>Remin) then
          friction=blasius_ptr%alpha*(Re**(-blasius_ptr%beta))
      else
          friction=blasius_ptr%alpha*(Remin**(-blasius_ptr%beta))
      endif
  end function friction_factor_blasius   
  
  
  function friction_factor_blasius_der(c_pt,Re) result(friction_der) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: Re
      real(dp) :: friction_der
      real(dp) :: Remin
      type(blasius_cfg_t), pointer :: blasius_ptr
      call c_f_pointer(c_pt,blasius_ptr)      
  
      Remin=10.0_dp  
      if(Re>Remin) then
          friction_der=-blasius_ptr%alpha*blasius_ptr%beta*(Re**(-blasius_ptr%beta-1.0_dp))
      else
          friction_der=0.0_dp
      endif      
  end function friction_factor_blasius_der     


  subroutine friction_factor_katheder_init(cfg,c_pt)  
      class(input_t), target, intent(in) :: cfg
      type(c_ptr), intent(out) :: c_pt
      type(katheder_cfg_t), pointer :: katheder_ptr ! fortran pointer

      allocate(katheder_ptr)
      katheder_ptr%alpha  = cfg%dbl('alpha',0.0231_dp)
      katheder_ptr%beta   = cfg%dbl('beta',0.7953_dp)
      katheder_ptr%VoidFr = cfg%dbl('VoidFr',0.297_dp)
      katheder_ptr%Re_min = cfg%dbl('Re_min',1000.0_dp)

      c_pt = c_loc(katheder_ptr) ! translates fortran pointer to C pointer
  end subroutine friction_factor_katheder_init 


  function friction_factor_katheder(c_pt,Re) result(friction) bind(C)
    type(c_ptr), value :: c_pt  
    real(dp), value :: Re
    real(dp) :: friction
    type(katheder_cfg_t), pointer :: katheder_ptr
    call c_f_pointer(c_pt,katheder_ptr)     

    if(Re > katheder_ptr%Re_min) then
      friction=0.25_dp*(19.5_dp/(Re**katheder_ptr%beta)+katheder_ptr%alpha)/(katheder_ptr%VoidFr**0.742_dp)
    else
      friction=0.0_dp
    endif
  end function friction_factor_katheder


  function friction_factor_katheder_der(c_pt,Re) result(friction_der) bind(C)
    type(c_ptr), value :: c_pt
    real(dp), value :: Re
    real(dp) :: friction_der
    type(katheder_cfg_t), pointer :: katheder_ptr
    call c_f_pointer(c_pt,katheder_ptr)

    if(Re > katheder_ptr%Re_min) then
      friction_der=-0.25_dp*19.5_dp*katheder_ptr%beta*(Re**(-katheder_ptr%beta-1.0_dp))/(katheder_ptr%VoidFr**0.742_dp)
    else
      friction_der=0.0_dp
    endif
  end function friction_factor_katheder_der 


  subroutine friction_factor_central_spiral_init(cfg,c_pt)  
      class(input_t), target, intent(in) :: cfg
      type(c_ptr), intent(out) :: c_pt
      type(central_spiral_cfg_t), pointer :: central_spiral_ptr ! fortran pointer

      allocate(central_spiral_ptr)
      central_spiral_ptr%alpha  = cfg%dbl('alpha',0.36_dp)      
      central_spiral_ptr%beta   = cfg%dbl('beta',0.038_dp)

      c_pt = c_loc(central_spiral_ptr) ! translates fortran pointer to C pointer
  end subroutine friction_factor_central_spiral_init     


  function friction_factor_central_spiral(c_pt,Re) result(friction) bind(C)
    type(c_ptr), value :: c_pt
    real(dp), value :: Re
    real(dp) :: friction
    type(central_spiral_cfg_t), pointer :: central_spiral_ptr
    call c_f_pointer(c_pt,central_spiral_ptr)    

    if(Re>0.0_dp) then
      friction=0.25_dp*central_spiral_ptr%alpha/Re**central_spiral_ptr%beta
    else
      friction=0.0_dp
    endif
  end function friction_factor_central_spiral      


  function friction_factor_central_spiral_der(c_pt,Re) result(friction_der) bind(C)
    type(c_ptr), value :: c_pt
    real(dp), value :: Re
    real(dp) :: friction_der
    type(central_spiral_cfg_t), pointer :: central_spiral_ptr
    call c_f_pointer(c_pt,central_spiral_ptr)    

    if(Re>0.0_dp) then
      friction_der=-0.25_dp*central_spiral_ptr%alpha*central_spiral_ptr%beta*(Re**(-central_spiral_ptr%beta-1.0_dp))
    else
      friction_der=0.0_dp
    endif    
  end function friction_factor_central_spiral_der      
 

  ! Member functions implementations --- calls to lower-level function pointers  
  function friction_correlation(me,Re)
    class(friction_t),  intent(inout) :: me
    real(dp), intent(in) :: Re
    real(dp) :: friction_correlation

    friction_correlation=me%frict(me%frict_cfg,Re)
  end function friction_correlation


  function friction_correlation_der(me,Re)
    class(friction_t),  intent(inout) :: me
    real(dp), intent(in) :: Re
    real(dp) :: friction_correlation_der
    real(dp) :: eps
    if(associated(me%frict_der)) then
        friction_correlation_der=me%frict_der(me%frict_cfg,Re)
    else
        eps=2.0e-1_dp
        friction_correlation_der=(me%frict(me%frict_cfg,Re+0.5_dp*eps) &
                                 -me%frict(me%frict_cfg,Re-0.5_dp*eps))/eps
    endif
  end function friction_correlation_der

  
  ! Dummy function - not implemented, to handle errors when friction does not set or override them
  function friction_correlation_not_implemented(c_pt,Re) result(ret_val) bind(C)
    type(c_ptr), value :: c_pt
    real(dp), value :: Re
    real(dp) :: ret_val
    ret_val=0.0_dp
    if(.false.) print*,c_associated(c_pt),Re
    print*,'friction_correlation - not implemented'
    stop
  end function friction_correlation_not_implemented   


  function friction_factor_laminar(Re)  
    real(dp), intent(in) :: Re
    real(dp) :: friction_factor_laminar
    real(dp) :: a,Remin

    a=16.0_dp
    Remin=1.0e-8_dp

    if(Re>Remin) then
      friction_factor_laminar=a/Re
    else
      friction_factor_laminar=a/Remin
    endif
  end function friction_factor_laminar
  

  function der_friction_factor_laminar(Re)
    real(dp), intent(in) :: Re
    real(dp) :: der_friction_factor_laminar
    real(dp) :: a,Remin

    a=16.0_dp
    Remin=1.0e-8_dp

    if(Re>Remin) then
      der_friction_factor_laminar=-a/(Re**2)
    else
      der_friction_factor_laminar=0.0_dp
    endif
  end function der_friction_factor_laminar    
    
end module lib_friction_correlations_m