"""
he3.py

3He parameter table

26 Jun 2009 Lev - Greywall superfluid 3He phase diagram
changed on 20-21 Jun 2010 by Lev

References:
[1] Greywall PRB 33 No.11, 7250 (1986)
[2] Lifshitz and Pitaevskii Stat. Phys pt 2 (vol. IX on L&L theor. phys course)
[3] Wheatley RMP 47, 415 (1975)
"""

#
# Changelog
# 19 Jul 2010: chiN added, from [3]
#


import numpy, flib

def P_AB_melt(): "melting pressure [bar] at AB line"; return 34.358
def Pc_melt(): "melting pressure [bar] at Tc line (P_A)"; return 34.338
def P_tri(): "pressure [bar] of the tri-critical point"; return 21.22
def Pc_solid(): "melting pressure [bar] at solid phase transition"; return Pc_melt() + 0.05252
def Tc_solid(): "melting temperature [mK] at solid phase transition"; return 0.931

def Tc(P):
    "return a Tc [mK] at a given pressure P [bar]"
    scalar = numpy.isscalar(P)
    if scalar:
        P = numpy.array([P])
    else:
        P = numpy.asanyarray(P)
    # the expression for Tc(P) is a polynomial in and after Eq. (5), page 7527 in Ref. 1
    T = numpy.polyval([0.53010918e-7, -0.57248644e-5, 0.25685169e-3, -0.69302185e-2, 0.13867188, 0.92938375], P)
    T[(P < 0) | (P > Pc_melt())] = numpy.nan
    if scalar:
        T = T[0]
    return T

__Pc__ = numpy.concatenate([numpy.arange(0.0, Pc_melt(), 0.1), [Pc_melt()]])
__Tc__ = Tc(__Pc__)
__T_tri__ = Tc(P_tri())

def T_tri(): "temperature [mK] of the tri-critical point"; return __T_tri__

def Pc(T):
    "return a P [bar] at which the Tc takes a given value T [mK]"
    return numpy.interp(T, __Tc__, __Pc__, left=numpy.nan, right=numpy.nan)

def T_AB(P):
    "return a T_AB [mK] at a given pressure P [bar]"
    scalar = numpy.isscalar(P)
    if scalar:
        P = numpy.array([P])
    else:
        P = numpy.asanyarray(P)
    # the expression for T_AB - T_tri(P - P_tri) is a polynomial in and after Eq. (15), page 7529 in Ref. 1
    T = numpy.polyval([0.17038992e-5, -0.61709783e-4, 0.83437032e-3, -0.53633181e-2, -0.10322623e-1, T_tri()], P - P_tri())
    T[(P < P_tri()) | (P > P_AB_melt())] = numpy.nan
    if scalar:
        T = T[0]
    return T

__P_AB__ = numpy.concatenate([numpy.arange(P_tri(), P_AB_melt(), 0.1), [P_AB_melt()]])
__T_AB__ = T_AB(__P_AB__)

def P_AB(T):
    "return a P [bar] at which the T_AB takes a given value T [mK]"
    return numpy.interp(T, __T_AB__, __P_AB__, left=numpy.nan, right=numpy.nan)

def Aphase_contour():
    """
    return a bundle (T,P) of arrays defining the outline of the A phase,
    the melting curve is considered flat
    """
    above_tri = (__Tc__ >= T_tri())    
    return (numpy.concatenate([__T_AB__[-1::-1], __Tc__[above_tri]]), numpy.concatenate([__P_AB__[-1::-1], __Pc__[above_tri]]))

def Bphase_contour():
    """
    return a bundle (T,P) of arrays defining the outline of the B phase,
    the melting curve is considered flat
    """
    below_tri = (__Tc__ <= T_tri())
    return (numpy.concatenate([__Tc__[below_tri], __T_AB__, [0, 0]]), numpy.concatenate([__Pc__[below_tri], __P_AB__, [Pc_solid(), 0]]))

# table VI, page 7532 in [1]
# column 1: Pressure [bar]
# column 2: V [cm^3/mol]
# column 3: gamma [1/K]
# column 4: m*/m
# column 5: F_1^S (Landau Fermi-liquid parameter)
__P_V_gamma_mstar_F1s__ = numpy.array([
    [0,     36.84,  2.78,   2.80,   5.39],
    [1,     35.74,  2.85,   2.93,   5.78],
    [2,     34.78,  2.92,   3.05,   6.14],
    [3,     33.95,  2.98,   3.16,   6.49],
    [4,     33.23,  3.04,   3.27,   6.82],
    [5,     32.59,  3.10,   3.38,   7.14],
    [6,     32.03,  3.16,   3.48,   7.45],
    [7,     31.54,  3.21,   3.58,   7.75],
    [8,     31.10,  3.27,   3.68,   8.03],
    [9,     30.71,  3.32,   3.77,   8.31],
    [10,    30.35,  3.37,   3.86,   8.57],
    [11,    30.02,  3.42,   3.95,   8.84],
    [12,    29.71,  3.48,   4.03,   9.09],
    [13,    29.42,  3.53,   4.12,   9.35],
    [14,    29.15,  3.58,   4.20,   9.60],
    [15,    28.89,  3.62,   4.28,   9.85],
    [16,    28.64,  3.67,   4.37,   10.10],
    [17,    28.41,  3.72,   4.45,   10.35],
    [18,    28.18,  3.77,   4.53,   10.60],
    [19,    27.96,  3.82,   4.61,   10.84],
    [20,    27.75,  3.87,   4.70,   11.09],
    [21,    27.55,  3.92,   4.78,   11.34],
    [22,    27.36,  3.97,   4.86,   11.58],
    [23,    27.18,  4.02,   4.94,   11.83],
    [24,    27.01,  4.06,   5.02,   12.07],
    [25,    26.85,  4.11,   5.10,   12.31],
    [26,    26.70,  4.16,   5.18,   12.55],
    [27,    26.56,  4.21,   5.26,   12.79],
    [28,    26.42,  4.26,   5.34,   13.03],
    [29,    26.29,  4.31,   5.42,   13.26],
    [30,    26.17,  4.36,   5.50,   13.50],
    [31,    26.04,  4.40,   5.58,   13.73],
    [32,    25.90,  4.45,   5.66,   13.97],
    [33,    25.75,  4.50,   5.74,   14.21],
    [34,    25.58,  4.54,   5.82,   14.46],
    [34.39, 25.50,  4.56,   5.85,   14.56]
    ])

def V_mol(P):
    "molar volume of liquid 3He [cm^3/mol] at a given pressure [bar]"
    return numpy.interp(P, __P_V_gamma_mstar_F1s__[:,0], __P_V_gamma_mstar_F1s__[:,1], left=numpy.nan, right=numpy.nan)

def gamma(P):
    "normal 3He heat capacity slope gamma [1/K] at a given pressure [bar]"
    return numpy.interp(P, __P_V_gamma_mstar_F1s__[:,0], __P_V_gamma_mstar_F1s__[:,2], left=numpy.nan, right=numpy.nan)

def m_star_over_m(P):
    "Fermi liquid mass enchancement m*/m for normal 3He at a given pressure [bar]"
    return numpy.interp(P, __P_V_gamma_mstar_F1s__[:,0], __P_V_gamma_mstar_F1s__[:,3], left=numpy.nan, right=numpy.nan)

def F1s(P):
    "Landau Fermi liquid parameter F_1^s at a given pressure [bar]"
    return numpy.interp(P, __P_V_gamma_mstar_F1s__[:,0], __P_V_gamma_mstar_F1s__[:,4], left=numpy.nan, right=numpy.nan)

__hbar__ = 1.05457148e-34 # Plank's constant [kg m^2/s]
__NA__ = 6.0221415e23 # Avogadro's number
__k_B__ = 1.3806503e-23 # Boltzmann's constant: [m^2 kg / (s^2 K)]

def p_Fermi(P):
    "liquid 3He Fermi momentum p_F [kg m/s] at a given pressure [bar]"
    # ref: [2] Eq. (1.1)
    return (3 * numpy.pi**2 * __hbar__**3 * __NA__ / (1e-6 * V_mol(P)))**(1./3)

def m_star(P):
    "3He quasiparticle mass [kg] at a given pressure [bar]"
    # bare 3He atom mass is 3.016 a.m.u., 1 a.m.u = 1.66e-27 kg
    return m_star_over_m(P) * 3.0160293 * 1.66053878e-27

def v_Fermi(P):
    "liquid 3He Fermi velocity v_F [m/s] at a given pressure [bar]"
    # ref: [2] Eq. (1.14)
    return p_Fermi(P) / m_star(P)

# chiN(P) from table V of [3]
__chi__ = {0: 3.81, 3: 4.88, 6: 5.67, 9: 6.38, 12: 7.09, 15: 7.75, 18: 8.38, 21: 8.92, 24: 9.42, 27: 9.91, 30: 10.42, 33: 10.94, 34.36: 11.17}

def chiN(P):
    "abs zero normal state susceptibility [3], table V"
    pp = sorted(__chi__.keys())
    return numpy.interp(P, pp, [__chi__[p] for p in pp], left=numpy.nan, right=numpy.nan) * 1e-8

def xi0(P):
    "return zero temperature coherence length [nm]"
    # xi_0 = \sqrt{\frac{7 \zeta(3)}{20}} \frac{\hbar v_F}{2\pi k_B T_c}
    return (7 * 1.2021 / 20)**0.5 * __hbar__ * v_Fermi(P) / (2*numpy.pi * __k_B__ * 1e-3*Tc(P)) * 1e9

def xi_GL(P, T, reducedT = True):
    "return Ginzburg-Landau coherence length [nm]"
    if not reducedT: T /= Tc(P)
    return xi0(P) / (1 - T)**0.5
