refactor(ipm): move simple_refrig_api into app.ipm and update loader; ignore native binaries

This commit is contained in:
Repo Bot 2025-10-19 12:23:34 +02:00
parent 92e9b05393
commit c45679d1f7
4 changed files with 750 additions and 8 deletions

6
.gitignore vendored
View File

@ -51,4 +51,8 @@ htmlcov/
# Temporary files
*.tmp
*.bak
*.swp
*.swp
# Ignore platform native binaries copied into app/ipm/lib
app/ipm/lib/windows/*.dll
app/ipm/lib/linux/*.so

View File

@ -7,13 +7,21 @@ import os
from pathlib import Path
from typing import Dict, Optional, List
# Ajouter le repertoire IPM_DLL au path pour importer simple_refrig_api
_current_dir = Path(__file__).parent.parent.parent
_ipm_dll_dir = _current_dir / "IPM_DLL"
if str(_ipm_dll_dir) not in sys.path:
sys.path.insert(0, str(_ipm_dll_dir))
from simple_refrig_api import Refifc
# Prefer the packaged app.ipm module, but keep a fallback to the legacy
# IPM_DLL folder for development compatibility.
try:
from app.ipm.simple_refrig_api import Refifc, MockRefifc # type: ignore
except Exception:
# Fall back to loading from IPM_DLL directory as before. Import the
# module and pick attributes if present; older legacy wrappers may not
# define MockRefifc.
_current_dir = Path(__file__).parent.parent.parent
_ipm_dll_dir = _current_dir / "IPM_DLL"
if str(_ipm_dll_dir) not in sys.path:
sys.path.insert(0, str(_ipm_dll_dir))
import simple_refrig_api as _sr # type: ignore
Refifc = getattr(_sr, 'Refifc')
MockRefifc = getattr(_sr, 'MockRefifc', None)
class RefrigerantLibrary:

5
app/ipm/__init__.py Normal file
View File

@ -0,0 +1,5 @@
# IPM integration package
# Exposes the simple_refrig_api wrapper for the app
from . import simple_refrig_api
__all__ = ["simple_refrig_api"]

View File

@ -0,0 +1,725 @@
import os
import ctypes
import numpy as np
import pandas as pd
from ctypes import POINTER, c_double, CFUNCTYPE, c_char_p, c_void_p, Structure
# @CFUNCTYPE(None)
# def modelica_print(a):
# print(a)
# @CFUNCTYPE(None)
# def modelica_error(a):
# print(f"Modelica Error: {a}")
# util_function_ptr = ctypes.CFUNCTYPE(None)
# class ModelicaUtilsWrapper(Structure):
# _fields_ = [('print_message', POINTER(util_function_ptr)),
# ('print_error', POINTER(util_function_ptr))]
class GenRefPropertiesPipev2(Structure):
"""
struct GenRefPropertiesPipev2
{
double T;
double Ts;
double rho;
double Cp;
double mu;
double lambda;
};
"""
_fields_ = [('T', c_double),
('Ts', c_double),
('rho', c_double),
('Cp', c_double),
('mu', c_double),
('lambda', c_double)]
class SatRefPropertiesPipe(Structure):
"""
struct SatRefPropertiesPipe
{
double rhosl; //liquid specific volume
double rhosv;
double hsl;
double hsv;
double Cpsl;
double Cpsv;
double musl;
double musv;
double lambdasl;
double lambdasv;
double sigma;
};
"""
_fields_ = [('rhosl', c_double),
('rhosv', c_double),
('hsl', c_double),
('hsv', c_double),
('Cpsl', c_double),
('Cpsv', c_double),
('musl', c_double),
('musv', c_double),
('lambdasl', c_double),
('lambdasv', c_double),
('sigma', c_double)]
class GenRefProperties(Structure):
"""
struct GenRefProperties
{
double T;
double Ts;
double v;
double h;
double s;
double Cp;
double mu;
double lambda;
double CpCv;
double n_is;
double c;
double dTglide;
};
"""
_fields_ = [('T', c_double),
('Ts', c_double),
('v', c_double),
('h', c_double),
('s', c_double),
('Cp', c_double),
('mu', c_double),
('lambda', c_double),
('CpCv', c_double),
('n_is', c_double),
('c', c_double),
('dTglide', c_double)]
if os.name == 'nt':
REFIFC_LIB_NAME = "refifc"
else: # 'posix'
REFIFC_LIB_NAME = "librefifc.so"
class Refifc(object):
def __init__(self, refrig_name):
# Sauvegardez le répertoire courant pour pouvoir y revenir plus tard
self.original_directory = os.getcwd()
# Determine candidate directories for the native library. Prefer
# app/ipm/lib/<platform> if present, otherwise fall back to the
# package directory (for compatibility with older layouts).
package_dir = os.path.dirname(os.path.abspath(__file__))
platform_dir = os.path.join(package_dir, 'lib', 'windows' if os.name == 'nt' else 'linux')
dll_directory = platform_dir if os.path.isdir(platform_dir) else package_dir
# Change working directory to the chosen directory while loading
os.chdir(dll_directory)
# Try to load the native library from the chosen directory; if that
# fails, attempt to load by name (for system-installed libs) and
# otherwise raise the original exception.
try:
self.lib = ctypes.cdll.LoadLibrary(os.path.join(dll_directory, REFIFC_LIB_NAME))
except OSError:
try:
self.lib = ctypes.cdll.LoadLibrary(REFIFC_LIB_NAME)
except Exception as e:
# Restore cwd before raising
os.chdir(self.original_directory)
raise
ctypes_refrig_name = refrig_name
if os.name == 'posix':
if not ctypes_refrig_name.lower().endswith("so"):
ctypes_refrig_name = ctypes_refrig_name + ".so"
if not ctypes_refrig_name.lower().startswith("lib"):
ctypes_refrig_name = "lib" + ctypes_refrig_name
try:
ctypes.CDLL(os.path.join(dll_directory, REFIFC_LIB_NAME))
except OSError:
print(f"Refrig {refrig_name} not found, please check!")
func = self.lib.refdll_load
func.restype = POINTER(c_void_p)
func.argtypes = [c_char_p, c_void_p]
self.handle = func(c_char_p(refrig_name.encode('utf-8')), c_void_p())
# def __del__(self):
# func = self.lib.refdll_unload
# func.restype = None
# func.argtypes = [c_void_p]
# func(self.handle)
def func_0_f(self, func_name):
func = self.lib[func_name]
func.restype = c_double
func.argtypes = [c_void_p]
return func(self.handle)
def func_f_f(self, func_name, f_arg):
func = self.lib[func_name]
func.restype = c_double
func.argtypes = [c_void_p, c_double]
return func(self.handle, f_arg)
def func_f_2f(self, func_name, f_arg_1, f_arg_2):
func = self.lib[func_name]
func.restype = c_double
func.argtypes = [c_void_p, c_double, c_double]
return func(self.handle, f_arg_1, f_arg_2)
def func_f_4f(self, func_name, f_arg_1, f_arg_2, f_arg_3, f_arg_4):
func = self.lib[func_name]
func.restype = c_double
func.argtypes = [c_void_p, c_double, c_double, c_double, c_double]
return func(self.handle, f_arg_1, f_arg_2, f_arg_3, f_arg_4)
def p_begin(self):
return self.func_0_f('pbegin')
def p_end(self):
return self.func_0_f('pend')
def x_begin(self):
return self.func_0_f('qbegin')
def x_end(self):
return self.func_0_f('qend')
"""
Define the AD functions
"""
def computeDpGenValuesPipev2_px(self, p, x):
func = self.lib.computeDpGenValuesPipev2_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, POINTER(GenRefPropertiesPipev2)]
gen_prop_pipe = GenRefPropertiesPipev2()
func(self.handle, p, x, gen_prop_pipe)
res = np.ctypeslib.as_array(gen_prop_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
return res
def computeDxGenValuesPipev2_px(self, p, x):
func = self.lib.computeDxGenValuesPipev2_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, POINTER(GenRefPropertiesPipev2)]
gen_prop_pipe = GenRefPropertiesPipev2()
func(self.handle, p, x, gen_prop_pipe)
res = np.ctypeslib.as_array(gen_prop_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
return res
def computeDpSatValuesPipe_px(self, p, x):
func = self.lib.computeDpSatValuesPipe_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, POINTER(SatRefPropertiesPipe)]
sat_pro_pipe = SatRefPropertiesPipe()
func(self.handle, p, x, sat_pro_pipe)
res = np.ctypeslib.as_array(sat_pro_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
return res
def computeDxSatValuesPipe_px(self, p, x):
func = self.lib.computeDxSatValuesPipe_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, POINTER(SatRefPropertiesPipe)]
sat_pro_pipe = SatRefPropertiesPipe()
func(self.handle, p, x, sat_pro_pipe)
res = np.ctypeslib.as_array(sat_pro_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
return res
def computeGenValuesPipev2_px(self, p, x):
func = self.lib.computeGenValuesPipev2_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, POINTER(GenRefPropertiesPipev2)]
gen_prop_pipe = GenRefPropertiesPipev2()
func(self.handle, p, x, gen_prop_pipe)
res = np.ctypeslib.as_array(gen_prop_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
return res
def computeSatValuesPipe_px(self, p, x):
func = self.lib.computeSatValuesPipe_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, POINTER(SatRefPropertiesPipe)]
sat_pro_pipe = SatRefPropertiesPipe()
func(self.handle, p, x, sat_pro_pipe)
res = np.ctypeslib.as_array(sat_pro_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
return res
def computeGenDxValues_px(self, p, x):
func = self.lib.computeGenDxValues_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, POINTER(GenRefProperties)]
gen_prop_pipe = GenRefProperties()
func(self.handle, p, x, gen_prop_pipe)
res = np.ctypeslib.as_array(gen_prop_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
return res
def computeGenDpValues_px(self, p, x):
func = self.lib.computeGenDpValues_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, POINTER(GenRefProperties)]
gen_prop_pipe = GenRefProperties()
func(self.handle, p, x, gen_prop_pipe)
res = np.ctypeslib.as_array(gen_prop_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
return res
def ComputeDFGenValuesPipev2_px(self, p, x, dp, dx):
func = self.lib.ComputeDFGenValuesPipev2_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, c_double, c_double, POINTER(GenRefPropertiesPipev2)]
gen_prop_pipe = GenRefPropertiesPipev2()
func(self.handle, p, x, dp, dx, gen_prop_pipe)
res = np.ctypeslib.as_array(gen_prop_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
res['dp'] = dp
res['dx'] = dx
return res
def ComputeDFSatValuesPipe_px(self, p, x, dp, dx):
func = self.lib.ComputeDFSatValuesPipe_px
func.restype = c_void_p
func.argtypes = [c_void_p, c_double, c_double, c_double, c_double, POINTER(SatRefPropertiesPipe)]
sat_pro_pipe = SatRefPropertiesPipe()
func(self.handle, p, x, dp, dx, sat_pro_pipe)
res = np.ctypeslib.as_array(sat_pro_pipe)
res = pd.Series(res.tolist(), index=res.dtype.names)
res['p'] = p
res['x'] = x
res['dp'] = dp
res['dx'] = dx
return res
def dTglide_p(self, p):
return self.func_f_f('dTglide_p', p)
def dvxdp_px(self, p, x):
return self.func_f_2f('dvxdp_px', p, x)
def dvpdp_px(self, p, x):
return self.func_f_2f('dvpdp_px', p, x)
def T_px(self, p, x):
return self.func_f_2f('T_px', p, x)
def dCpsldx_px(self, p, x):
return self.func_f_2f('dCpsldx_px', p, x)
def dCpsldp_px(self, p, x):
return self.func_f_2f('dCpsldp_px', p, x)
def dCpdx_px(self, p, x):
return self.func_f_2f('dCpdx_px', p, x)
def dCpdp_px(self, p, x):
return self.func_f_2f('dCpdp_px', p, x)
def dssvdx_px(self, p, x):
return self.func_f_2f('dssvdx_px', p, x)
def dssvdp_px(self, p, x):
return self.func_f_2f('dssvdp_px', p, x)
def dssldx_px(self, p, x):
return self.func_f_2f('dssldx_px', p, x)
def dssldp_px(self, p, x):
return self.func_f_2f('dssldp_px', p, x)
def dhsvdx_px(self, p, x):
return self.func_f_2f('dhsvdx_px', p, x)
def dhsvdp_px(self, p, x):
return self.func_f_2f('dhsvdp_px', p, x)
def dTsdp_px(self, p, x):
return self.func_f_2f('dTsdp_px', p, x)
def dTdp_px(self, p, x):
return self.func_f_2f('dTdp_px', p, x)
def dvp_px(self, p, x, dp, dx):
return self.func_f_4f('dvp_px', p, x, dp, dx)
def dhxdx_px(self, p, x):
return self.func_f_2f('dhxdx_px', p, x)
def dhxdp_px(self, p, x):
return self.func_f_2f('dhxdp_px', p, x)
def dhx_px(self, p, x, dp, dx):
return self.func_f_4f('dhx_px', p, x, dp, dx)
def dhpdx_px(self, p, x):
return self.func_f_2f('dhpdx_px', p, x)
def dhpdp_px(self, p, x):
return self.func_f_2f('dhpdp_px', p, x)
def dhp_px(self, p, x, dp, dx):
return self.func_f_4f('dhp_px', p, x, dp, dx)
def dlambdasvdx_px(self, p, x):
return self.func_f_2f('dlambdasvdx_px', p, x)
def dlambdasvdp_px(self, p, x):
return self.func_f_2f('dlambdasvdp_px', p, x)
def dlambdasldx_px(self, p, x):
return self.func_f_2f('dlambdasldx_px', p, x)
def dlambdasldp_px(self, p, x):
return self.func_f_2f('dlambdasldp_px', p, x)
def dlambdadx_px(self, p, x):
return self.func_f_2f('dlambdadx_px', p, x)
def dlambdadp_px(self, p, x):
return self.func_f_2f('dlambdadp_px', p, x)
def dmusvdx_px(self, p, x):
return self.func_f_2f('dmusvdx_px', p, x)
def dmusvdp_px(self, p, x):
return self.func_f_2f('dmusvdp_px', p, x)
def dmusldx_px(self, p, x):
return self.func_f_2f('dmusldx_px', p, x)
def dmusldp_px(self, p, x):
return self.func_f_2f('dmusldp_px', p, x)
def dsdx_px(self, p, x):
return self.func_f_2f('dsdx_px', p, x)
def dsdp_px(self, p, x):
return self.func_f_2f('dsdp_px', p, x)
def dhsldx_px(self, p, x):
return self.func_f_2f('dhsldx_px', p, x)
def dhsldp_px(self, p, x):
return self.func_f_2f('dhsldp_px', p, x)
def hx_px(self, p, x):
return self.func_f_2f('hx_px', p, x)
def hp_px(self, p, x):
return self.func_f_2f('hp_px', p, x)
def dhdx_px(self, p, x):
return self.func_f_2f('dhdx_px', p, x)
def dhdp_px(self, p, x):
return self.func_f_2f('dhdp_px', p, x)
def vx_px(self, p, x):
return self.func_f_2f('vx_px', p, x)
def vp_px(self, p, x):
return self.func_f_2f('vp_px', p, x)
def drhosvdx_px(self, p, x):
return self.func_f_2f('drhosvdx_px', p, x)
def drhosvdp_px(self, p, x):
return self.func_f_2f('drhosvdp_px', p, x)
def drhosldx_px(self, p, x):
return self.func_f_2f('drhosldx_px', p, x)
def drhosldp_px(self, p, x):
return self.func_f_2f('drhosldp_px', p, x)
def drhodh_px(self, p, x):
return self.func_f_2f('drhodh_px', p, x)
def drhodp_px(self, p, x):
return self.func_f_2f('drhodp_px', p, x)
def dTs_px(self, p, x, dp, dx):
return self.func_f_4f('dTs_px', p, x, dp, dx)
def dT_px(self, p, x, dp, dx):
return self.func_f_4f('dT_px', p, x, dp, dx)
def dc_ph(self, p, h, dp, dh):
return self.func_f_4f('dc_ph', p, h, dp, dh)
def dlambda_ph(self, p, h, dp, dh):
return self.func_f_4f('dlambda_ph', p, h, dp, dh)
def dmu_ph(self, p, h, dp, dh):
return self.func_f_4f('dmu_ph', p, h, dp, dh)
def dCpCv_ph(self, p, h, dp, dh):
return self.func_f_4f('dCpCv_ph', p, h, dp, dh)
def dh_ps(self, p, s, dp, ds):
return self.func_f_4f('dh_ps', p, s, dp, ds)
def dh_pT(self, p, T, dp, dT):
return self.func_f_4f('dh_pT', p, T, dp, dT)
def drhodh_ph(self, p, h):
return self.func_f_2f('drhodh_ph', p, h)
def drhodp_ph(self, p, h):
return self.func_f_2f('drhodp_ph', p, h)
def drho_ph(self, p, h, dp, dh):
return self.func_f_4f('drho_ph', p, h, dp, dh)
def h_pT(self, p, T):
return self.func_f_2f('h_pT', p, T)
def x_ph(self, p, h):
return self.func_f_2f('x_ph', p, h)
def c_ph(self, p, h):
return self.func_f_2f('c_ph', p, h)
def lambda_ph(self, p, h):
return self.func_f_2f('lambda_ph', p, h)
def mu_ph(self, p, h):
return self.func_f_2f('mu_ph', p, h)
def CpCv_ph(self, p, h):
return self.func_f_2f('CpCv_ph', p, h)
def Cp_ph(self, p, h):
return self.func_f_2f('Cp_ph', p, h)
def s_ph(self, p, h):
return self.func_f_2f('s_ph', p, h)
def rho_ph(self, p, h):
return self.func_f_2f('rho_ph', p, h)
def Ts_ph(self, p, h):
return self.func_f_2f('Ts_ph', p, h)
def T_ph(self, p, h):
return self.func_f_2f('T_ph', p, h)
def dp_Tx(self, T, x, dT, dx):
return self.func_f_4f('dp_Tx', T, x, dT, dx)
def dx_ph(self, p, h, dp, dh):
return self.func_f_4f('dx_ph', p, h, dp, dh)
def dCp_ph(self, p, h, dp, dh):
return self.func_f_4f('dCp_ph', p, h, dp, dh)
def dvxdx_px(self, p, x):
return self.func_f_2f('dvxdx_px', p, x)
def dvx_px(self, p, x, dp, dx):
return self.func_f_4f('dvx_px', p, x, dp, dx)
def dsigmadx_px(self, p, x):
return self.func_f_2f('dsigmadx_px', p, x)
def dsigmadp_px(self, p, x):
return self.func_f_2f('dsigmadp_px', p, x)
def dcsvdx_px(self, p, x):
return self.func_f_2f('dcsvdx_px', p, x)
def dcsvdp_px(self, p, x):
return self.func_f_2f('dcsvdp_px', p, x)
def dcsldx_px(self, p, x):
return self.func_f_2f('dcsldx_px', p, x)
def dcsldp_px(self, p, x):
return self.func_f_2f('dcsldp_px', p, x)
def dcdx_px(self, p, x):
return self.func_f_2f('dcdx_px', p, x)
def dcdp_px(self, p, x):
return self.func_f_2f('dcdp_px', p, x)
def dmudx_px(self, p, x):
return self.func_f_2f('dmudx_px', p, x)
def dmudp_px(self, p, x):
return self.func_f_2f('dmudp_px', p, x)
def dmu_px(self, p, x, dp, dx):
return self.func_f_4f('dmu_px', p, x, dp, dx)
def dCpCvdx_px(self, p, x):
return self.func_f_2f('dCpCvdx_px', p, x)
def dCpCvdp_px(self, p, x):
return self.func_f_2f('dCpCvdp_px', p, x)
def dCpsvdx_px(self, p, x):
return self.func_f_2f('dCpsvdx_px', p, x)
def dCpsvdp_px(self, p, x):
return self.func_f_2f('dCpsvdp_px', p, x)
def ds_px(self, p, x, dp, dx):
return self.func_f_4f('ds_px', p, x, dp, dx)
def dhsl_px(self, p, x, dp, dx):
return self.func_f_4f('dhsl_px', p, x, dp, dx)
def dh_px(self, p, x, dp, dx):
return self.func_f_4f('dh_px', p, x, dp, dx)
def dv_px(self, p, x, dp, dx):
return self.func_f_4f('dv_px', p, x, dp, dx)
def drhosv_px(self, p, x, dp, dx):
return self.func_f_4f('drhosv_px', p, x, dp, dx)
def drhosl_px(self, p, x, dp, dx):
return self.func_f_4f('drhosl_px', p, x, dp, dx)
def drho_px(self, p, x, dp, dx):
return self.func_f_4f('drho_px', p, x, dp, dx)
def dTsdx_px(self, p, x):
return self.func_f_2f('dTsdx_px', p, x)
def dTdx_px(self, p, x):
return self.func_f_2f('dTdx_px', p, x)
def p_Tx(self, T, x):
return self.func_f_2f('p_Tx', T, x)
def h_ps(self, p, s):
return self.func_f_2f('h_ps', p, s)
def vx_px(self, p, x):
return self.func_f_2f('vx_px', p, x)
def vp_px(self, p, x):
return self.func_f_2f('vp_px', p, x)
def hx_px(self, p, x):
return self.func_f_2f('hx_px', p, x)
def hp_px(self, p, x):
return self.func_f_2f('hp_px', p, x)
def sigma_px(self, p, x):
return self.func_f_2f('sigma_px', p, x)
def c_px(self, p, x):
return self.func_f_2f('c_px', p, x)
def lambdasv_px(self, p, x):
return self.func_f_2f('lambdasv_px', p, x)
def lambdasl_px(self, p, x):
return self.func_f_2f('lambdasl_px', p, x)
def lambda_px(self, p, x):
return self.func_f_2f('lambda_px', p, x)
def musv_px(self, p, x):
return self.func_f_2f('musv_px', p, x)
def musl_px(self, p, x):
return self.func_f_2f('musl_px', p, x)
def mu_px(self, p, x):
return self.func_f_2f('mu_px', p, x)
def CpCv_px(self, p, x):
return self.func_f_2f('CpCv_px', p, x)
def Cpsv_px(self, p, x):
return self.func_f_2f('Cpsv_px', p, x)
def Cpsl_px(self, p, x):
return self.func_f_2f('Cpsl_px', p, x)
def Cp_px(self, p, x):
return self.func_f_2f('Cp_px', p, x)
def ssv_px(self, p, x):
return self.func_f_2f('ssv_px', p, x)
def ssl_px(self, p, x):
return self.func_f_2f('ssl_px', p, x)
def s_px(self, p, x):
return self.func_f_2f('s_px', p, x)
def hsv_px(self, p, x):
return self.func_f_2f('hsv_px', p, x)
def hsl_px(self, p, x):
return self.func_f_2f('hsl_px', p, x)
def h_px(self, p, x):
return self.func_f_2f('h_px', p, x)
def v_px(self, p, x):
return self.func_f_2f('v_px', p, x)
def rhosv_px(self, p, x):
return self.func_f_2f('rhosv_px', p, x)
def rhosl_px(self, p, x):
return self.func_f_2f('rhosl_px', p, x)
def rho_px(self, p, x):
return self.func_f_2f('rho_px', p, x)
def Ts_px(self, p, x):
return self.func_f_2f('Ts_px', p, x)