Beispiel #1
0
def test_horner():
    from fluids.numerics import horner
    assert_allclose(horner([1.0, 3.0], 2.0), 5.0)
    assert_allclose(horner([3.0], 2.0), 3.0)
    
    poly = [1.12, 432.32, 325.5342, .235532, 32.235]
    assert_allclose(horner_and_der2(poly, 3.0), (14726.109396, 13747.040732, 8553.7884))
    assert_allclose(horner_and_der3(poly, 3.0), (14726.109396, 13747.040732, 8553.7884, 2674.56))
Beispiel #2
0
def TDE_RIXExpansion(T, Bs, Cs, wavelength=589.26e-9):
    r'''Calculates the refractive index of a pure liquid at a given temperature,
    and wavelength, using the NIST TDE RIXExpansion formula [1]_.

    .. math::
        n(T, \lambda) = \sum_{i=0}^{i} B_i t^i + \sum_j C_j w^j
    
    .. math::
        t = T - 298.15
        
    .. math::
        w = WL\times 10^{9} - 589.26


    Parameters
    ----------
    T : float
        Temperature of the fluid [K]
    Bs : list[float]
        Polynomial temperature expansion coefficients, in reverse order to the
        polynomial (as needed for efficient computation with horner's method'),
        [-]
    Cs : list[float]
        Polynomial wavelength expansion coefficients, in reverse order to the
        polynomial (as needed for efficient computation with horner's method'),
        [-]
    wavelength : float
        Wavelength of fluid [meters]

    Returns
    -------
    RI : float
        Refractive index of the pure fluid, [-]

    Notes
    -----

    Examples
    --------
    >>> TDE_RIXExpansion(330.0, Bs=[-0.000125041, 1.33245], Cs=[1.20771e-7, -3.56795e-5, 0.0], wavelength=589.26e-9*.7)
    1.33854894426073

    References
    ----------
    .. [1] "ThermoData Engine (TDE103b V10.1) User’s Guide." 
       https://trc.nist.gov/TDE/Help/TDE103b/Eqns-Pure-RefractiveIndex/RIXExpansion.htm.
    '''
    t = T - 298.15
    w = (wavelength - 589.26e-9) * 1e9
    n_D = horner(Bs, t)
    if Cs is not None:
        n_D += horner(Cs, w)
    return n_D
Beispiel #3
0
    def _custom_set_poly_fit(self):
        try:
            Tmin, Tmax = self.poly_fit_Tmin, self.poly_fit_Tmax
            poly_fit_coeffs = self.poly_fit_coeffs
            v_Tmin = horner(poly_fit_coeffs, Tmin)
            for T_trans in linspace(Tmin, Tmax, 25):
                v, d1, d2 = horner_and_der2(poly_fit_coeffs, T_trans)
                Psat = exp(v)
                dPsat_dT = Psat * d1
                d2Psat_dT2 = Psat * (d1 * d1 + d2)

                A, B, C = Antoine_ABC = Antoine_coeffs_from_point(T_trans,
                                                                  Psat,
                                                                  dPsat_dT,
                                                                  d2Psat_dT2,
                                                                  base=e)
                self.poly_fit_AB = list(
                    Antoine_AB_coeffs_from_point(T_trans,
                                                 Psat,
                                                 dPsat_dT,
                                                 base=e))
                self.DIPPR101_ABC = list(
                    DIPPR101_ABC_coeffs_from_point(T_trans, Psat, dPsat_dT,
                                                   d2Psat_dT2))

                B_OK = B > 0.0  # B is negated in this implementation, so the requirement is reversed
                C_OK = -T_trans < C < 0.0
                if B_OK and C_OK:
                    self.poly_fit_Antoine = Antoine_ABC
                    break
                else:
                    continue

            # Calculate the extrapolation values
            v_Tmax = horner(poly_fit_coeffs, Tmax)
            v, d1, d2 = horner_and_der2(poly_fit_coeffs, Tmax)
            Psat = exp(v)
            dPsat_dT = Psat * d1
            d2Psat_dT2 = Psat * (d1 * d1 + d2)
            #                A, B, C = Antoine_ABC = Antoine_coeffs_from_point(T_trans, Psat, dPsat_dT, d2Psat_dT2, base=e)
            self.poly_fit_AB_high = list(
                Antoine_AB_coeffs_from_point(Tmax, Psat, dPsat_dT, base=e))
            self.poly_fit_AB_high_ABC_compat = [
                self.poly_fit_AB_high[0], -self.poly_fit_AB_high[1]
            ]
            self.DIPPR101_ABC_high = list(
                DIPPR101_ABC_coeffs_from_point(Tmax, Psat, dPsat_dT,
                                               d2Psat_dT2))

        except:
            pass
Beispiel #4
0
 def func(T):
     if T < Tmin:
         Cp = (T - Tmin)*Tmin_slope + Tmin_value
     elif T > Tmax:
         Cp = (T - Tmax)*Tmax_slope + Tmax_value
     else:
         Cp = horner(coeffs, T)
     return Cp
Beispiel #5
0
def Rac_Nusselt_Rayleigh_disk(H, D, insulated=True):
    r'''Calculates the critical Rayleigh number for free convection to begin
    in the parallel horizontal disk scenario. There are
    actually two cases - one for the top plate to be insulated (adiabatic) and
    the other where it has infinite thermal conductivity/is infinitely thin or
    not present (perfectly conducting). All real cases will lie between the
    two.
    
    Parameters
    ----------
    H : float
        Distance between the two disks, [m]
    D : float
        Diameter of the two disks, [m]
    insulated : bool, optional
        Whether the top plate is insulated or uninsulated, [-]

    Returns
    -------
    Rac : float
        Critical Rayleigh number, [-]

    Examples
    --------
    >>> Rac_Nusselt_Rayleigh_disk(H=1, D=.4, insulated=False)
    151199.9999999945
    
    >>> Rac_Nusselt_Rayleigh_disk(H=1, D=4, insulated=False)
    1891.520931853363
    
    >>> Rac_Nusselt_Rayleigh_disk(2, 1, True)
    24347.31479211917

    Notes
    -----
    The range of data covered by this function is `D`/`H` from 0.4 to infinity.
    As inifinity is not well suited to polynomial form, the upper limit is 
    6 in actuality. Values outside that range are rounded to the limits.
    
    This function provides 17-coefficient polynomial fits to interpolate in the
    table of values in [1]_. The source of the coefficients is cited as being
    from [2]_.

    References
    ----------
    .. [1] Rohsenow, Warren and James Hartnett and Young Cho. Handbook of Heat
       Transfer, 3E. New York: McGraw-Hill, 1998.
    .. [2] Buell, J. C., and I. Catton. "The Effect of Wall Conduction on the 
       Stability of a Fluid in a Right Circular Cylinder Heated From Below."
       Journal of Heat Transfer 105, no. 2 (May 1, 1983): 255-60.
       https://doi.org/10.1115/1.3245571.
    '''
    x = min(max(D / H, 0.4), 6.0)
    if insulated:
        coeffs = insulated_disk_coeffs
    else:
        coeffs = uninsulated_disk_coeffs
    return exp(1.0 / horner(coeffs, 0.357142857142857151 * (x - 3.2)))
Beispiel #6
0
def test_fit_cheb_poly():
    eos = PR(Tc=507.6, Pc=3025000.0, omega=0.2975, T=400., P=1E6)

    coeffs_linear_short = fit_cheb_poly(eos.Psat, 350, 370, 10)
    for T in linspace(350, 370, 30):
        assert_close(eos.Psat(T), horner(coeffs_linear_short, T), rtol=1e-9)



    # Test transformation of the output only
    coeffs_log_wide = fit_cheb_poly(eos.Psat, 200, 400, 15, interpolation_property=lambda x: log(x),
                                            interpolation_property_inv=lambda x: exp(x))

    for T in linspace(200, 400, 30):
        assert_close(eos.Psat(T), exp(horner(coeffs_log_wide, T)), rtol=1e-9)

    # Test ability to have other arguments depend on it
    coeffs_linear_short_under_P = fit_cheb_poly(lambda T, P: eos.to(T=T, P=P).V_l, 350, 370, 7,
                                                arg_func=lambda T: (eos.Psat(T)*1.1,))

    for T in linspace(350, 370, 30):
        P = eos.Psat(T)*1.1
        assert_close(eos.to(T=T, P=P).V_l, horner(coeffs_linear_short_under_P, T), rtol=1e-9)

    # Test ability to have other arguments depend on it
    coeffs_log_short_above_P = fit_cheb_poly(lambda T, P: eos.to(T=T, P=P).V_g, 350, 370, 7,
                                             arg_func=lambda T: (eos.Psat(T)*.7,),
                                             interpolation_property=lambda x: log(x),
                                             interpolation_property_inv=lambda x: exp(x))
    for T in linspace(350, 370, 30):
        P = eos.Psat(T)*0.7
        assert_close(eos.to(T=T, P=P).V_g, exp(horner(coeffs_log_short_above_P, T)), rtol=1e-9)


    # test interpolation_x
    Tc = 750.0
    coeffs_linear_short_SMK_x_trans = fit_cheb_poly(lambda T: SMK(T, Tc=Tc, omega=0.04), 200, 748, 20,
                                            interpolation_x=lambda T: log(1. - T/Tc),
                                            interpolation_x_inv=lambda x: -(exp(x)-1.0)*Tc)
    for T in linspace(200, 748, 30):
        x =  log(1. - T/Tc)
        assert_close(SMK(T, Tc=Tc, omega=0.04), horner(coeffs_linear_short_SMK_x_trans, x), rtol=1e-7)

    # Case with one coefficient and no T bounds
    assert_close1d(fit_cheb_poly(func=lambda T: 102.5, low=298.15, high=298.15, n=1), [102.5])
Beispiel #7
0
    def calculate(self, T, method):
        r'''Method to calculate heat of sublimation of a solid at
        temperature `T` with a given method.

        This method has no exception handling; see :obj:`T_dependent_property <thermo.utils.TDependentProperty.T_dependent_property>`
        for that.

        Parameters
        ----------
        T : float
            Temperature at which to calculate heat of sublimation, [K]
        method : str
            Name of the method to use

        Returns
        -------
        Hsub : float
            Heat of sublimation of the solid at T, [J/mol]
        '''
        if method == POLY_FIT:
            if T < self.poly_fit_Tmin:
                Hsub = (T - self.poly_fit_Tmin
                        ) * self.poly_fit_Tmin_slope + self.poly_fit_Tmin_value
            elif T > self.poly_fit_Tmax:
                Hsub = (T - self.poly_fit_Tmax
                        ) * self.poly_fit_Tmax_slope + self.poly_fit_Tmax_value
            else:
                Hsub = horner(self.poly_fit_coeffs, T)

        elif method == GHARAGHEIZI_HSUB_298:
            Hsub = self.GHARAGHEIZI_Hsub
        elif method == GHARAGHEIZI_HSUB:
            T_base = 298.15
            Hsub = self.GHARAGHEIZI_Hsub
        elif method == CRC_HFUS_HVAP_TM:
            T_base = self.Tm
            Hsub = self.CRC_Hfus
            try:
                Hsub += self.Hvap(T_base)
            except:
                Hsub += self.Hvap
        else:
            return self._base_calculate(T, method)
        if method in (GHARAGHEIZI_HSUB, CRC_HFUS_HVAP_TM):
            try:
                #                Cpg, Cps = self.Cpg(T_base), self.Cps(T_base)
                #                Hsub += (T - T_base)*(Cpg - Cps)
                Hsub += self.Cpg.T_dependent_property_integral(
                    T_base, T) - self.Cps.T_dependent_property_integral(
                        T_base, T)
            except:
                Hsub += (T - T_base) * (self.Cpg - self.Cps)

        return Hsub
Beispiel #8
0
    def calculate(self, T, method):
        r'''Method to calculate sublimation pressure of a fluid at temperature
        `T` with a given method.

        This method has no exception handling; see :obj:`T_dependent_property <thermo.utils.TDependentProperty.T_dependent_property>`
        for that.

        Parameters
        ----------
        T : float
            Temperature at calculate sublimation pressure, [K]
        method : str
            Name of the method to use

        Returns
        -------
        Psub : float
            Sublimation pressure at T, [pa]
        '''
        if method == BESTFIT:
            if T < self.poly_fit_Tmin:
                Psub = (T - self.poly_fit_Tmin
                        ) * self.poly_fit_Tmin_slope + self.poly_fit_Tmin_value
            elif T > self.poly_fit_Tmax:
                Psub = (T - self.poly_fit_Tmax
                        ) * self.poly_fit_Tmax_slope + self.poly_fit_Tmax_value
            else:
                Psub = horner(self.poly_fit_coeffs, T)
            Psub = exp(Psub)
        elif method == PSUB_CLAPEYRON:
            Psub = max(
                Psub_Clapeyron(T, Tt=self.Tt, Pt=self.Pt, Hsub_t=self.Hsub_t),
                1e-200)
        elif method in self.tabular_data:
            Psub = self.interpolate(T, method)
        return Psub
Beispiel #9
0
    def calculate(self, T, method):
        r'''Method to calculate vapor pressure of a fluid at temperature `T`
        with a given method.

        This method has no exception handling; see :obj:`thermo.utils.TDependentProperty.T_dependent_property`
        for that.

        Parameters
        ----------
        T : float
            Temperature at calculate vapor pressure, [K]
        method : str
            Name of the method to use

        Returns
        -------
        Psat : float
            Vapor pressure at T, [pa]
        '''
        if method == BESTFIT:
            if T < self.poly_fit_Tmin:
                Psat = (T - self.poly_fit_Tmin
                        ) * self.poly_fit_Tmin_slope + self.poly_fit_Tmin_value
            elif T > self.poly_fit_Tmax:
                Psat = (T - self.poly_fit_Tmax
                        ) * self.poly_fit_Tmax_slope + self.poly_fit_Tmax_value
            else:
                Psat = horner(self.poly_fit_coeffs, T)
            Psat = exp(Psat)
        elif method == BEST_FIT_AB:
            if T < self.poly_fit_Tmax:
                return self.calculate(T, BESTFIT)
            A, B = self.poly_fit_AB_high_ABC_compat
            return exp(A + B / T)
        elif method == BEST_FIT_ABC:
            if T < self.poly_fit_Tmax:
                return self.calculate(T, BESTFIT)
            A, B, C = self.DIPPR101_ABC_high
            return exp(A + B / T + C * log(T))
        elif method == WAGNER_MCGARRY:
            Psat = Wagner_original(T, self.WAGNER_MCGARRY_Tc,
                                   self.WAGNER_MCGARRY_Pc,
                                   *self.WAGNER_MCGARRY_coefs)
        elif method == WAGNER_POLING:
            Psat = Wagner(T, self.WAGNER_POLING_Tc, self.WAGNER_POLING_Pc,
                          *self.WAGNER_POLING_coefs)
        elif method == ANTOINE_EXTENDED_POLING:
            Psat = TRC_Antoine_extended(T, *self.ANTOINE_EXTENDED_POLING_coefs)
        elif method == ANTOINE_POLING:
            A, B, C = self.ANTOINE_POLING_coefs
            Psat = Antoine(T, A, B, C, base=10.0)
        elif method == DIPPR_PERRY_8E:
            Psat = EQ101(T, *self.Perrys2_8_coeffs)
        elif method == VDI_PPDS:
            Psat = Wagner(T, self.VDI_PPDS_Tc, self.VDI_PPDS_Pc,
                          *self.VDI_PPDS_coeffs)
        elif method == COOLPROP:
            Psat = PropsSI('P', 'T', T, 'Q', 0, self.CASRN)
        elif method == BOILING_CRITICAL:
            Psat = boiling_critical_relation(T, self.Tb, self.Tc, self.Pc)
        elif method == LEE_KESLER_PSAT:
            Psat = Lee_Kesler(T, self.Tc, self.Pc, self.omega)
        elif method == AMBROSE_WALTON:
            Psat = Ambrose_Walton(T, self.Tc, self.Pc, self.omega)
        elif method == SANJARI:
            Psat = Sanjari(T, self.Tc, self.Pc, self.omega)
        elif method == EDALAT:
            Psat = Edalat(T, self.Tc, self.Pc, self.omega)
        elif method == EOS:
            Psat = self.eos[0].Psat(T)
        elif method == BESTFIT:
            Psat = exp(horner(self.poly_fit_coeffs, T))
        else:
            return self._base_calculate(T, method)
        return Psat
Beispiel #10
0
    def calculate(self, T, method):
        r'''Method to calculate heat of vaporization of a liquid at
        temperature `T` with a given method.

        This method has no exception handling; see :obj:`T_dependent_property <thermo.utils.TDependentProperty.T_dependent_property>`
        for that.

        Parameters
        ----------
        T : float
            Temperature at which to calculate heat of vaporization, [K]
        method : str
            Name of the method to use

        Returns
        -------
        Hvap : float
            Heat of vaporization of the liquid at T, [J/mol]
        '''
        if method == POLY_FIT:
            if T > self.poly_fit_Tc:
                Hvap = 0.0
            else:
                Hvap = horner(self.poly_fit_coeffs,
                              log(1.0 - T / self.poly_fit_Tc))

        elif method == COOLPROP:
            Hvap = PropsSI('HMOLAR', 'T', T, 'Q', 1, self.CASRN) - PropsSI(
                'HMOLAR', 'T', T, 'Q', 0, self.CASRN)
        elif method == DIPPR_PERRY_8E:
            Hvap = EQ106(T, *self.Perrys2_150_coeffs)
        # CSP methods
        elif method == VDI_PPDS:
            Hvap = PPDS12(T, self.VDI_PPDS_Tc, *self.VDI_PPDS_coeffs)
        elif method == ALIBAKHSHI:
            Hvap = Alibakhshi(T=T, Tc=self.Tc, C=self.Alibakhshi_C)
        elif method == MORGAN_KOBAYASHI:
            Hvap = MK(T, self.Tc, self.omega)
        elif method == SIVARAMAN_MAGEE_KOBAYASHI:
            Hvap = SMK(T, self.Tc, self.omega)
        elif method == VELASCO:
            Hvap = Velasco(T, self.Tc, self.omega)
        elif method == PITZER:
            Hvap = Pitzer(T, self.Tc, self.omega)
        elif method == CLAPEYRON:
            Psat = self.Psat(T) if callable(self.Psat) else self.Psat
            Zg = self.Zg(T, Psat) if callable(self.Zg) else self.Zg
            Zl = self.Zl(T, Psat) if callable(self.Zl) else self.Zl
            if Zg:
                if Zl:
                    dZ = Zg - Zl
                else:
                    dZ = Zg
            Hvap = Clapeyron(T, self.Tc, self.Pc, dZ=dZ, Psat=Psat)
        # CSP methods at Tb only
        elif method == RIEDEL:
            Hvap = Riedel(self.Tb, self.Tc, self.Pc)
        elif method == CHEN:
            Hvap = Chen(self.Tb, self.Tc, self.Pc)
        elif method == VETERE:
            Hvap = Vetere(self.Tb, self.Tc, self.Pc)
        elif method == LIU:
            Hvap = Liu(self.Tb, self.Tc, self.Pc)
        # Individual data point methods
        elif method == CRC_HVAP_TB:
            Hvap = self.CRC_HVAP_TB_Hvap
        elif method == CRC_HVAP_298:
            Hvap = self.CRC_HVAP_298
        elif method == GHARAGHEIZI_HVAP_298:
            Hvap = self.GHARAGHEIZI_HVAP_298_Hvap
        else:
            return self._base_calculate(T, method)
        # Adjust with the watson equation if estimated at Tb or Tc only
        if method in self.boiling_methods or (self.Tc and method in (
                CRC_HVAP_TB, CRC_HVAP_298, GHARAGHEIZI_HVAP_298)):
            if method in self.boiling_methods:
                Tref = self.Tb
            elif method == CRC_HVAP_TB:
                Tref = self.CRC_HVAP_TB_Tb
            elif method in [CRC_HVAP_298, GHARAGHEIZI_HVAP_298]:
                Tref = 298.15
            Hvap = Watson(T, Hvap, Tref, self.Tc, self.Watson_exponent)
        return Hvap
Beispiel #11
0
def fit_cheb_poly(func, low, high, n,
                  interpolation_property=None, interpolation_property_inv=None,
                  interpolation_x=lambda x: x, interpolation_x_inv=lambda x: x,
                  arg_func=None):
    r'''Fit a function of one variable to a polynomial of degree `n` using the
    Chebyshev approximation technique. Transformations of the base function
    are allowed as lambdas.

    Parameters
    ----------
    func : callable
        Function to fit, [-]
    low : float
        Low limit of fitting range, [-]
    high : float
        High limit of fitting range, [-]
    n : int
        Degree of polynomial fitting, [-]
    interpolation_property : None or callable
        When specified, this callable will transform the output of the function
        before fitting; for example a property like vapor pressure should be
        `interpolation_property=lambda x: log(x)` because it rises
        exponentially. The output of the evaluated polynomial should then have
        the reverse transform applied to it; in this case, `exp`, [-]
    interpolation_property_inv : None or callable
        When specified, this callable reverses `interpolation_property`; it
        must always be provided when `interpolation_property` is set, and it
        must perform the reverse transform, [-]
    interpolation_x : None or callable
        Callable to transform the input variable to fitting. For example,
        enthalpy of vaporization goes from a high value at low temperatures to zero at
        the critical temperature; it is normally hard for a chebyshev series
        to match this, but by setting this to lambda T: log(1. - T/Tc), this
        issue is resolved, [-]
    interpolation_x_inv : None or callable
        Inverse function of `interpolation_x_inv`; must always be provided when
        `interpolation_x` is set, and it must perform the reverse transform,
        [-]
    arg_func : None or callable
        Function which is called with the value of `x` in the original domain,
        and that returns arguments to `func`.

    Returns
    -------
    coeffs : list[float]
        Polynomial coefficients in order for evaluation by `horner`, [-]

    Notes
    -----
    This is powered by Ian Bell's ChebTools.

    '''
    global ChebTools
    if ChebTools is None:
        import ChebTools

    low_orig, high_orig = low, high
    cheb_fun = None
    low, high = interpolation_x(low_orig), interpolation_x(high_orig)
    if arg_func is not None:
        if interpolation_property is not None:
            def func_fun(T):
                arg = interpolation_x_inv(T)
                if arg > high_orig:
                    arg = high_orig
                if arg < low_orig:
                    arg = low_orig
                return interpolation_property(func(arg, *arg_func(arg)))
        else:
            def func_fun(T):
                arg = interpolation_x_inv(T)
                if arg > high_orig:
                    arg = high_orig
                if arg < low_orig:
                    arg = low_orig
                return func(arg, *arg_func(arg))
    else:
        if interpolation_property is not None:
            def func_fun(T):
                arg = interpolation_x_inv(T)
                if arg > high_orig:
                    arg = high_orig
                if arg < low_orig:
                    arg = low_orig
                return interpolation_property(func(arg))
        else:
            def func_fun(T):
                arg = interpolation_x_inv(T)
                if arg > high_orig:
                    arg = high_orig
                if arg < low_orig:
                    arg = low_orig
                return func(arg)
    func_fun = np.vectorize(func_fun)
    if n == 1:
        coeffs = [func_fun(0.5*(low + high)).tolist()]
    else:
        cheb_fun = ChebTools.generate_Chebyshev_expansion(n-1, func_fun, low, high)

        coeffs = cheb_fun.coef()
        coeffs = cheb2poly(coeffs)[::-1].tolist() # Convert to polynomial basis
    # Mix in low high limits to make it a normal polynomial
    if high != low:
        # Handle the case of no transformation, no limits
        my_poly = Polynomial([-0.5*(high + low)*2.0/(high - low), 2.0/(high - low)])
        coeffs = horner(coeffs, my_poly).coef[::-1].tolist()
    return coeffs
Beispiel #12
0
def poly_fit_statistics(func, coeffs, low, high, pts=200,
                        interpolation_property_inv=None,
                        interpolation_x=lambda x: x,
                        arg_func=None):
    r'''Function to check how accurate a fit function is to a polynomial.

    This function uses the asolute relative error definition.

    Parameters
    ----------
    func : callable
        Function to fit, [-]
    coeffs : list[float]
        Coefficients for calculating the property, [-]
    low : float
        Low limit of fitting range, [-]
    high : float
        High limit of fitting range, [-]
    n : int
        Degree of polynomial fitting, [-]
    interpolation_property_inv : None or callable
        When specified, this callable reverses `interpolation_property`; it
        must always be provided when `interpolation_property` is set, and it
        must perform the reverse transform, [-]
    interpolation_x : None or callable
        Callable to transform the input variable to fitting. For example,
        enthalpy of vaporization goes from a high value at low temperatures to zero at
        the critical temperature; it is normally hard for a chebyshev series
        to match this, but by setting this to lambda T: log(1. - T/Tc), this
        issue is resolved, [-]
    arg_func : None or callable
        Function which is called with the value of `x` in the original domain,
        and that returns arguments to `func`.

    Returns
    -------
    err_avg : float
        Mean error in the evaluated points, [-]
    err_std : float
        Standard deviation of errors in the evaluated points, [-]
    min_ratio : float
        Lowest ratio of calc/actual in any found points, [-]
    max_ratio : float
        Highest ratio of calc/actual in any found points, [-]

    Notes
    -----
    '''

    low_orig, high_orig = low, high
    all_points_orig = linspace(low_orig, high_orig, pts)

    # Get the low, high, and x points in the transformed domain
    low, high = interpolation_x(low_orig), interpolation_x(high_orig)
    all_points = [interpolation_x(v) for v in all_points_orig]

    # Calculate the fit values
    calc_pts = [horner(coeffs, x) for x in all_points]
    if interpolation_property_inv:
        for i in range(pts):
            calc_pts[i] = interpolation_property_inv(calc_pts[i])

    if arg_func is not None:
        actual_pts = [func(v, *arg_func(v)) for v in all_points_orig]
    else:
        actual_pts = [func(v) for v in all_points_orig]

    ARDs = [(abs((i-j)/j) if j != 0 else 0.0) for i, j in zip(calc_pts, actual_pts)]

    err_avg = sum(ARDs)/pts
    err_std = np.std(ARDs)

    actual_pts = np.array(actual_pts)
    calc_pts = np.array(calc_pts)

    max_ratio, min_ratio = max(calc_pts/actual_pts), min(calc_pts/actual_pts)
    return err_avg, err_std, min_ratio, max_ratio
Beispiel #13
0
def test_horner():
    from fluids.numerics import horner
    assert_allclose(horner([1.0, 3.0], 2.0), 5.0)
    assert_allclose(horner([3.0], 2.0), 3.0)