Ejemplo n.º 1
0
def saturation_pressure(Ref, ClassName, fName=None, LV=None):

    if fName is None:
        Tc = Props(Ref, 'Tcrit')
        pc = Props(Ref, 'pcrit')
        rhoc = Props(Ref, 'rhocrit')
        Tmin = Props(Ref, 'Tmin')

        TT = np.linspace(Tmin + 1e-6, Tc - 0.00001, 300)
        pL = Props('P', 'T', TT, 'Q', 0, Ref)
        pV = Props('P', 'T', TT, 'Q', 1, Ref)
        rhoL = Props('D', 'T', TT, 'Q', 0, Ref)
        rhoV = Props('D', 'T', TT, 'Q', 1, Ref)
    else:
        Tc = 423.27
        pc = 3533
        rhoc = 470
        Tmin = 273
        lines = open(fName, 'r').readlines()
        TT, p, rhoL, rhoV = [], [], [], []
        for line in lines:
            _T, _p, _rhoL, _rhoV = line.split(' ')
            TT.append(float(_T))
            p.append(float(_p))
            rhoL.append(float(_rhoL))
            rhoV.append(float(_rhoV))

        TT = np.array(TT)

    Np = 60
    n = range(1, Np)
    max_abserror = 0
    while len(n) > 3:

        def f_p(B, x):
            # B is a vector of the parameters.
            # x is an array of the current x values.
            return sum([_B * x**(_n / 2.0) for _B, _n in zip(B, n)])

        x = 1.0 - TT / Tc
        if LV == 'L':
            y = (np.log(pL) - np.log(pc)) * TT / Tc
        elif LV == 'V' or LV is None:
            y = (np.log(pV) - np.log(pc)) * TT / Tc

        linear = Model(f_p)
        mydata = Data(x, y)
        myodr = ODR(mydata, linear, beta0=[0] * len(n))
        myoutput = myodr.run()

        beta = myoutput.beta
        sd = myoutput.sd_beta

        p_fit = np.exp(f_p(myoutput.beta, x) * Tc / TT) * pc
        if LV == 'L':
            max_abserror = np.max(np.abs((p_fit / pL) - 1) * 100)
        elif LV == 'V' or LV is None:
            max_abserror = np.max(np.abs((p_fit / pV) - 1) * 100)

        print(max_abserror)
        psat_error = max_abserror

        dropped_indices = [i for i in range(len(n)) if abs(sd[i]) < 1e-15]
        if dropped_indices:
            # for i in reversed(dropped_indices):
            # randomly drop one of them
            n.pop(random.choice(dropped_indices))
            continue

        if max_abserror < 0.5:  # Max error is 0.5%
            Ncoeffs = str(list(myoutput.beta)).lstrip('[').rstrip(']')
            tcoeffs = str(n).lstrip('[').rstrip(']')
            maxerror = max_abserror
            N = len(n)
        else:
            break

        # Find the least significant entry (the one with the largest standard error)
        # and remove it
        n.pop(np.argmax(sd))

        # Remove elements that are not
    import textwrap
    template = textwrap.dedent(
    """
    double {name:s}Class::psat{LV:s}(double T)
    {{
        // Maximum absolute error is {psat_error:f} % between {Tmin:f} K and {Tmax:f} K
        const double t[]={{0, {tcoeffs:s}}};
        const double N[]={{0, {Ncoeffs:s}}};
        double summer=0,theta;
        theta=1-T/reduce.T;
        for (int i=1;i<={N:d};i++)
        {{
            summer += N[i]*pow(theta,t[i]/2);
        }}
        return reduce.p.Pa*exp(reduce.T/T*summer);
    }}
    """)
    the_string = template.format(N=len(n) + 1,
                            tcoeffs=tcoeffs,
                            Ncoeffs=Ncoeffs,
                            name=ClassName,
                            Tmin=Tmin,
                            Tmax=TT[-1],
                            psat_error=maxerror,
                            LV=LV if LV in ['L', 'V'] else ''
                            )

    f = open('anc.txt', 'a')
    f.write(the_string)
    f.close()
    return the_string
Ejemplo n.º 2
0
def saturation_pressure(Ref, ClassName, fName=None, LV=None):

    if fName is None:
        Tc = Props(Ref, 'Tcrit')
        pc = Props(Ref, 'pcrit')
        rhoc = Props(Ref, 'rhocrit')
        Tmin = Props(Ref, 'Tmin')

        TT = np.linspace(Tmin + 1e-6, Tc - 0.00001, 300)
        pL = Props('P', 'T', TT, 'Q', 0, Ref)
        pV = Props('P', 'T', TT, 'Q', 1, Ref)
        rhoL = Props('D', 'T', TT, 'Q', 0, Ref)
        rhoV = Props('D', 'T', TT, 'Q', 1, Ref)
    else:
        Tc = 423.27
        pc = 3533
        rhoc = 470
        Tmin = 273
        lines = open(fName, 'r').readlines()
        TT, p, rhoL, rhoV = [], [], [], []
        for line in lines:
            _T, _p, _rhoL, _rhoV = line.split(' ')
            TT.append(float(_T))
            p.append(float(_p))
            rhoL.append(float(_rhoL))
            rhoV.append(float(_rhoV))

        TT = np.array(TT)

    Np = 60
    n = range(1, Np)
    max_abserror = 0
    while len(n) > 3:

        def f_p(B, x):
            # B is a vector of the parameters.
            # x is an array of the current x values.
            return sum([_B * x**(_n / 2.0) for _B, _n in zip(B, n)])

        x = 1.0 - TT / Tc
        if LV == 'L':
            y = (np.log(pL) - np.log(pc)) * TT / Tc
        elif LV == 'V' or LV is None:
            y = (np.log(pV) - np.log(pc)) * TT / Tc

        linear = Model(f_p)
        mydata = Data(x, y)
        myodr = ODR(mydata, linear, beta0=[0] * len(n))
        myoutput = myodr.run()

        beta = myoutput.beta
        sd = myoutput.sd_beta

        p_fit = np.exp(f_p(myoutput.beta, x) * Tc / TT) * pc
        if LV == 'L':
            max_abserror = np.max(np.abs((p_fit / pL) - 1) * 100)
        elif LV == 'V' or LV is None:
            max_abserror = np.max(np.abs((p_fit / pV) - 1) * 100)

        print(max_abserror)
        psat_error = max_abserror

        dropped_indices = [i for i in range(len(n)) if abs(sd[i]) < 1e-15]
        if dropped_indices:
            #for i in reversed(dropped_indices):
            # randomly drop one of them
            n.pop(random.choice(dropped_indices))
            continue

        if max_abserror < 0.5:  #Max error is 0.5%
            Ncoeffs = str(list(myoutput.beta)).lstrip('[').rstrip(']')
            tcoeffs = str(n).lstrip('[').rstrip(']')
            maxerror = max_abserror
            N = len(n)
        else:
            break

        # Find the least significant entry (the one with the largest standard error)
        # and remove it
        n.pop(np.argmax(sd))

        #Remove elements that are not
    import textwrap
    template = textwrap.dedent("""
    double {name:s}Class::psat{LV:s}(double T)
    {{
        // Maximum absolute error is {psat_error:f} % between {Tmin:f} K and {Tmax:f} K
        const double t[]={{0, {tcoeffs:s}}};
        const double N[]={{0, {Ncoeffs:s}}};
        double summer=0,theta;
        theta=1-T/reduce.T;
        for (int i=1;i<={N:d};i++)
        {{
            summer += N[i]*pow(theta,t[i]/2);
        }}
        return reduce.p.Pa*exp(reduce.T/T*summer);
    }}
    """)
    the_string = template.format(N=len(n) + 1,
                                 tcoeffs=tcoeffs,
                                 Ncoeffs=Ncoeffs,
                                 name=ClassName,
                                 Tmin=Tmin,
                                 Tmax=TT[-1],
                                 psat_error=maxerror,
                                 LV=LV if LV in ['L', 'V'] else '')

    f = open('anc.txt', 'a')
    f.write(the_string)
    f.close()
    return the_string
Ejemplo n.º 3
0
def saturation_density(Ref, ClassName, form='A', LV='L', perc_error_allowed=0.3, fName=None, add_critical=True):
    """

    Parameters
    ----------
    Ref : string
        The fluid name for the fluid that will be used to generate the saturation data
    ClassName : The name of the class that will be used in the C++ code
    form : string
        If ``'A'``, use a term of the form
    """

    if fName is None:
        Tc = Props(Ref, 'Tcrit')
        pc = Props(Ref, 'pcrit')
        rhoc = Props(Ref, 'rhocrit')
        Tmin = Props(Ref, 'Tmin')
        print("%s %s %s" % (Ref, Tmin, Props(Ref, 'Ttriple')))

        TT = np.linspace(Tmin, Tc - 1, 1000)
        TT = list(TT)
        # Add temperatures around the critical temperature
        if add_critical:
            for dT in [1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1]:
                TT.append(Tc - dT)
        TT = np.array(sorted(TT))

        p = Props('P', 'T', TT, 'Q', 0, Ref)
        rhoL = Props('D', 'T', TT, 'Q', 0, Ref)
        rhoV = Props('D', 'T', TT, 'Q', 1, Ref)
    else:
        Tc = 423.27
        pc = 3533
        rhoc = 470
        Tmin = 273
        lines = open(fName, 'r').readlines()
        TT, p, rhoL, rhoV = [], [], [], []
        for line in lines:
            _T, _p, _rhoL, _rhoV = line.split(' ')
            TT.append(float(_T))
            p.append(float(_p))
            rhoL.append(float(_rhoL))
            rhoV.append(float(_rhoV))

        TT = np.array(TT)

    # Start with a large library of potential powers
    n = [i / 6.0 for i in range(1, 200)]  # +[0.35+i/200.0 for i in range(1,70)]+[0.05+0.01*i for i in range(1,70)]

    x = 1.0 - TT / Tc

    if LV == 'L':
        rho_EOS = rhoL
    elif LV == 'V':
        rho_EOS = rhoV
    else:
        raise ValueError

    if form == 'A':
        y = np.array(rho_EOS) / rhoc - 1
    elif form == 'B':
        y = (np.log(rho_EOS) - np.log(rhoc)) * TT / Tc
    else:
        raise ValueError

    max_abserror = 0
    while len(n) > 3:
        print("%s %s" % (max_abserror, len(n)))

        def f_p(B, x):
            # B is a vector of the parameters.
            # x is an array of the current x values.
            return sum([_B * x**(_n) for _B, _n in zip(B, n)])

        linear = Model(f_p)
        mydata = Data(x, y)
        myodr = ODR(mydata, linear, beta0=[0] * len(n))
        myoutput = myodr.run()

        beta = myoutput.beta
        sd = myoutput.sd_beta

        if form == 'A':
            rho_fit = (f_p(myoutput.beta, x) + 1) * rhoc
        elif form == 'B':
            rho_fit = np.exp(f_p(myoutput.beta, x) * Tc / TT) * rhoc
        else:
            raise ValueError

        print('first,last %s %s %s %s %s %s' % (TT[0], TT[-1], rho_fit[0], rho_fit[-1], rho_EOS[0], rho_EOS[-1]))

        max_abserror = np.max(np.abs(rho_fit / rho_EOS - 1)) * 100

        dropped_indices = [i for i in range(len(n)) if abs(sd[i]) < 1e-15]
        if dropped_indices:
            for i in reversed(sorted(dropped_indices)):
                n.pop(i)
            print('popping... %s terms remaining' % len(n))
            continue

        if max_abserror > perc_error_allowed:
            break  # The last good run will be used
        else:
            print(max_abserror)
            Ncoeffs = str(list(myoutput.beta)).lstrip('[').rstrip(']')
            tcoeffs = str(n).lstrip('[').rstrip(']')
            maxerror = max_abserror
            if form == 'A':
                code_template = textwrap.dedent(
                """
                for (int i=1; i<={count:d}; i++)
                {{
                    summer += N[i]*pow(theta,t[i]);
                }}
                return reduce.rho*(summer+1);
                """.format(count=len(n))
                )
            elif form == 'B':
                code_template = textwrap.dedent(
                """
                for (int i=1; i<={count:d}; i++)
                {{
                    summer += N[i]*pow(theta,t[i]);
                }}
                return reduce.rho*exp(reduce.T/T*summer);
                """.format(count=len(n))
                )
            else:
                raise ValueError

        # Find the least significant entry (the one with the largest relative standard error)
        # and remove it
        n.pop(np.argmax(np.abs(sd / beta)))

        # Remove elements that are not
    template = textwrap.dedent(
    """
    double {name:s}Class::rhosat{LV:s}(double T)
    {{
        // Maximum absolute error is {error:f} % between {Tmin:f} K and {Tmax:f} K
        const double t[] = {{0, {tcoeffs:s}}};
        const double N[] = {{0, {Ncoeffs:s}}};
        double summer=0,theta;
        theta=1-T/reduce.T;
        \t{code:s}
    }}
    """)
    the_string = template.format(tcoeffs=tcoeffs,
                            Ncoeffs=Ncoeffs,
                            name=ClassName,
                            Tmin=Tmin,
                            Tmax=TT[-1],
                            error=maxerror,
                            code=code_template,
                            LV=LV
                            )
    f = open('anc.txt', 'a')
    f.write(the_string)
    f.close()
    return the_string
Ejemplo n.º 4
0
def saturation_density(Ref,
                       ClassName,
                       form='A',
                       LV='L',
                       perc_error_allowed=0.3,
                       fName=None,
                       add_critical=True):
    """

    Parameters
    ----------
    Ref : string
        The fluid name for the fluid that will be used to generate the saturation data
    ClassName : The name of the class that will be used in the C++ code
    form : string
        If ``'A'``, use a term of the form
    """

    if fName is None:
        Tc = Props(Ref, 'Tcrit')
        pc = Props(Ref, 'pcrit')
        rhoc = Props(Ref, 'rhocrit')
        Tmin = Props(Ref, 'Tmin')
        print("%s %s %s" % (Ref, Tmin, Props(Ref, 'Ttriple')))

        TT = np.linspace(Tmin, Tc - 1, 1000)
        TT = list(TT)
        # Add temperatures around the critical temperature
        if add_critical:
            for dT in [
                    1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1
            ]:
                TT.append(Tc - dT)
        TT = np.array(sorted(TT))

        p = Props('P', 'T', TT, 'Q', 0, Ref)
        rhoL = Props('D', 'T', TT, 'Q', 0, Ref)
        rhoV = Props('D', 'T', TT, 'Q', 1, Ref)
    else:
        Tc = 423.27
        pc = 3533
        rhoc = 470
        Tmin = 273
        lines = open(fName, 'r').readlines()
        TT, p, rhoL, rhoV = [], [], [], []
        for line in lines:
            _T, _p, _rhoL, _rhoV = line.split(' ')
            TT.append(float(_T))
            p.append(float(_p))
            rhoL.append(float(_rhoL))
            rhoV.append(float(_rhoV))

        TT = np.array(TT)

    # Start with a large library of potential powers
    n = [
        i / 6.0 for i in range(1, 200)
    ]  #+[0.35+i/200.0 for i in range(1,70)]+[0.05+0.01*i for i in range(1,70)]

    x = 1.0 - TT / Tc

    if LV == 'L':
        rho_EOS = rhoL
    elif LV == 'V':
        rho_EOS = rhoV
    else:
        raise ValueError

    if form == 'A':
        y = np.array(rho_EOS) / rhoc - 1
    elif form == 'B':
        y = (np.log(rho_EOS) - np.log(rhoc)) * TT / Tc
    else:
        raise ValueError

    max_abserror = 0
    while len(n) > 3:
        print("%s %s" % (max_abserror, len(n)))

        def f_p(B, x):
            # B is a vector of the parameters.
            # x is an array of the current x values.
            return sum([_B * x**(_n) for _B, _n in zip(B, n)])

        linear = Model(f_p)
        mydata = Data(x, y)
        myodr = ODR(mydata, linear, beta0=[0] * len(n))
        myoutput = myodr.run()

        beta = myoutput.beta
        sd = myoutput.sd_beta

        if form == 'A':
            rho_fit = (f_p(myoutput.beta, x) + 1) * rhoc
        elif form == 'B':
            rho_fit = np.exp(f_p(myoutput.beta, x) * Tc / TT) * rhoc
        else:
            raise ValueError

        print(
            'first,last %s %s %s %s %s %s' %
            (TT[0], TT[-1], rho_fit[0], rho_fit[-1], rho_EOS[0], rho_EOS[-1]))

        max_abserror = np.max(np.abs(rho_fit / rho_EOS - 1)) * 100

        dropped_indices = [i for i in range(len(n)) if abs(sd[i]) < 1e-15]
        if dropped_indices:
            for i in reversed(sorted(dropped_indices)):
                n.pop(i)
            print('popping... %s terms remaining' % len(n))
            continue

        if max_abserror > perc_error_allowed:
            break  # The last good run will be used
        else:
            print(max_abserror)
            Ncoeffs = str(list(myoutput.beta)).lstrip('[').rstrip(']')
            tcoeffs = str(n).lstrip('[').rstrip(']')
            maxerror = max_abserror
            if form == 'A':
                code_template = textwrap.dedent("""
                for (int i=1; i<={count:d}; i++)
                {{
                    summer += N[i]*pow(theta,t[i]);
                }}
                return reduce.rho*(summer+1);
                """.format(count=len(n)))
            elif form == 'B':
                code_template = textwrap.dedent("""
                for (int i=1; i<={count:d}; i++)
                {{
                    summer += N[i]*pow(theta,t[i]);
                }}
                return reduce.rho*exp(reduce.T/T*summer);
                """.format(count=len(n)))
            else:
                raise ValueError

        # Find the least significant entry (the one with the largest relative standard error)
        # and remove it
        n.pop(np.argmax(np.abs(sd / beta)))

        #Remove elements that are not
    template = textwrap.dedent("""
    double {name:s}Class::rhosat{LV:s}(double T)
    {{
        // Maximum absolute error is {error:f} % between {Tmin:f} K and {Tmax:f} K
        const double t[] = {{0, {tcoeffs:s}}};
        const double N[] = {{0, {Ncoeffs:s}}};
        double summer=0,theta;
        theta=1-T/reduce.T;
        \t{code:s}
    }}
    """)
    the_string = template.format(tcoeffs=tcoeffs,
                                 Ncoeffs=Ncoeffs,
                                 name=ClassName,
                                 Tmin=Tmin,
                                 Tmax=TT[-1],
                                 error=maxerror,
                                 code=code_template,
                                 LV=LV)
    f = open('anc.txt', 'a')
    f.write(the_string)
    f.close()
    return the_string