Exemple #1
0
    def get_state(self, volume, temperature=None):
        '''
        Using SAFT gamma mie and automatic differentiation, return all the properties
        that could be derived from the EoS: (A, P, S, G, H)
        '''
        Var.set_order(2)
        self.volume = Var(mt.m3mol_to_nm(volume,
                                         molecules=self.__moltol()))  # nm3
        if isinstance(temperature, float):
            self.temp = Var(temperature)
        else:
            self.temp = Var(self.temp)

        A = self.helmholtz()  # J total for current system, Var
        molcs = self.__moltol()
        d1 = derivative(A, self.volume, self.temp, order=1, getvar=False)

        P = -d1[0] / pow(cst.nmtom, 3)  # Pa, float
        S = -d1[1] / molcs  # J/K per molecule, float
        G = (A + P * self.volume *
             pow(cst.nmtom, 3)) / molcs  # (J + Pa*m3) for each molecule, Var
        H = G + S * self.temp  # J + J/K * K (it is already in per molecule here), Var
        A = A.value / molcs
        # Reset system back to floats
        self.volume = self.volume.value
        self.temp = self.temp.value
        return (A, P, S, G.value, H.value)
Exemple #2
0
    def critical_point(self,
                       initial_t=300,
                       initial_v=3e-4,
                       v_nd=None,
                       get_volume=False,
                       get_density=False,
                       print_results=True,
                       solver=least_squares,
                       solver_kwargs={'bounds': (0.1, 10)},
                       xtol=1e-8,
                       print_progress=False):
        tscale = initial_t
        x0 = np.array([1.])
        if not isinstance(solver_kwargs, dict): solver_kwargs = {}
        if not isinstance(v_nd, np.ndarray): v_nd = np.logspace(-4, -2, 50)
        Var.set_order(2)
        crit_pt = solver(self.__crit_t,
                         x0,
                         xtol=xtol,
                         args=(v_nd, tscale, print_progress),
                         **solver_kwargs)

        if print_progress: print()
        if print_results: print(crit_pt)
        T = crit_pt.x[0] * tscale

        crit_v = solver(self.__crit_v,
                        np.array([initial_v]),
                        xtol=xtol,
                        args=(T, ),
                        bounds=(min(v_nd), max(v_nd)))
        v = crit_v.x[0]

        Var.set_order(1)
        self.volume = Var(mt.m3mol_to_nm(v, molecules=self.__moltol()))
        self.temp = T

        A = self.helmholtz()
        P = -derivative(A, self.volume, order=1) / pow(cst.nmtom, 3)

        self.volume = mt.m3mol_to_nm(v, molecules=self.__moltol())
        results = (P, T)
        if get_volume: results += (v, )
        if get_density: results += (1 / v, )

        return results
Exemple #3
0
    def __crit_v(self, v, T):
        self.temp = T
        v = v[0]
        self.volume = Var(mt.m3mol_to_nm(v, molecules=self.__moltol()))
        A = self.helmholtz()
        _, dpdv = derivative(A, self.volume, order=2)
        dpdv = -dpdv / (pow(cst.nmtom, 6) * cst.Na) / (cst.R * T)

        return dpdv
Exemple #4
0
    def __getp(self, x, targetP):
        '''
        Takes in single value to get P
        '''
        x = x[0]
        self.volume = Var(mt.m3mol_to_nm(x, molecules=self.__moltol()))
        A = self.helmholtz()
        P = -derivative(A, self.volume, order=1) / pow(cst.nmtom, 3)

        return P - targetP
Exemple #5
0
    def get_critical_point(self,
                           initial_guess=(3e-4, 300),
                           get_volume=False,
                           get_density=False,
                           print_results=True,
                           solver=least_squares,
                           solver_kwargs={'bounds': ((1e-1, 1e-1), (10, 10))},
                           xtol=1e-8,
                           print_progress=False):
        scaler = initial_guess
        x0 = np.array([1., 1.])
        if not isinstance(solver_kwargs, dict): solver_kwargs = {}
        Var.set_order(3)
        crit_pt = solver(self.__critpt,
                         x0,
                         xtol=xtol,
                         args=(print_progress, scaler),
                         **solver_kwargs)

        if print_progress: print()
        if print_results: print(crit_pt)
        vT = crit_pt.x
        v = vT[0] * scaler[0]
        T = vT[1] * scaler[1]

        Var.set_order(1)
        self.volume = Var(mt.m3mol_to_nm(v, molecules=self.__moltol()))
        self.temp = T

        A = self.helmholtz()
        P = -derivative(A, self.volume, order=1) / pow(cst.nmtom, 3)

        self.volume = mt.m3mol_to_nm(v, molecules=self.__moltol())
        results = (P, T)
        if get_volume: results += (v, )
        if get_density: results += (1 / v, )

        return results
Exemple #6
0
 def __crit_t(self, x, v_nd, scale, print_):
     T = x[0] * scale
     dp = np.zeros(np.size(v_nd))
     for i in range(len(v_nd)):
         v = v_nd[i]
         self.volume = Var(mt.m3mol_to_nm(v, molecules=self.__moltol()))
         self.temp = T
         A = self.helmholtz()
         _, dpdv = derivative(A, self.volume, order=2)
         dp[i] = -dpdv / (pow(cst.nmtom, 6) * cst.Na) / (cst.R * T)
     if print_:
         print(f'Current: T = {T:7.3f}: max dP/dV = {max(dp):7.3e}',
               end='\r')
     return max(dp)
Exemple #7
0
    def vapour_pressure(self,
                        temperature=None,
                        initial_guess=(1e-4, .1),
                        get_volume=False,
                        get_gibbs=False,
                        print_results=True,
                        solver=least_squares,
                        solver_kwargs={'bounds': ((0.1, 1e-2), (1e2, 1e2))},
                        print_progress=False):
        if isinstance(temperature, float) or isinstance(temperature, int):
            self.temp = temperature
        scaler = initial_guess
        x0 = np.array([1., 1.])
        if not isinstance(solver_kwargs, dict): solver_kwargs = {}
        vle = solver(self.__eqpg,
                     x0,
                     args=(print_progress, scaler),
                     **solver_kwargs)
        if print_progress: print()
        if print_results:
            print(
                f'Scaled wrt initial guess of ({scaler[0]:7.3e},{scaler[1]:7.3e})'
            )
            print(vle)
        vlv = (vle.x[0] * scaler[0], vle.x[1] * scaler[1])
        v = vlv[1]
        self.volume = Var(mt.m3mol_to_nm(v, molecules=self.__moltol()))

        A = self.helmholtz()
        P = -derivative(A, self.volume, order=1) / pow(cst.nmtom, 3)
        G = (A.value +
             P * self.volume.value * pow(cst.nmtom, 3)) / self.__moltol()
        self.volume = mt.m3mol_to_nm(v, molecules=self.__moltol())
        result = (P, )
        if get_volume: result += (vlv, )
        if get_gibbs: result += (G, )
        return result
Exemple #8
0
    def __eqpg(self, x, print_, scaler):
        '''
        Takes in ndarray to find Pressure1 - Pressure2
        '''
        P = []
        G = []
        v_ = [x[0] * scaler[0], x[1] * scaler[1]]
        for i in v_:
            self.volume = Var(mt.m3mol_to_nm(i, molecules=self.__moltol()))
            A = self.helmholtz()
            Pi = -derivative(A, self.volume, order=1) / pow(cst.nmtom, 3)
            P.append(Pi)
            G.append((A.value + Pi * self.volume.value * pow(cst.nmtom, 3)) *
                     cst.Na)

        if print_:
            print(
                f'Current: v\'s = {v_[0]:7.3e}, {v_[1]:7.3e}; dP = {(P[0]-P[1]):7.3e}, dG = {(G[0]-G[1]):7.3e}'
            )
        return np.array([(P[0] - P[1]), (G[0] - G[1])])
Exemple #9
0
    def __critpt(self, x, print_, scale):
        '''
        Takes in (v, T) to solve for dP/dV = 0 and d2P/dV2 = 0
        '''
        v_ = scale[0]
        T_ = scale[1]
        v = x[0] * v_
        T = x[1] * T_
        self.volume = Var(mt.m3mol_to_nm(v, molecules=self.__moltol()))
        self.temp = T

        A = self.helmholtz()
        dP = -np.array(derivative(A, self.volume, order=3)) / pow(cst.nmtom, 3)
        dP[1] = dP[1] / (pow(cst.nmtom, 3) * cst.Na) / (cst.R * T)
        dP[2] = dP[2] / (pow(cst.nmtom, 6) * pow(cst.Na, 2)) / (cst.R * T)
        dP[0] = dP[0] / (cst.R * T)
        if print_:
            print(
                f'Current: v = {v:7.3e}, T = {T:7.3f}: P, dP/dV, d2P/dV2 = {dP[0]:7.3e},{dP[1]:7.3e},{dP[2]:7.3e}',
                end='\r')
        dP[0] = min(dP[0], 0)
        return dP