예제 #1
0
def findNearest(locarr, loc, notFoundVal=None):
    # returns nearest index from locarr (minimize abs(loc-locarr[?]))
    # return values: idxleft, idxright, idxclosest (idxclosesti is either 0 or 1)
    #
    # About NaNs: Currently can handle a situation where there are NaNs at
    # either end of the array. Intermittent NaNs cause unknonwn behaviour.

    if loc < locarr[0] or loc > locarr[-1]:
        if notFoundVal is None:
            raise pyle.PyLerr_OutsideRange (loc)
        else:
            return notFoundVal
    gtearr = [loc >= val for val in locarr]
    ltearr = [loc <= val for val in locarr]
    andarr = [gtearr[i] and ltearr[i] for i in range(len(gtearr))]
    xorarr = [gtearr[i]  ^  ltearr[i] for i in range(len(gtearr))]
    if np.nansum(andarr) == 1:  # found exact location
        idx = andarr.index(True)
        return (idx, idx, 0)  #  0 could as well be 1
    elif np.nansum(andarr) == 0 and np.nansum(xorarr) == len(gtearr)-np.isnan(locarr).sum():
        ilt = ltearr.index(True)-1
        igt = [True if locarr[i]!=locarr[i] else gtearr[i] for i in range(len(gtearr))].index(False)
        # igt = gtearr.index(False) # <-- this is the idea, but this can't handle Falses in between, caused by nans
        if ilt != igt-1:
            raise pyle.PyLerr_Undefined ("ilt != igt-1")
        if abs(locarr[ilt]-loc) <= abs(locarr[igt]-loc):
            return (ilt, igt, 0)
        else:
            return (ilt, igt, 1)
    else:
        raise pyle.PyLerr_Undefined ("Strange locarr, unordered?")
예제 #2
0
    def updatePerplex(self, perplex=None):
        if perplex is None:
            if self.perplex is None:
                raise pyle.PyLerr_Undefined("No valid perplex module")
            else:
                perplex = self.perplex
        else:
            self.perplex = perplex

        if set(self.components) != set(perplex.callerComponents) or len(
                self.components) != len(perplex.callerComponents):
            raise pyle.PyLerr_Undefined("component set mismatch")

        if self._P is None or self._T is None:
            raise pyle.PyLerr_Undefined("P or T not set")

        idxs = [self.components.index(a) for a in perplex.callerComponents]

        masses = np.array(self.masses, dtype=float)
        masses = masses / np.sum(masses)
        masses = masses[idxs]

        self.perplexResult = None
        self.perplexResult = perplex.phaseq(self._P,
                                            self._T,
                                            masses.tolist(),
                                            debug=False)
예제 #3
0
def interpolate(locarr, valarr, locarrnew, notFoundVal=float('NaN')):
    # find values from valarr at locations locarrnew

    valarrnew = []

    for loc in locarrnew:
        if loc < locarr[0] or loc > locarr[-1]:
            valarrnew.append(notFoundVal)
            continue

        try:
            (ilt, igt, which) = findNearest(locarr, loc)
        except pyle.PyLerr_OutsideRange as e:
            valarrnew.append(notFoundVal)
            continue
        except Exception as e:
            raise e

        if ilt == igt:
            newval = valarr[ilt]
        elif which >= 0:
            newval = valarr[ilt] + (valarr[igt]-valarr[ilt])*(loc-locarr[ilt])/(locarr[igt]-locarr[ilt])
        else:
            raise pyle.PyLerr_Undefined ("interpolate(): I don't understand findNearest()")

        valarrnew.append(newval)

    return valarrnew
예제 #4
0
 def __init__(self, copyfrom=None, compos=None, masses=None, perplex=None):
     if copyfrom is None:
         if compos is None:
             self.components = []
             self.masses = []
             self.ncomponents = 0
             self._T = None
             self._P = None
             self._H = None
         else:
             self.components = compos[:]
             self.ncomponents = len(self.components)
             if masses is None:
                 self.masses = [0] * self.ncomponents
             else:
                 if self.ncomponents != len(masses):
                     raise pyle.PyLerr_Undefined(
                         "len(components) != len(masses)")
                 self.masses = masses[:]
             self._T = None
             self._P = None
             self._H = None
     else:
         if not isinstance(copyfrom, Container):
             raise pyle.PyLerr_TypeError(
                 "Argument is not instance of Container")
         self.components = copy.components[:]
         self.masses = copyfrom.masses[:]
         self.ncomponents = copyfrom.ncomponents
         self._T = copyfrom._T
         self._P = copyfrom._P
         self._H = copyfrom._H
     self.perplex = perplex
     self.perplexResult = None
예제 #5
0
    def move_isentropic(self, dP, perplex=None):
        if self.perplexResult is None:
            self.updatePerplex(perplex=perplex)

        if self._P is None or self._T is None:
            raise pyle.PyLerr_Undefined("T/P not defined")

        maxerr = 0.01
        curerr = 1.1 * maxerr

        T0 = self.T
        P0 = self.P
        V0 = self.perplexResult['SYSPROP'][self.perplex.syspropnum['V']]
        Cp0 = self.perplexResult['SYSPROP'][self.perplex.syspropnum['Cp']]
        S0 = self.perplexResult['SYSPROP'][self.perplex.syspropnum['S']]
        H0 = self.perplexResult['SYSPROP'][self.perplex.syspropnum['H']]

        dH = V0 * dP  # q=0, only expansion work

        dT = dH / Cp0
        self.T = T0 + dT
        self.P = P0 + dP
        self.updatePerplex(perplex=perplex)
        S1 = self.perplexResult['SYSPROP'][self.perplex.syspropnum['S']]
        Cp1 = self.perplexResult['SYSPROP'][self.perplex.syspropnum['Cp']]

        dSph = S1 - S0  # entropy mismatch (entropy  change of phase changes)
        dHadj = (-dSph) * self.T  # to gain it back, modify enthalpy
        dTadj = dHadj / Cp1  # calculate corresponding temp change
        self.T = self.T + dTadj
        self.updatePerplex(perplex=perplex)
        S1 = self.perplexResult['SYSPROP'][self.perplex.syspropnum['S']]
        Cp1 = self.perplexResult['SYSPROP'][self.perplex.syspropnum['Cp']]
예제 #6
0
    def move_adiab(self, dPtot, dP=3e6 * 1e-5, perplex=None):
        # Assume adiabatic AND isentropic process
        #
        # dS = 0
        # dH = V dp
        #
        # 1. Read current H (H_1), S (S_1) and V (V_1) at T_1, P_1
        # 2. Calc dH = V dP
        # 3. Calc H_2 = H_1 + dH
        # 4. Find T_2, P_2==P_1 where H==H_2
        # 5. Check that S_2 == S_1
        #
        # 1. Estimate dH: dH = V dP
        # 2. Estimate dT: dT = dH / Cp
        # 3.

        method = 2

        if self.perplexResult is None:
            self.updatePerplex(perplex=perplex)

        if self._P is None or self._T is None:
            raise pyle.PyLerr_Undefined("T/P not defined")

        maxdT = 5.
        if dPtot < 0:
            dPdir = -1.
            if dP > 0:
                dP = -dP
        else:
            dPdir = 1.

        dPsum = 0.0
        dTsum = 0.0

        T0 = self._T
        rho0 = self.perplexResult['SYSPROP'][
            self.perplex.syspropnum['rho']]  # kg/m3
        Cp0 = 1000. * self.perplexResult['SYSPROP'][
            self.perplex.syspropnum['Cp']] / self.perplexResult['SYSPROP'][
                self.perplex.syspropnum['N']]  # J K^-1 kg^-1
        alpha0 = self.perplexResult['SYSPROP'][
            self.perplex.syspropnum['alpha']]
        #V0 = sum(self.masses) / rho0
        V0 = 1000. * self.perplexResult['SYSPROP'][
            self.perplex.syspropnum['V']] / self.perplexResult['SYSPROP'][
                self.perplex.syspropnum['N']]  # J/bar/kg
        H0 = 1000. * self.perplexResult['SYSPROP'][
            self.perplex.syspropnum['H']] / self.perplexResult['SYSPROP'][
                self.perplex.syspropnum['N']]  # J/kg

        origP = self.P
        origT = T0
        origV = V0
        origH = H0
        origCp = Cp0

        while abs(dPtot - dPsum) > dPdir * dPtot / 1e3:
            dP0 = dPdir * min(dPdir * dP, dPdir * dPtot - dPdir * dPsum)
            if method == 1:
                dT0 = T0 * alpha0 * dP0 * 1e5 / (Cp0 * rho0)
            elif method == 2:
                dH0 = dP0 * V0
                dT0 = dH0 / Cp0
            self.T = self.T + dT0
            self.P = self.P + dP0
            dPsum = dPsum + dP0
            print dP0, dPsum, dT0, self.T, self.P
            self.updatePerplex(perplex=perplex)
            T0 = self.T
            Cp0 = 1000. * self.perplexResult['SYSPROP'][
                self.perplex.syspropnum['Cp']] / self.perplexResult['SYSPROP'][
                    self.perplex.syspropnum['N']]
            alpha0 = self.perplexResult['SYSPROP'][
                self.perplex.syspropnum['alpha']]
            rho0 = self.perplexResult['SYSPROP'][
                self.perplex.syspropnum['rho']]
            V0 = 1000. * self.perplexResult['SYSPROP'][
                self.perplex.syspropnum['V']] / self.perplexResult['SYSPROP'][
                    self.perplex.syspropnum['N']]
            if method == 2:
                H1 = 1000. * self.perplexResult['SYSPROP'][
                    self.perplex.syspropnum['H']] / self.perplexResult[
                        'SYSPROP'][self.perplex.syspropnum['N']]
                print "H mismatch: ", (H1 - H0 - dH0), (H1 - H0), dH0
                H0 = H1

            print self.perplexResult['NAMEPHASES']
            if "melt(HP)" in self.perplexResult['NAMEPHASES']:
                print "Melt!"

        finalV = 1000. * self.perplexResult['SYSPROP'][self.perplex.syspropnum[
            'V']] / self.perplexResult['SYSPROP'][self.perplex.syspropnum['N']]
        finalH = 1000. * self.perplexResult['SYSPROP'][self.perplex.syspropnum[
            'H']] / self.perplexResult['SYSPROP'][self.perplex.syspropnum['N']]
        finalCp = 1000. * self.perplexResult['SYSPROP'][
            self.perplex.syspropnum['Cp']] / self.perplexResult['SYSPROP'][
                self.perplex.syspropnum['N']]
        print "dPtot:", dPtot
        print "P, T, V, H, Cp:"
        print "orig: ", origP, origT, origV, origH, origCp
        print "final:", self.P, self.T, finalV, finalH, finalCp