!# This source file is part of code Pégase.3.0.1 (2019-02-21).
!# Copyright: Michel Fioc (Michel.Fioc@iap.fr), Sorbonne université, 
!# Institut d'astrophysique de Paris/CNRS, France.
!# 
!# Pégase.3.0.1 is governed by the CeCILL license under French law and abides 
!# by the rules of distribution of free software. You can use, modify and/or 
!# redistribute this software under the terms of the CeCILL license as circulated 
!# by CEA, CNRS and INRIA at "http://www.cecill.info". The text of this license
!# is also available in French and in English in directory "doc_dir/" of this
!# code.
!# 
!# As a counterpart to the access to the source code and to the rights to copy,
!# modify and redistribute it granted by the license, users are provided only
!# with a limited warranty, and the software's author, the holder of the
!# economic rights, and the successive licensors have only limited
!# liability. 
!# 
!# The fact that you are presently reading this means that you have had
!# knowledge of the CeCILL license and that you accept its terms.
!#====================================================================== 

module mod_stel_lib

  use mod_types

  implicit none
  private
  type :: struct_stel_lib
     integer :: dim_spec
     integer :: dim_lambda
     real(CDR), dimension(:,:), pointer :: lum_star => null()
     real(DPR), dimension(:), pointer :: HI_rate_star => null(), &
          HeI_rate_star => null(), &
          HeII_rate_star => null(), &
          T => null(), &
          g => null(), &
          HI_power_star => null(), &
          HeI_power_star => null(), &
          HeII_power_star => null()
  end type struct_stel_lib
  public :: SSP_read_stel_lib, spectra_read_stel_lib1, &
       spectra_read_stel_lib2, interp_stel_lib, struct_stel_lib

contains

!#======================================================================
  
  subroutine SSP_read_stel_lib(dim_low_T, dim_high_T, &
       stel_lib, &
       M_over_H_SL, dim_SL, T_SL_max, T_SL_min, dim_spec, stel_lib_set)

    use mod_types
    use mod_directories, only : stel_lib_dir
    use mod_file_access, only : open_file, close_file, skip_lines, path_file

    implicit none
    integer, intent(out) :: dim_SL, dim_low_T, dim_high_T
    type(struct_stel_lib), dimension(:), pointer :: stel_lib
    integer, dimension(:), pointer :: dim_spec
    real(DPR), dimension(:), pointer :: M_over_H_SL, T_SL_max, T_SL_min
    character(len=*), intent(in) :: stel_lib_set
!#......................................................................
    integer :: unit, i_SL, i_spec
    character(std_string), dimension(:), allocatable :: stel_lib_file
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call open_file(unit, path_file(stel_lib_dir, stel_lib_set))
    read(unit,*) !# Skip file of wavelengths.
    read(unit,*) dim_low_T, dim_high_T

    dim_SL = dim_low_T+dim_high_T

    if (allocated(stel_lib_file)) deallocate(stel_lib_file)
    allocate(stel_lib_file(dim_SL))

    if (associated(dim_spec)) deallocate(dim_spec)
    allocate(dim_spec(dim_SL))

    if (associated(M_over_H_SL)) deallocate(M_over_H_SL)
    allocate(M_over_H_SL(dim_SL))

    if (associated(stel_lib)) deallocate(stel_lib)
    allocate(stel_lib(dim_SL))

    if (associated(T_SL_max)) deallocate(T_SL_max)
    allocate(T_SL_max(dim_SL))

    if (associated(T_SL_min)) deallocate(T_SL_min)
    allocate(T_SL_min(dim_SL))

    do i_SL = 1, dim_SL
       read(unit,*) stel_lib_file(i_SL)
    enddo
    call close_file(unit)

    do i_SL = 1, dim_SL
       call open_file(unit, path_file(stel_lib_dir, stel_lib_file(i_SL)))
       call skip_lines(unit, 1) !# "[M/H]".
       read(unit,*) dim_spec(i_SL), M_over_H_SL(i_SL)

       if (associated(stel_lib(i_SL) % T)) deallocate(stel_lib(i_SL) % T)
       allocate(stel_lib(i_SL) % T(0:dim_spec(i_SL)))
       if (associated(stel_lib(i_SL) % g)) deallocate(stel_lib(i_SL) % g)
       allocate(stel_lib(i_SL) % g(0:dim_spec(i_SL)))
       if (associated(stel_lib(i_SL) % HI_rate_star)) deallocate(stel_lib(i_SL) % HI_rate_star)
       allocate(stel_lib(i_SL) % HI_rate_star(0:dim_spec(i_SL)))
       if (associated(stel_lib(i_SL) % HeI_rate_star)) deallocate(stel_lib(i_SL) % HeI_rate_star)
       allocate(stel_lib(i_SL) % HeI_rate_star(0:dim_spec(i_SL)))
       if (associated(stel_lib(i_SL) % HeII_rate_star)) deallocate(stel_lib(i_SL) % HeII_rate_star)
       allocate(stel_lib(i_SL) % HeII_rate_star(0:dim_spec(i_SL)))
       if (associated(stel_lib(i_SL) % HI_power_star)) deallocate(stel_lib(i_SL) % HI_power_star)
       allocate(stel_lib(i_SL) % HI_power_star(0:dim_spec(i_SL)))
       if (associated(stel_lib(i_SL) % HeI_power_star)) deallocate(stel_lib(i_SL) % HeI_power_star)
       allocate(stel_lib(i_SL) % HeI_power_star(0:dim_spec(i_SL)))
       if (associated(stel_lib(i_SL) % HeII_power_star)) deallocate(stel_lib(i_SL) % HeII_power_star)
       allocate(stel_lib(i_SL) % HeII_power_star(0:dim_spec(i_SL)))
       
       do i_spec = 1, dim_spec(i_SL)
          read(unit,*) stel_lib(i_SL) % T(i_spec), &
               stel_lib(i_SL) % g(i_spec), &
               stel_lib(i_SL) % HI_rate_star(i_spec), &
               stel_lib(i_SL) % HeI_rate_star(i_spec), &
               stel_lib(i_SL) % HeII_rate_star(i_spec), &
               stel_lib(i_SL) % HI_power_star(i_spec), &
               stel_lib(i_SL) % HeI_power_star(i_spec), &
               stel_lib(i_SL) % HeII_power_star(i_spec)
       enddo
       call close_file(unit)
       T_SL_max(i_SL) = maxval(stel_lib(i_SL) % T(1:dim_spec(i_SL)))
       T_SL_min(i_SL) = minval(stel_lib(i_SL) % T(1:dim_spec(i_SL)))
       stel_lib(i_SL) % T(0) = 0
       stel_lib(i_SL) % g(0) = 0
       stel_lib(i_SL) % HI_rate_star(0) = 0
       stel_lib(i_SL) % HeI_rate_star(0) = 0
       stel_lib(i_SL) % HeII_rate_star(0) = 0
       stel_lib(i_SL) % HI_power_star(0) = 0
       stel_lib(i_SL) % HeI_power_star(0) = 0
       stel_lib(i_SL) % HeII_power_star(0) = 0
    enddo

  end subroutine SSP_read_stel_lib

!#======================================================================

  subroutine spectra_read_stel_lib1(dim_SL, dim_spec, dim_lambda, lambda, stel_lib_file, &
       stel_lib_set)

    use mod_types
    use mod_directories, only : stel_lib_dir
    use mod_file_access, only : open_file, close_file, skip_lines, path_file

    implicit none
    integer, intent(out) :: dim_SL, dim_lambda
    integer, dimension(:), pointer :: dim_spec
    real(CDR), dimension(:), pointer :: lambda
    character(len=*), dimension(:), pointer :: stel_lib_file
    character(len=*), intent(in) :: stel_lib_set
!#......................................................................
    integer :: unit, i_SL, unit2
    character(len=std_string) :: SL_wavelengths_file
    integer :: dim_low_T, dim_high_T
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call open_file(unit, path_file(stel_lib_dir, stel_lib_set))
    read(unit, *) SL_wavelengths_file

    call open_file(unit2, path_file(stel_lib_dir, SL_wavelengths_file))
    read(unit2,*) dim_lambda
    if (associated(lambda)) deallocate(lambda)
    allocate(lambda(dim_lambda))
    read(unit2,*) lambda(1:dim_lambda)
    call close_file(unit2)

    read(unit,*) dim_low_T, dim_high_T
    dim_SL = dim_low_T+dim_high_T

    if (associated(stel_lib_file)) deallocate(stel_lib_file)
    allocate(stel_lib_file(dim_SL))
    if (associated(dim_spec)) deallocate(dim_spec)
    allocate(dim_spec(dim_SL))

    do i_SL = 1, dim_SL
       read(unit,*) stel_lib_file(i_SL)
    enddo
    call close_file(unit)

    do i_SL = 1, dim_SL
       call open_file(unit, path_file(stel_lib_dir, stel_lib_file(i_SL)))
       call skip_lines(unit, 1)
       read(unit,*) dim_spec(i_SL)
       call close_file(unit)
    enddo

  end subroutine spectra_read_stel_lib1

!#======================================================================

  subroutine spectra_read_stel_lib2(stel_lib_file, dim_lambda, &
       lum_star)

    use mod_types
    use mod_file_access, only : open_file, close_file, skip_lines, path_file
    use mod_directories, only : stel_lib_dir

    implicit none
    character(len=*), intent(in) :: stel_lib_file
    integer, intent(in) :: dim_lambda
    real(CDR), dimension(:,:), pointer :: lum_star
!#......................................................................
    integer :: unit, i_spec, dim_spec
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    call open_file(unit, path_file(stel_lib_dir, stel_lib_file))
    call skip_lines(unit, 1)
    read(unit,*) dim_spec
    call skip_lines(unit, dim_spec)
    if (associated(lum_star)) deallocate(lum_star)
    allocate(lum_star(dim_lambda, dim_spec))
    do i_spec = 1, dim_spec
       read(unit,*) lum_star(1:dim_lambda, i_spec)
    enddo
    call close_file(unit)

  end subroutine spectra_read_stel_lib2

!#======================================================================

  subroutine interp_stel_lib(T, g, i1, i2, i3, i4, alpha1, alpha2, alpha3, &
       alpha4, i_SL12, i_SL34, dim_spec, stel_lib)

    use mod_types
    use mod_SSPs_constants, only : d_T_max_SL, kappa_SL

    implicit none
    integer, intent(in) :: i_SL12, i_SL34
    real(DPR), intent(in) :: T, g
    integer, intent(out) :: i1, i2, i3, i4
    real(DPR), intent(out) :: alpha1, alpha2, alpha3, alpha4
    integer, dimension(:), intent(in) :: dim_spec
    type(struct_stel_lib), dimension(:), intent(in) :: stel_lib
!#......................................................................
    integer :: i
    real(DPR) :: alpha, beta, gamma, g_prim, g_sec, g1, g2, g3, g4
    real(DPR) :: T1, T2, T3, T4
    real(DPR) :: delta1, delta2, delta3, delta4
    real(DPR) :: det0, det1, det2, det3, det4
    real(DPR), dimension(9) :: mat0, mat1, mat2, mat3, mat4

!# Parameter used to test if temperatures are equal:
    real(DPR), parameter :: eps_T = 1.e-6_DPR !# (Probably useless, but avoids warnings about \
!# equality tests of reals from quibbling compilers.)
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    i1 = 0
    i2 = 0
    i3 = 0
    i4 = 0

    delta1 = huge(1._DPR)
    delta2 = delta1
    delta3 = delta1
    delta4 = delta1

!# i1 = index of the star with temperature > T and gravity > g.
!# Among all such stars, one chooses the one minimizing
!# abs(Delta T)+kappa_SL*abs(Delta g).
!# If no star with temperature > T and gravity > g exists, i1 = 0.
!#
!# i2 = index of the star with temperature > T and gravity < g.
!#
!# i3 = index of the star with temperature < T and gravity > g.
!#
!# i4 = index of the star with temperature < T and gravity < g.

!#  g
!#
!# /|\
!#  | i3  |
!#  |     |  i1
!#  | ----x------
!#  |     |     i2
!#  |  i4 |
!#  |__________\ T
!#             /

    do i = 1, dim_spec(i_SL12)
       if (stel_lib(i_SL12) % T(i) >= T) then
          if (stel_lib(i_SL12) % g(i) >= g) then
             if ((stel_lib(i_SL12) % T(i)-T) + kappa_SL*(stel_lib(i_SL12) % g(i)-g) < &
                  delta1) then
                i1 = i
                delta1 = (stel_lib(i_SL12) % T(i)-T) + kappa_SL*(stel_lib(i_SL12) % g(i)-g)
             endif
          else
             if ((stel_lib(i_SL12) % T(i)-T) + kappa_SL*(g-stel_lib(i_SL12) % g(i)) < &
                  delta2) then
                i2 = i
                delta2 = (stel_lib(i_SL12) % T(i)-T) + kappa_SL*(g-stel_lib(i_SL12) % g(i))
             endif
          end if
       endif
    enddo

    do i = 1, dim_spec(i_SL34)
       if (stel_lib(i_SL34) % T(i) < T) then
          if (stel_lib(i_SL34) % g(i) >= g) then
             if ((T-stel_lib(i_SL34) % T(i)) + kappa_SL*(stel_lib(i_SL34) % g(i)-g) < &
                  delta3) then
                i3 = i
                delta3 = (T-stel_lib(i_SL34) % T(i)) + kappa_SL*(stel_lib(i_SL34) % g(i)-g)
             endif
          else
             if ((T-stel_lib(i_SL34) % T(i)) + kappa_SL*(g-stel_lib(i_SL34) % g(i)) < &
                  delta4) then
                i4 = i
                delta4 = (T-stel_lib(i_SL34) % T(i)) + kappa_SL*(g-stel_lib(i_SL34) % g(i))
             endif
          end if
       end if
    end do

    T1 = stel_lib(i_SL12) % T(i1)
    g1 = stel_lib(i_SL12) % g(i1)
    T2 = stel_lib(i_SL12) % T(i2)
    g2 = stel_lib(i_SL12) % g(i2)
    T3 = stel_lib(i_SL34) % T(i3)
    g3 = stel_lib(i_SL34) % g(i3)
    T4 = stel_lib(i_SL34) % T(i4)
    g4 = stel_lib(i_SL34) % g(i4)
    alpha1 = 0
    alpha2 = 0
    alpha3 = 0
    alpha4 = 0

!# If T2 (resp. T1) is too far from T compared to T1 (resp. T2), i2 (resp. i1)
!# is not used. The same for i3 and i4.

    if (i1 /= 0 .and. i2 /= 0) then
       if (T1 < T2-d_T_max_SL) then
          i2 = 0
       else if (T2 < T1-d_T_max_SL) then
          i1 = 0
       endif
    endif

    if (i3 /= 0 .and. i4 /= 0) then
       if (T3 > T4+d_T_max_SL) then
          i4 = 0
       else if (T4 > T3+d_T_max_SL) then
          i3 = 0
       endif
    endif

!# Interpolation in the (T, g) plane between the used points (at least 1, at most 4).
!# Code "0110" means that i1 = i4 = 0, i2 /= 0 and i3 /= 0.
!# Note: preference is always given to the temperature over the gravity when needed.

    if (i1 == 0) then
       if (i2 == 0) then
          if (i3 == 0) then
             if (i4 == 0) then !# 0000
                write(*, "(a)") "Error: i1 = i2 = i3 = i4 = 0. Stopped."
                stop
             else !# 0001
                alpha1 = 0
                alpha2 = 0
                alpha3 = 0
                alpha4 = 1
             endif
          else if (i4 == 0) then !# 0010
             alpha1 = 0
             alpha2 = 0
             alpha3 = 1
             alpha4 = 0
          else !# 0011
             alpha1 = 0
             alpha2 = 0
             if (abs(T3-T4) < eps_T) then
                if (g3 == g4) then
                   alpha3 = 0.5_DPR
                else
                   alpha3 = (g-g4)/(g3-g4)
                endif
                alpha4 = 1-alpha3
             else
                if (T3 > T4) then
                   alpha3 = 1
                   alpha4 = 0 ; i4 = 0
                else
                   alpha3 = 0 ; i3 = 0
                   alpha4 = 1
                end if
             end if
          endif
       else if (i3 == 0) then
          if (i4 == 0) then !# 0100
             alpha1 = 0
             alpha2 = 1
             alpha3 = 0
             alpha4 = 0
          else !# 0101
             alpha1 = 0
             if (T2 == T4) then
                alpha2 = 0.5_DPR
             else
                alpha2 = (T-T4)/(T2-T4)
             endif
             alpha3 = 0
             alpha4 = 1-alpha2
          endif
       else if (i4 == 0) then !# 0110
          alpha1 = 0
          if (T2 == T3) then
             alpha2 = 0.5_DPR
          else
             alpha2 = (T-T3)/(T2-T3)
          endif
          alpha3 = 1-alpha2
          alpha4 = 0
       else !# 0111

!# Assume that (T, g) is within the triangle formed by the three points.

          mat0 = (/ &
               T2, T3, T4, &
               g2, g3, g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat2 = (/ &
               T,  T3, T4, &
               g,  g3, g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat3 = (/ &
               T2, T,  T4, &
               g2, g,  g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat4 = (/ &
               T2, T3, T, &
               g2, g3, g, &
               1._DPR, 1._DPR, 1._DPR/)
          det0 = det3x3(mat0)
          det2 = det3x3(mat2)
          det3 = det3x3(mat3)
          det4 = det3x3(mat4)
          alpha1 = 0
          alpha2 = det2/det0
          alpha3 = det3/det0
          alpha4 = det4/det0

!# If (T, g) is outside the triangle formed by the three used points,
!# use only two points.

          if (alpha2 < 0 .or. alpha2 > 1 .or. alpha3 < 0 .or. &
               alpha3 > 1 .or. alpha4 < 0 .or. alpha4 > 1) then
             alpha1 = 0
             if (T2 == T3) then
                alpha2 = 0.5_DPR
             else
                alpha2 = (T-T3)/(T2-T3)
             endif
             alpha3 = 1-alpha2
             alpha4 = 0; i4 = 0
          endif
       endif
    else if (i2 == 0) then
       if (i3 == 0) then
          if (i4 == 0) then !# 1000
             alpha1 = 1
             alpha2 = 0
             alpha3 = 0
             alpha4 = 0
          else !# 1001
             if (T1 == T4) then
                alpha1 = 0.5_DPR
             else
                alpha1 = (T-T4)/(T1-T4)
             endif
             alpha2 = 0
             alpha3 = 0
             alpha4 = 1-alpha1
          endif
       else if (i4 == 0) then !# 1010
          if (T1 == T3) then
             alpha1 = 0.5_DPR
          else
             alpha1 = (T-T3)/(T1-T3)
          endif
          alpha2 = 0
          alpha3 = 1-alpha1
          alpha4 = 0
       else !# 1011

!# Assume that (T, g) is within the triangle formed by the three points.

          mat0 = (/ &
               T1, T3, T4, &
               g1, g3, g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat1 = (/ &
               T,  T3, T4, &
               g,  g3, g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat3 = (/ &
               T1, T,  T4, &
               g1, g,  g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat4 = (/ &
               T1, T3, T, &
               g1, g3, g, &
               1._DPR, 1._DPR, 1._DPR/)
          det0 = det3x3(mat0)
          det1 = det3x3(mat1)
          det3 = det3x3(mat3)
          det4 = det3x3(mat4)
          alpha1 = det1/det0
          alpha2 = 0
          alpha3 = det3/det0
          alpha4 = det4/det0

!# If (T, g) is outside the triangle formed by the three used points,
!# use only two points.

          if (alpha1 < 0 .or. alpha1 > 1 .or. alpha3 < 0 .or. &
               alpha3 > 1 .or. alpha4 < 0 .or. alpha4 > 1) then
             if (T1 == T4) then
                alpha1 = 0.5_DPR
             else
                alpha1 = (T-T4)/(T1-T4)
             endif
             alpha2 = 0
             alpha3 = 0 ; i3 = 0
             alpha4 = 1-alpha1
          endif
       endif
    else if (i3 == 0) then
       if (i4 == 0) then !# 1100
          if (abs(T1-T2) < eps_T) then
             if (g1 == g2) then
                alpha1 = 0.5_DPR
             else
                alpha1 = (g-g2)/(g1-g2)
             endif
             alpha2 = 1-alpha1
          else
             if (T1 < T2) then
                alpha1 = 1
                alpha2 = 0 ; i2 = 0
             else
                alpha1 = 0 ; i1 = 0
                alpha2 = 1
             end if
          end if
          alpha3 = 0
          alpha4 = 0
       else !# 1101

!# Assume that (T, g) is within the triangle formed by the three points.

          mat0 = (/ &
               T1, T2, T4, &
               g1, g2, g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat1 = (/ &
               T,  T2, T4, &
               g,  g2, g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat2 = (/ &
               T1, T,  T4, &
               g1, g,  g4, &
               1._DPR, 1._DPR, 1._DPR/)
          mat4 = (/ &
               T1, T2, T, &
               g1, g2, g, &
               1._DPR, 1._DPR, 1._DPR/)
          det0 = det3x3(mat0)
          det1 = det3x3(mat1)
          det2 = det3x3(mat2)
          det4 = det3x3(mat4)
          alpha1 = det1/det0
          alpha2 = det2/det0
          alpha3 = 0
          alpha4 = det4/det0

!# If (T, g) is outside the triangle formed by the three used points,
!# use only two points.

          if (alpha1 < 0 .or. alpha1 > 1 .or. alpha2 < 0 .or. &
               alpha2 > 1 .or. alpha4 < 0 .or. alpha4 > 1) then
             if (T1 == T4) then
                alpha1 = 0.5_DPR
             else
                alpha1 = (T-T4)/(T1-T4)
             endif
             alpha2 = 0 ; i2 = 0
             alpha3 = 0
             alpha4 = 1-alpha1
          endif
       endif
    else if (i4 == 0) then !# 1110

!# Assume that (T, g) is within the triangle formed by the three points.

       mat0 = (/ &
            T1, T2, T3, &
            g1, g2, g3, &
            1._DPR, 1._DPR, 1._DPR/)
       mat1 = (/ &
            T,  T2, T3, &
            g,  g2, g3, &
            1._DPR, 1._DPR, 1._DPR/)
       mat2 = (/ &
            T1, T,  T3, &
            g1, g,  g3, &
            1._DPR, 1._DPR, 1._DPR/)
       mat3 = (/ &
            T1, T2, T, &
            g1, g2, g, &
            1._DPR, 1._DPR, 1._DPR/)
       det0 = det3x3(mat0)
       det1 = det3x3(mat1)
       det2 = det3x3(mat2)
       det3 = det3x3(mat3)
       alpha1 = det1/det0
       alpha2 = det2/det0
       alpha3 = det3/det0
       alpha4 = 0

!# If (T, g) is outside the triangle formed by the three used points,
!# use only two points.

       if (alpha1 < 0 .or. alpha1 > 1 .or. alpha2 < 0 .or. &
            alpha2 > 1 .or. alpha3 < 0 .or. alpha3 > 1) then
          alpha1 = 0 ; i1 = 0
          if (T2 == T3) then
             alpha2 = 0.5_DPR
          else
             alpha2 = (T-T3)/(T2-T3)
          endif
          alpha3 = 1-alpha2
          alpha4 = 0
       endif
    end if

!# All four points used.

    if (i3 /= 0 .and. i4 /= 0 .and. i1 /= 0 .and. i2 /= 0) then
       if (T1 /= T3) then
          alpha = (T-T3)/(T1-T3)
       else
          alpha = 0.5_DPR
       endif
       if (T2 /= T4) then
          beta = (T-T4)/(T2-T4)
       else
          beta = 0.5_DPR
       endif
       g_prim = alpha*g1+(1-alpha)*g3
       g_sec = beta*g2+(1-beta)*g4
       if (g_prim /= g_sec) then
          gamma = (g-g_sec)/(g_prim-g_sec)
       else
          gamma = 0.5_DPR
       endif
       alpha1 = alpha*gamma
       alpha2 = beta*(1-gamma)
       alpha3 = (1-alpha)*gamma
       alpha4 = (1-beta)*(1-gamma)
    end if

  end subroutine interp_stel_lib

!#======================================================================

  function det3x3(a)

    use mod_types
    implicit none
    real(DPR), dimension(9) :: a
    real(DPR) :: det3x3

    det3x3 = &
         +a(1)*(a(5)*a(9)-a(8)*a(6)) &
         -a(2)*(a(4)*a(9)-a(7)*a(6)) &
         +a(3)*(a(4)*a(8)-a(7)*a(5))

  end function det3x3

end module mod_stel_lib
