lib_material_nbti.f90 Source File


This file depends on

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

Files dependent on this one

sourcefile~~lib_material_nbti.f90~~AfferentGraph sourcefile~lib_material_nbti.f90 lib_material_nbti.f90 sourcefile~lib_material.f90 lib_material.f90 sourcefile~lib_material.f90->sourcefile~lib_material_nbti.f90 sourcefile~cmp_fslink_init.f90 cmp_FSlink_init.f90 sourcefile~cmp_fslink_init.f90->sourcefile~lib_material.f90 sourcefile~cmp_mesh2d_init.f90 cmp_mesh2D_init.f90 sourcefile~cmp_mesh2d_init.f90->sourcefile~lib_material.f90 sourcefile~cmp_solid_init.f90 cmp_solid_init.f90 sourcefile~cmp_solid_init.f90->sourcefile~lib_material.f90 sourcefile~cmp_sssrclink_init.f90 cmp_SSsrcLink_init.f90 sourcefile~cmp_sssrclink_init.f90->sourcefile~lib_material.f90 sourcefile~cmp_strand_init.f90 cmp_strand_init.f90 sourcefile~cmp_strand_init.f90->sourcefile~lib_material.f90 sourcefile~reims.f90 reims.f90 sourcefile~reims.f90->sourcefile~lib_material.f90 sourcefile~cmp_fslink_calc.f90 cmp_FSlink_calc.f90 sourcefile~reims.f90->sourcefile~cmp_fslink_calc.f90 sourcefile~cmp_mesh2d_calc.f90 cmp_mesh2D_calc.f90 sourcefile~reims.f90->sourcefile~cmp_mesh2d_calc.f90 sourcefile~cmp_mesh2d_flux.f90 cmp_mesh2D_flux.f90 sourcefile~reims.f90->sourcefile~cmp_mesh2d_flux.f90 sourcefile~cmp_mesh2d_hdf5_write.f90 cmp_mesh2D_hdf5_write.f90 sourcefile~reims.f90->sourcefile~cmp_mesh2d_hdf5_write.f90 sourcefile~cmp_solid_calc.f90 cmp_solid_calc.f90 sourcefile~reims.f90->sourcefile~cmp_solid_calc.f90 sourcefile~cmp_solid_flux.f90 cmp_solid_flux.f90 sourcefile~reims.f90->sourcefile~cmp_solid_flux.f90 sourcefile~cmp_sssrclink_calc.f90 cmp_SSsrcLink_calc.f90 sourcefile~reims.f90->sourcefile~cmp_sssrclink_calc.f90 sourcefile~cmp_strand_calc.f90 cmp_strand_calc.f90 sourcefile~reims.f90->sourcefile~cmp_strand_calc.f90 sourcefile~cmp_strand_flux.f90 cmp_strand_flux.f90 sourcefile~reims.f90->sourcefile~cmp_strand_flux.f90 sourcefile~cmp_fslink_calc.f90->sourcefile~cmp_fslink_init.f90 sourcefile~cmp_mesh2d_calc.f90->sourcefile~cmp_mesh2d_init.f90 sourcefile~cmp_mesh2d_flux.f90->sourcefile~cmp_mesh2d_init.f90 sourcefile~cmp_mesh2d_hdf5_write.f90->sourcefile~cmp_mesh2d_init.f90 sourcefile~cmp_solid_calc.f90->sourcefile~cmp_solid_init.f90 sourcefile~cmp_solid_flux.f90->sourcefile~cmp_solid_init.f90 sourcefile~cmp_sssrclink_calc.f90->sourcefile~cmp_sssrclink_init.f90 sourcefile~cmp_strand_calc.f90->sourcefile~cmp_strand_init.f90 sourcefile~cmp_strand_source_terms.f90 cmp_strand_source_terms.f90 sourcefile~cmp_strand_calc.f90->sourcefile~cmp_strand_source_terms.f90 sourcefile~cmp_strand_flux.f90->sourcefile~cmp_strand_init.f90 sourcefile~cmp_strand_source_terms.f90->sourcefile~cmp_strand_init.f90

Source Code

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

module lib_material_nbti_m
  use krn_global_tools_m
  use iso_c_binding
  use lib_input_m, only: input_t

  implicit none

  type nbti_cfg_t
    real(dp) :: E0,nPow,str1,str2,Bc20,Tc0_p,nu,CC0,p,q,n
  end type nbti_cfg_t
  
  contains


  subroutine material_nbti_init(cfg,density,c_pt)  
      class(input_t), target, intent(in) :: cfg
      real(dp), intent(out) :: density
      type(c_ptr), intent(out) :: c_pt

      type(nbti_cfg_t), pointer :: nbti_ptr ! fortran pointer

      density=cfg%dbl('density',6000.0_dp)

      allocate(nbti_ptr)
      nbti_ptr%E0    = cfg%dbl('E0',1.0e-5_dp)
      nbti_ptr%nPow  = cfg%int('nPow',5)      
      nbti_ptr%str1  = cfg%dbl('str1',0.00742_dp)
      nbti_ptr%str2  = cfg%dbl('str2',1.301e-9_dp)
      nbti_ptr%Bc20  = cfg%dbl('Bc20',13.72_dp)
      nbti_ptr%Tc0_p = cfg%dbl('Tc0_p',8.79_dp)
      nbti_ptr%nu    = cfg%dbl('nu',1.7_dp)      
      nbti_ptr%CC0   = cfg%dbl('CC0',8.92534e11_dp)
      nbti_ptr%p     = cfg%dbl('p',0.98_dp)
      nbti_ptr%q     = cfg%dbl('q',0.98_dp)
      nbti_ptr%n     = cfg%dbl('n',1.96_dp)

      c_pt = c_loc(nbti_ptr) ! translates fortran pointer to C pointer
  end subroutine material_nbti_init      


   subroutine get_power_law_parameters_nbti(c_pt,E0,nPow) 
      type(c_ptr), intent(in) :: c_pt
      real(dp), intent(out) :: E0
      integer, intent(out) :: nPow

      type(nbti_cfg_t), pointer :: nbti_ptr
      call c_f_pointer(c_pt,nbti_ptr)
      E0 = nbti_ptr%E0
      nPow = nbti_ptr%nPow
  end subroutine get_power_law_parameters_nbti


  function thermal_conductivity_nbti(c_pt,T,B) result(thermal_conductivity) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: T,B
      real(dp) :: thermal_conductivity
      real(dp) :: tmin,tmax,TT,a0,a1,a2,a3,a4,a5,a6
      real(dp) :: T_CUT,k_cut,slope_cut
      type(nbti_cfg_t), pointer :: nbti_ptr
      call c_f_pointer(c_pt,nbti_ptr)

      tmin=1.0d0
      tmax=1000.0d0
    
      TT=min(T,tmax)
      TT=max(TT,tmin)

      a0=6.60e-2_dp
      a1=4.56e-2_dp
      a2=3.00e-4_dp
      a3=-3.00e-6_dp
      a4=6.00e-9_dp
      a5=1.5e-11_dp
      a6=-5.0e-14_dp

      T_CUT     = 200.0_dp
      k_cut     = a0 + a1*T_CUT + a2*T_CUT**2 + a3*T_CUT**3 &
                + a4*T_CUT**4 + a5*T_CUT**5 + a6*T_CUT**6
      slope_cut = a1 + 2.0_dp*a2*T_CUT + 3.0_dp*a3*T_CUT**2 + 4.0_dp*a4*T_CUT**3 &
                + 5.0_dp*a5*T_CUT**4 + 6.0_dp*a6*T_CUT**5

      if (TT <= T_CUT) then
          thermal_conductivity=a0+a1*TT+a2*TT**2+a3*TT**3+a4*TT**4+a5*TT**5+a6*TT**6
      else
          thermal_conductivity = k_cut + slope_cut * (TT - T_CUT)
      end if
  end function thermal_conductivity_nbti  


  function heat_capacity_nbti(c_pt,T,B,TC,TCS,TC0) result(heat_capacity) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: T,B,TC,TCS,TC0
      real(dp) :: heat_capacity
      real(dp) :: cpHigh, Bc20_loc, gama, Beta, CpLow  

      type(nbti_cfg_t), pointer :: nbti_ptr
      call c_f_pointer(c_pt,nbti_ptr)

      cpHigh=400.0_dp

      Bc20_loc=14.0_dp
      gama=0.145_dp
      Beta=0.0023_dp

      if(T<Tc) then
          CpLow=(Beta+3.0_dp*gama/Tc**2)*T**3+gama*B*T/Bc20_loc
      else
          CpLow=Beta*T**3+gama*T
      endif

      heat_capacity=1.0_dp/(1.0_dp/cpHigh+1.0_dp/CpLow)          
  end function heat_capacity_nbti


  function strain_nbti(c_pt,B,I) result(strain) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: B,I
      real(dp) :: strain

      type(nbti_cfg_t), pointer :: nbti_ptr
      call c_f_pointer(c_pt,nbti_ptr)

      strain = -nbti_ptr%str1-nbti_ptr%str2*I*B
  end function strain_nbti


  function critical_temperature_nbti(c_pt,B,St) result(critical_temperature) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: B,St
      real(dp) :: critical_temperature
      real(dp) :: Blim,bb0,tt,Tc,Blow

      type(nbti_cfg_t), pointer :: nbti_ptr
      call c_f_pointer(c_pt,nbti_ptr)

      ! M.S.Lubell, Scaling formulas for critical current and critical field
      ! for commercial NbTi, IEEE Trans. Mag. ,19, (1983).      

      Blow=1.0e-3_dp
      Blim=max(abs(B),Blow)
      bb0 = Blim/nbti_ptr%Bc20

      if(bb0>0.0_dp .and. bb0<1.0_dp) then
         tt = (1.0_dp-bb0)**(1.0_dp/nbti_ptr%nu)
      else if(abs(bb0)<=1.0e-12_dp) then
         tt = 1.0_dp
      else if(bb0>1.0_dp) then
         tt = 0.0_dp
      endif
      Tc = nbti_ptr%Tc0_p * tt
      critical_temperature = Tc
  end function critical_temperature_nbti


  function critical_field_nbti(c_pt,T,St) result(critical_field) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: T,St
      real(dp) :: critical_field
      real(dp) :: Tlim,tt,bb,Tlow

      type(nbti_cfg_t), pointer :: nbti_ptr
      call c_f_pointer(c_pt,nbti_ptr)

      ! M.S.Lubell, Scaling formulas for critical current and critical field
      ! for commercial NbTi, IEEE Trans. Mag. ,19, (1983).      

      Tlow=0.0_dp
      Tlim=max(T,Tlow)
      tt = Tlim/nbti_ptr%Tc0_p

      if(tt>0.0_dp .and. tt<1.0_dp) then
        bb = 1.0_dp-tt**nbti_ptr%nu
      else if(tt<=0.0_dp) then
        bb = 1.0_dp
      else if(tt>1.0_dp) then
        bb = 0.0_dp
      endif
 
      critical_field = nbti_ptr%Bc20 * bb
  end function critical_field_nbti


  real(dp) function hNbTi(t,n)
    real(dp), intent(in) :: t,n
    real(dp) :: h

    if(t>0.0_dp .and. t<1.0_dp) then
       h = 1.0_dp-t**n
    else if(t<=0.0_dp) then
       h = 1.0_dp
    else if(t>=1.0_dp) then
       h = 0.0_dp
    endif

    hNbTi = h
    return
  end function hNbTi


  real(dp) function fpNbTi(b,p,q)
    real(dp), intent(in) :: b,p,q
    real(dp) :: fp

    if(b>0.0_dp .and. b<1.0_dp) then
       fp = b**p * (1.0_dp-b)**q
    else
       fp = 0.0_dp
    endif

    fpNbTi=fp
    return
  end function fpNbTi    


  function critical_current_density_nbti(c_pt,T,B,St,Tc0,Bc) result(critical_current_density) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: T,B,St,Tc0,Bc
      real(dp) :: critical_current_density
      real(dp) :: Blim,Tlim,tt,bb,h,fp,Blow,Tlow

      type(nbti_cfg_t), pointer :: nbti_ptr
      call c_f_pointer(c_pt,nbti_ptr)

      ! M.A. Green, Calculating the Jc, B, T Surface for Niobium Titanium
      ! Using a Reduced State Model, IEEE Trans. Mag., 25, 2, (1989).
  
      ! G. Morgan, A Comparison of Two Analytic Forms for the Jc(B,T)
      ! surface, SSC Magnet Division Notes, 310-1 (SSC-MD-218), (1989)
  
      ! L. Bottura, B. Bordini, Jc(B,T,e) Parameterization for the ITER
      ! Nb3Sn Production, IEEE Trans. Appl. Sup., 19(2), 1477-1480, 2009
              
      Blow=1.0e-3_dp
      Tlow=0.0_dp
      Blim=max(abs(B),Blow)
      Tlim=max(T,Tlow)
      tt = Tlim/nbti_ptr%Tc0_p

      if(tt>1.0_dp) then
         critical_current_density=0.0_dp
         return
      endif

      bb = Blim/Bc
      if(bb>1.0_dp) then
         critical_current_density=0.0_dp
         return
      endif

      h = hNbTi(tt,nbti_ptr%nu)
      fp = fpNbTi(bb,nbti_ptr%p,nbti_ptr%q)
      critical_current_density = nbti_ptr%CC0/Blim * h**nbti_ptr%n * fp
  end function critical_current_density_nbti
  

  function current_sharing_temperature_nbti(c_pt,B,St,Jop,Bc0,Jc0,Tc,Tc0,Bc) result(current_sharing_temperature) bind(C)
      type(c_ptr), value :: c_pt
      real(dp), value :: B,St,Jop,Bc0,Jc0,Tc,Tc0,Bc
      real(dp) :: current_sharing_temperature
      real(dp) :: T,tt,ttlow,ttup,error,tolerance,Jc
      logical :: converged

      type(nbti_cfg_t), pointer :: nbti_ptr
      call c_f_pointer(c_pt,nbti_ptr)

      tolerance=1.0e-5_dp

      if(B>=nbti_ptr%Bc20) then
        current_sharing_temperature=0.0_dp
        return
      endif

      if(Jop>=Jc0) then
        current_sharing_temperature=0.0_dp
        return
      endif

      if(Jop<=0.0_dp) then
        current_sharing_temperature = nbti_ptr%Tc0_p
        return
      endif

      ttup =1.0_dp
      ttlow=0.0_dp

      converged=.false.
      do while(.not.converged) 
        tt=0.5_dp*(ttlow+ttup)
        T  = tt * nbti_ptr%Tc0_p
        Jc = critical_current_density_nbti(c_pt,T,B,St,Tc0,Bc)

        if(Jc>Jop) then
           ttlow = tt
        elseif(Jc<=Jop) then
           ttup  = tt
        elseif(abs(Jc-Jop)<=1.0e-12_dp) then
           ttup  = tt
           ttlow = tt
        endif

        error     = abs(ttup-ttlow)
        converged = error<=tolerance
      enddo
      current_sharing_temperature = tt*nbti_ptr%Tc0_p
  end function current_sharing_temperature_nbti
    
end module lib_material_nbti_m