Пример #1
0
 def setUp(self):
     self.phases = ct.import_phases('KOH.xml', [
         'K_solid', 'K_liquid', 'KOH_a', 'KOH_b', 'KOH_liquid',
         'K2O2_solid', 'K2O_solid', 'KO2_solid', 'ice', 'liquid_water',
         'KOH_plasma'
     ])
     self.mix = ct.Mixture(self.phases)
Пример #2
0
 def setUp(self):
     self._gas = ct.Solution('h2o2.yaml')
     self._carbon = ct.Solution('graphite.yaml')
     self._mix = ct.Mixture([self._gas, self._carbon])
     self._output.save(self._mix, 'foo')
     self._mix.T = 500
     self._output.save(self._mix, 'bar')
Пример #3
0
    def compute_Zst(self):

        s = self

        s.gas.TPY = s.T1, s.pres, s.y1
        mix = ct.Mixture([(s.gas, 1.0)])

        nc1 = mix.element_moles("C")
        nh1 = mix.element_moles("H")
        no1 = mix.element_moles("O")
        nn1 = mix.element_moles("N")

        nfsp = mix.species_moles
        nf = sum(nfsp)

        no2_per_nfuel = (nc1 + nh1 / 4 - no1 / 2) / nf

        n1 = 1
        n0 = no2_per_nfuel / s.x0[s.gas.species_index("O2")]
        s.gas.TPY = s.T0, s.pres, s.y0
        M0 = s.gas.mean_molecular_weight
        s.gas.TPY = s.T1, s.pres, s.y1
        M1 = s.gas.mean_molecular_weight

        s.Zst = n1 * M1 / (n0 * M0 + n1 * M1)
Пример #4
0
def doAnalysis(fuel):
    gas.set_equivalence_ratio(1.0, fuel, air)
    mix = ct.Mixture([(gas, 1.0), (carbon, 0.0)])
    mix.T = Ti
    mix.P = Pi
    mix.equilibrate('HP')
    products = mix.phase(0)
    prodx = dict(zip(products.species_names, products.X))
    fuel = fixDict(fuel)
    ox = fixDict({'N2': 3.76, 'O2': 1})
    inert = fixDict(prodx)
    dfOut = pd.DataFrame(columns=['Xf', 'Xa', 'Xi', 'phi', 'Tad', 'Flammable'])
    Xf = 0.01
    haseverburned = False
    while Xf <= 1.:
        Xa = round(1.0 - Xf, 3)
        burned = False
        while Xa >= 0:
            Xi = abs(round(1.00 - Xf - Xa, 3))
            MMIX = collections.defaultdict(lambda: 0)
            for key in gaslistfull:
                MMIX[key] = Xf * fuel[key] + Xa * ox[key] + Xi * inert[key]
            Tl, Tu = Tblend(MMIX)
            dres = Eqq(MMIX)
            if dres['phi'] > 1:
                if dres['Tad'] > Tu:
                    Flammable = 1
                    burned = True
                    haseverburned = True
                else:
                    Flammable = 0
            else:
                if dres['Tad'] > Tl:
                    Flammable = 1
                    haseverburned = True
                    burned = True
                else:
                    Flammable = 0
            dfOut = dfOut.append(
                {
                    'Xf': Xf,
                    'Xa': Xa,
                    'Xi': Xi,
                    'phi': dres['phi'],
                    'Tad': dres['Tad'],
                    'Flammable': Flammable
                },
                ignore_index=True)
            print(Xf, Xa, Xi, Flammable, dres['Tad'])
            if sum(dfOut.iloc[-2::]['Flammable']) == 0.0:
                Xa = round(Xa - 0.1, 1)
            else:
                Xa = round(Xa - 0.01, 3)
        if haseverburned and burned:
            Xf = round(Xf + 0.1, 1)
        else:
            Xf = round(Xf + 0.01, 3)
    return dfOut
Пример #5
0
    def test_properties(self):
        mix = ct.Mixture([(self.phase1, 1.0), (self.phase2, 2.0)])
        self.assertEqual(mix.nSpecies, self.phase1.nSpecies + self.phase2.nSpecies)

        mix.temperature = 350
        self.assertEqual(mix.temperature, 350)

        mix.pressure = 2e5
        self.assertEqual(mix.pressure, 2e5)
Пример #6
0
def run(initial, phases, equilibrate):
    """Function handling equilibrium calculations.

    The function handles equilibrium calculations for both single
    phases (``Solution``; single entry in *phases* argument) and multiple
    phases (``Mixture``; multiple entries in *phases* argument).

    Arguments:
        initial (Parser): Initial condition
        phases (Parser): Definition of phases
        equilibrate (Parser): Arguments of ``equilibrate`` function

    Returns:
        Cantera `Solution` or `Mixture` object
    """
    T = initial.T.m_as('kelvin')
    P = initial.P.m_as('pascal')

    # phases that will be included in the calculation, and their initial moles
    mix_phases = []
    for phase in phases.values():
        if phase is None:
            continue
        obj = ct.Solution(phase.mechanism)
        if all([key in phase
                for key in ['fuel', 'oxidizer']] + ['phi' in initial]):
            obj.TP = T, P
            obj.set_equivalence_ratio(initial.phi, phase.fuel, phase.oxidizer)
        elif 'X' in phase:
            obj.TPX = T, P, phase.X
        elif 'Y' in phase:
            obj.TPY = T, P, phase.Y
        mix_phases.append((obj, phase.get('moles')))

    # equilibrate the mixture based on configuration
    if len(mix_phases) > 1:
        obj = ct.Mixture(mix_phases)
        obj.T = T
        obj.P = P
    kwargs = equilibrate.raw
    mode = kwargs.pop('mode')
    obj.equilibrate(mode, **kwargs)

    print('Tad = {:8.2f}'.format(obj.T))

    return obj
Пример #7
0
    def solve(self, solver, **kwargs):
        n_points = 12
        T = 300
        P = 101325
        data = np.zeros((n_points, 2+self.n_species))
        phi = np.linspace(0.3, 3.5, n_points)
        for i in range(n_points):
            self.gas.set_equivalence_ratio(phi[i], self.fuel,
                                           {'O2': 1.0, 'N2': 3.76})
            mix = ct.Mixture(self.mix_phases)
            mix.T = T
            mix.P = P

            # equilibrate the mixture adiabatically at constant P
            mix.equilibrate('HP', solver=solver, max_steps=1000, **kwargs)
            data[i,:2] = (phi[i], mix.T)
            data[i,2:] = mix.species_moles

        self.compare(data, pjoin(self.test_data_dir, 'gas-carbon-equil.csv'))
Пример #8
0
    def solve(self, solver):
        n_points = 12
        T = 300
        P = 101325
        data = np.zeros((n_points, 2 + self.n_species))
        phi = np.linspace(0.3, 3.5, n_points)
        for i in range(n_points):
            X = {self.fuel: phi[i] / self.stoich, 'O2': 1.0, 'N2': 3.76}
            self.gas.TPX = T, P, X

            mix = ct.Mixture(self.mix_phases)
            mix.T = T
            mix.P = P

            # equilibrate the mixture adiabatically at constant P
            mix.equilibrate('HP', solver=solver, max_steps=1000)
            data[i, :2] = (phi[i], mix.T)
            data[i, 2:] = mix.species_moles

        self.compare(data, '../data/gas-carbon-equil.csv')
Пример #9
0
def Eq(fuel, phi):
    gas = ct.Solution('gri30.xml', 'gri30_mix')
    gas.set_equivalence_ratio(phi, fuel, air)
    mix = ct.Mixture([(gas, 1.0), (carbon, 0.0)])
    mix.T = Ti
    mix.P = Pi
    mix.equilibrate('HP')
    print(mix.T)
    Xf = 1 - sum(mix.phase(0)['N2', 'O2'].X)
    Xff = 1 - sum(mix.phase(0)['N2', 'O2', 'H2O', 'CO2'].X)
    Xair = 1 - Xf
    dResult = {
        'phi': phi,
        'Tad': mix.T,
        'Xf': Xf,
        'Xff': Xff,
        'air': Xair,
        'O2': mix.phase(0)['O2'].X
    }
    return dResult
Пример #10
0
    def get_mw(self, conv=ml2l):
        """ Initialize parameters for cantera simulation. init() calls this function"""

        mx = ct.Mixture(self.phase)
        aq = mx.phase_index(self.phase_names[0])
        org = mx.phase_index(self.phase_names[1])

        mwre = np.zeros(len(self.ree))  # molecular weight of rees
        mwslv = np.zeros(len(self.solv))  # mw & densities for 'solvents'

        for re in self.ree:
            mwre[self.ree.index(re)] = mx.phase(aq).molecular_weights[mx.phase(
                aq).species_index(re + '+++')]

        for so in self.solv:
            if so == 'H2O(L)':
                mwslv[self.solv.index(so)] = mx.phase(aq).molecular_weights[
                    mx.phase(aq).species_index(so)]
            else:
                mwslv[self.solv.index(so)] = mx.phase(org).molecular_weights[
                    mx.phase(org).species_index(so)]

        return mwre, mwslv
Пример #11
0
    def test_add_species_disabled(self):
        ref = ct.Solution('gri30.xml')

        reactor = ct.IdealGasReactor(self.phase)
        with self.assertRaises(ct.CanteraError):
            self.phase.add_species(ref.species('CH4'))
        del reactor
        gc.collect()
        self.phase.add_species(ref.species('CH4'))

        flame = ct.FreeFlame(self.phase, width=0.1)
        with self.assertRaises(ct.CanteraError):
            self.phase.add_species(ref.species('CO'))
        del flame
        gc.collect()
        self.phase.add_species(ref.species('CO'))

        mix = ct.Mixture([(self.phase, 2.0)])
        with self.assertRaises(ct.CanteraError):
            self.phase.add_species(ref.species('CH2O'))
        del mix
        gc.collect()
        self.phase.add_species(ref.species('CH2O'))
Пример #12
0
            'size': 15
        },
        'tickcolor': 'rgba(0,0,0,0)',
        'ticklen': 5,
        'showline': True,
        'showgrid': True
    }


# Setup Cantera
Pi = 101000  # Initial pressure Pa
Ti = 300  # Initial unburned gas temperature K
carbon = ct.Solution('graphite.xml')
# Calls Gas Properties from Gri-MECH
gas = ct.Solution('gri30.xml', 'gri30_mix')
mix = ct.Mixture([(gas, 1.0), (carbon, 0.0)])

fuel10Ah = {'CO2': 44, 'CO': 15, 'H2': 31, 'CH4': 6, 'C3H8': 4}
# 100 Percent Charge C
fuelSom100pct = {'CO2': 30, 'CO': 23, 'H2': 28, 'CH4': 6, 'C2H6': 1, 'C3H8': 4}
# LFP 100 SOC Golubkov 2015 Ethylene binned to Propane
fuelLFP = {
    'CO2': 48.3,
    'CO': 9.1,
    'H2': 29.4,
    'CH4': 5.4,
    'C2H6': 0.5,
    'C3H8': 7.2
}

air = {'N2': 3.76, 'O2': 1}
Пример #13
0
 def setUp(self):
     self.mix = ct.Mixture(self.phases)
Пример #14
0
 def setUp(self):
     self.mix = ct.Mixture([(self.phase1, 1.0), (self.phase2, 2.0)])
Пример #15
0
    def run(self):
        # Gas Mixtures
        air_species = self.air  # Air
        fuel_species = self.fuel
        phi = self.phi  # Composition
        f = self.f

        # Temperatures and Pressures
        Patm = self.P  # Initial Pressure
        T = self.T  # Initial unburned gas temperature K
        P1 = Patm  # Initial Pressure
        Pa = Patm  # Exit pressure outside vent
        # Tu = T  # Unburned gas temperature
        T1 = T  # Initial Temperature

        # Geometry and Vent
        R = self.R  # Radius
        Cd = self.Cd  # Coefficient for vent
        Av = self.Av  # Vent Area (m2)

        S = self.S

        # Solution Control
        tmax = self.tmax  # Max Time for analysis

        # Create Gases
        carbon = ct.Solution('graphite.xml')
        # Calls Gas Properties from Gri-MECH
        gas_b = ct.Solution('gri30.xml', 'gri30_mix')
        # Calls Gas Properties from Gri-MECH
        gas_bv = ct.Solution('gri30.xml', 'gri30_mix')
        # Calls Gas Properties from Gri-MECH
        gas_u = ct.Solution('gri30.xml', 'gri30_mix')
        mix_phases_b = [(gas_b, 1.0), (carbon, 0.0)]  # Burned Mixture
        mix_phases_u = [(gas_u, 1.0), (carbon, 0.0)]  # Unburned Mixture

        gas_b.set_equivalence_ratio(phi, fuel_species, air_species)
        gas_bv.set_equivalence_ratio(phi, fuel_species, air_species)
        gas_u.set_equivalence_ratio(phi, fuel_species, air_species)
        gas_b.TP = T, Patm
        gas_bv.TP = T, Patm
        gas_u.TP = T, Patm

        unburned = ct.Mixture(mix_phases_u)  # noqa
        burned = ct.Mixture(mix_phases_b)

        # # Calculate Laminar Flamespeed
        # CalcFlamespeed = False
        # if CalcFlamespeed:
        #     # A freely-propagating flat flame
        #     f = ct.FreeFlame(unburned, width=5)
        #     # Energy equation enabled
        #     f.energy_enabled = True
        #     f.set_max_time_step(1000)
        #     f.set_refine_criteria(ratio = 2.0, slope = 0.05, curve = 0.05)
        #     # Solve with multi or mix component transport properties
        #     f.transport_model = 'Mix'
        #     f.solve(loglevel=1,auto=True,refine_grid=True)
        #     S = f.u[0]
        # else:
        #     Xh2 = float(gas_u['H2'].X)
        #     #Laminar Burning Velocity for Hydrogen
        #     # From Liu and MacFarlane for Xh2 < 0.42
        #     A1 = 4.644E-4
        #     A2 = -2.119E-3
        #     A3 = 2.344E-3
        #     A4 = 1.571
        #     A5 = 3.839E-1
        #     A6 = -2.21
        #     xh2O = 0.0  # mol fraction of steam
        #     S = (((A1 + A2*(0.42-Xh2)+A3*(0.42-Xh2)**2) *
        #          Tu**(A4+A5*(0.42-Xh2)))*np.exp(A6*xh2O))

        # Unburned Gas Properties
        cp_aveu = gas_u.cp
        cv_aveu = gas_u.cv
        W_aveu = gas_u.mean_molecular_weight
        rou = gas_u.density

        # Burned Gas Properties
        # Chemical Equilibrium
        # equilibrate the mixture adiabatically at constant P
        burned.equilibrate('HP', solver='gibbs', max_steps=1000)
        cp_aveb = gas_b.cp  # Average Cp
        cv_aveb = gas_b.cv  # Average Cv
        W_aveb = gas_b.mean_molecular_weight  # Average Molecular wt
        rob = gas_b.density  # Average density
        Tb = burned.T
        gas_bv.equilibrate('UV')
        Pf_ = gas_bv.P / Patm

        # Ratio of specific heats for unburned gas = Cp/Cvs
        gammaU = cp_aveu / cv_aveu
        # Ratio of specific heats
        gammaB = cp_aveb / cv_aveb
        gammaE = (gammaU - 1) / (gammaB - 1)
        # gammaE=1.0

        # Initial Volume and Mass
        V1 = 4.0 / 3.0 * np.pi * R**3  # Initial Volume
        mi = rou * V1  # Initial Mass

        # print("Unburned Mol Fraction")
        # print(gas_u.species_names,'\n', gas_u.X , '\n',
        #       'Mass Fraction \n', gas_u.Y)
        # print("Burned Mol Fraction")
        # print(gas_b.species_names, '\n',gas_b.X ,'\n',
        #       'Mass Fraction \n', gas_b.Y)
        # print("S:  ",S)
        # print("Tb: ",Tb)
        # print("Pf: ",Pf_)
        # print("GammaE:", gammaE)
        # print("cp_aveb",cp_aveb)

        # start
        # initial conditions
        P_init = 1
        n3init = 1E-5 * (W_aveu / W_aveb) * (Tb / T1)
        ninit = 1E-5
        init = [P_init, n3init, ninit]
        t = np.linspace(0, tmax, 10000)

        # Solve ODE's
        x = odeint(vent_gas_explosion,
                   init,
                   t,
                   args=(P1, R, V1, gammaE, Pf_, gammaU, mi, gas_u, S, rou,
                         rob, gammaB, Cd, Av, f, T1, Pa))

        # Output
        self.P_ = x[:, 0]  # Pressure/initial pressure
        self.n3 = x[:, 1]  # Burnt gas volume
        self.n = x[:, 2]  # Ratio of burnt mass/initial mass
        self.r = R * (self.n3)**(1.0 / 3.0)  # Spherical flame radius
        self.t = t
        self.nu = 1 - self.n  # Ratio of unburned mass/initial mass
        self.mu = mi * self.nu  # Mass of unburned gas
        # Number of unburned moles
        nmu = self.mu / (gas_u.mean_molecular_weight / 1000)

        self.Vu = (1 - self.n3) * V1
        self.Tu = self.P_ * Patm * self.Vu / (nmu * RR)
        self.gas_u = gas_u
        self.gas_b = gas_b
        self.gas_bv = gas_bv
        self.Tb = Tb
        self.Pf_ = Pf_
Пример #16
0
    def areaV(self, Av1):

        #Standard Air Composition Attribute
        air_species = self.air
        #Fuel Gas Composition Passed Into Vent Object on creation
        fuel_species = self.fuel
        #Equivalence Ratio
        phi = self.phi

        # Temperatures and Pressures
        Patm = self.P  # Initial Pressure
        T = self.T  # Initial unburned gas temperature K
        P1 = Patm  # Initial Pressure
        Pa = Patm  # Exit pressure outside vent
        # Tu = T  # Unburned gas temperature
        T1 = T  # Initial Temperature

        #Geometry parameters
        L = self.L
        W = self.W
        H = self.H

        #Face Areas
        Aw1 = L * H
        Aw2 = W * H
        Aw3 = W * L

        #Total Surface Area
        As = 2 * Aw1 + 2 * Aw2 + Aw3
        #Hydraulic Diameter
        Dhe = 4 * (Aw2 / (2 * W + 2 * H))
        #Area Blockage Ratio
        Br = self.Block
        #Reduced Pressure
        P_red = self.Reduced
        Pmax = self.Adiabatic
        Po = 0.01325
        Pstat = self.Static

        #Vent Drag Coefficient
        Cd = self.Drag
        #Vent Static Activation Pressures
        P_stat = self.Static
        #Unburned Gas-Air Mixture Sonic Flow Mass Flux(kg/m^2-s)
        Gu = 230.1

        #Flame speed
        Su = self.S

        #Cantera Objects
        carbon = ct.Solution('graphite.xml')
        # Calls Gas Properties from Gri-MECH -- creates burned gas object
        gas_b = ct.Solution('gri30.xml', 'gri30_mix')
        # Calls Gas Properties from Gri-MECH -- creates unburned object
        gas_u = ct.Solution('gri30.xml', 'gri30_mix')

        mix_phases_b = [(gas_b, 1.0), (carbon, 0.0)]  # Burned Mixture
        mix_phases_u = [(gas_u, 1.0), (carbon, 0.0)]  # Unburned Mixture

        gas_b.set_equivalence_ratio(phi, fuel_species, air_species)
        gas_u.set_equivalence_ratio(phi, fuel_species, air_species)

        Pi = 101000  #Initial pressure Pa
        Ti = 300  #Initital unburned gas temperature K
        gas_b.TP = Ti, Pi
        gas_u.TP = 300, ct.one_atm

        #----------------------
        #Unburned gas-air mixture speed of sound (m/s):
        #au = self.equilSoundSpeeds(gas_u)[0]
        # save properties
        rtol = 1.0e-6
        maxiter = 8000

        gas_u.equilibrate('TP', rtol=rtol, maxiter=maxiter)

        s0 = gas_u.s
        p0 = gas_u.P
        r0 = gas_u.density

        # Perturb the pressure
        p1 = p0 * 1.0001

        # Set the gas to a state with the same entropy and composition but
        # The perturbed pressure
        gas_u.SP = s0, p1

        # Now equilibrate the gas holding S and P constant
        gas_u.equilibrate('SP', rtol=rtol, maxiter=maxiter)

        ptest = p1 - p0
        ztest = gas_u.density - r0
        dtest = ptest / ztest
        debub = {
            'r0': r0,
            'density': gas_u.density,
            'bottom': ztest,
            'top': ptest,
            'div': dtest
        }
        # Equilibrium sound speed
        aequil = math.sqrt((p1 - p0) / (gas_u.density - r0))
        #print('executed')
        au = aequil
        #--------

        rho_u = gas_b.density
        mu_u = gas_b.viscosity

        unburned = ct.Mixture(mix_phases_u)  # noqa
        burned = ct.Mixture(mix_phases_b)

        burned.equilibrate('HP', solver='gibbs', max_steps=1000)
        gamma_b = gas_b.cp / gas_b.cv

        #------------VENT AREA FUNCTION FROM AUSTIN'S SCRIPT-------------------
        Dv = math.sqrt((Av1 / self.Number))

        #Reynolds number of flame through structure:
        Re_flame = rho_u * Su * (0.5 * Dhe) / mu_u
        #Phi 1: Based on Reynolds Number of Flame Front:
        phi_1 = max(1, (Re_flame / 4000)**0.39)

        #Maximum Velocity through Vent (m/s):
        uv = min(math.sqrt(P_red * 2 * 10**5 / rho_u), au)

        #Reynolds number through vent
        Re_vent = 0.5 * rho_u * uv * Dv / mu_u

        #Phi 2: Based on Reynolds Number through Vent:
        beta1 = 1.23
        beta2 = 2.37 * 10**-3
        phi_2 = max(1, beta1 * (Re_vent / 10**6)**((beta2 / Su)**0.5))

        #Lambda 0:
        Lambda_0 = phi_1 * phi_2

        #Lambda 1 Based on Obstructed surface area (m^2):
        Aobs = 0.3 * As

        #Obstruction Correction Factor
        if Aobs < 0.2 * As:
            Lambda_1 = Lambda_0
        elif Aobs >= 0.2 * As:
            Lambda_1 = Lambda_0 * math.exp(math.sqrt((Aobs / As) - 0.2))

        #L/D
        L_D = L / Dhe

        #Solving for Lambda:
        if L_D < 2.5:
            Lambda = Lambda_1
        elif L_D >= 2.5:
            Lambda = Lambda_1 * (1 + ((L_D / 2.5) - 1)**2)

        # #L/D Correction Factor
        # if L_D > 5:
        #     print ("L/D Above 5 see NFPA 68 Chapter 9")
        # elif Pmax > 10:
        #     print ("Pmax Above 10 bar-g see NFPA 68")

        #Solving for vent size:
        C = (0.5 * Su * rho_u * Lambda /
             (Gu * Cd)) * (((Pmax + 1) /
                            (Po + 1))**(1 / gamma_b) - 1) * (Po + 1)**0.5
        delta = (((Pstat + 1) / (Po + 1))**(1 / gamma_b) - 1) / ((
            (Pmax + 1) / (Po + 1))**(1 / gamma_b) - 1)

        #Pred Corrction Factor
        if P_red <= 0.5:
            Avo = As * C / math.sqrt(P_red)
        elif P_red > 0.5:
            Avo = (As * Su * rho_u * Lambda /
                   (Gu * Cd)) * (1 - ((P_red + 1) /
                                      (Pmax + 1))**(1 / gamma_b)) / (
                                          ((P_red + 1) /
                                           (Pmax + 1))**(1 / gamma_b) - delta)
        return (Avo)
#Unburned gas-air mixture speed of sound (m/s):
au = equilSoundSpeeds(gas)[0]

#Burned Mixture
Pi = 101000  #Initial pressure Pa
Ti = 300  #Initial unburned gas temperature K
gas_b.TP = Ti, Pi

#Mass Density of Unburned Gas-Air Mixture (kg/m^3):
rho_u = gas_b.density

#Unburned gas-air mixture dynamic viscosity (kg/m-s):
mu_u = gas_b.viscosity

#Suppress the next two lines for unburned data
burned = ct.Mixture(mix_phases_b)

#Equilibrate the mixture adiabatically at constant P
burned.equilibrate('HP', solver='gibbs', max_steps=1000)
gamma_b = gas_b.cp / gas_b.cv  #Suppress for unburned data

#Structure Surface Area (m^2):

#Length (m):
L = 24.4

#Depth (m):
D = 30.5

#Height (m):
H = 6.1
Пример #18
0
    def set_in_moles(self, feed_vol):
        """Function that initializes mole fractions to input feed_vol

                This function is called at initialization

                Sets in_moles to a pd.DataFrame containing initial mole fractions

                Columns for species and rows for different experiments

                This function also calls update_predicted_dict

                :param feed_vol: (float) feed volume of mixture (L)
                """
        phases_copy = self._phases.copy()
        exp_df = self._exp_df.copy()
        solvent_name = self._aq_solvent_name
        extractant_name = self._extractant_name
        diluant_name = self._diluant_name
        solvent_rho = self._aq_solvent_rho
        extractant_rho = self._extractant_rho
        diluant_rho = self._diluant_rho
        extracted_species_names = self._extracted_species_ion_names
        extracted_species_list = self._extracted_species_list

        mixed = ct.Mixture(phases_copy)
        aq_ind = None
        solvent_ind = None
        for ind, phase in enumerate(phases_copy):
            if solvent_name in phase.species_names:
                aq_ind = ind
                solvent_ind = phase.species_names.index(solvent_name)
        if aq_ind is None:
            raise Exception('Solvent "{0}" not found \
                                        in xml file'.format(solvent_name))

        if aq_ind == 0:
            org_ind = 1
        else:
            org_ind = 0
        self._aq_ind = aq_ind
        self._org_ind = org_ind
        extractant_ind = phases_copy[org_ind].species_names.index(
            extractant_name)
        diluant_ind = phases_copy[org_ind].species_names.index(diluant_name)

        extracted_species_ind_list = [
            phases_copy[aq_ind].species_names.index(extracted_species_name)
            for extracted_species_name in extracted_species_names
        ]
        extracted_species_charges = np.array([
            phases_copy[aq_ind].species(extracted_species_ind).charge
            for extracted_species_ind in extracted_species_ind_list
        ])
        self._extracted_species_charges = extracted_species_charges

        mix_aq = mixed.phase(aq_ind)
        mix_org = mixed.phase(org_ind)
        solvent_mw = mix_aq.molecular_weights[solvent_ind]  # g/mol
        extractant_mw = mix_org.molecular_weights[extractant_ind]
        diluant_mw = mix_org.molecular_weights[diluant_ind]
        if solvent_rho is None:
            solvent_rho = mix_aq(aq_ind).partial_molar_volumes[
                solvent_ind] / solvent_mw * 1e6  # g/L
            self._aq_solvent_rho = solvent_rho
        if extractant_rho is None:
            extractant_rho = mix_org(org_ind).partial_molar_volumes[
                extractant_ind] / extractant_mw * 1e6
            self._extractant_rho = extractant_rho
        if diluant_rho is None:
            diluant_rho = mix_org(org_ind).partial_molar_volumes[
                extractant_ind] / extractant_mw * 1e6
            self._diluant_rho = diluant_rho

        in_moles_data = []
        aq_phase_solvent_moles = feed_vol * solvent_rho / solvent_mw
        for index, row in exp_df.iterrows():
            h_plus_moles = feed_vol * row['h_i']
            hydroxide_ions = 0
            extracted_species_moles = np.array([
                feed_vol * row['{0}_aq_i'.format(extracted_species)]
                for extracted_species in extracted_species_list
            ])
            extracted_species_charge_sum = np.sum(extracted_species_charges *
                                                  extracted_species_moles)
            chlorine_moles = extracted_species_charge_sum + h_plus_moles
            extractant_moles = feed_vol * row['z_i']
            extractant_vol = extractant_moles * extractant_mw / extractant_rho
            diluant_vol = feed_vol - extractant_vol
            diluant_moles = diluant_vol * diluant_rho / diluant_mw
            complex_moles = np.zeros(len(extracted_species_list))

            species_moles_aq = [
                aq_phase_solvent_moles, h_plus_moles, hydroxide_ions,
                chlorine_moles
            ]
            species_moles_aq.extend(list(extracted_species_moles))
            species_moles_aq.append(self.nacl_molarity * feed_vol)
            species_moles_aq[3] += self.nacl_molarity * feed_vol
            species_moles_org = [extractant_moles, diluant_moles]
            species_moles_org.extend(list(complex_moles))
            if aq_ind == 0:
                species_moles = species_moles_aq + species_moles_org
            else:
                species_moles = species_moles_org + species_moles_aq
            in_moles_data.append(species_moles)

        self._in_moles = pd.DataFrame(in_moles_data,
                                      columns=mixed.species_names)
        self.update_predicted_dict()
        return None
Пример #19
0
 def test_invalid_phase_type(self):
     water = ct.Water()
     with self.assertRaisesRegex(ct.CanteraError, 'not compatible'):
         self.mix = ct.Mixture([(self.phase1, 1.0), (water, 2.0)])
Пример #20
0
"""

import cantera as ct
import csv

# create objects representing the gas phase and the condensed phases. The gas
# is a mixture of multiple species, and the condensed phases are all modeled
# as incompressible stoichiometric substances. See file KOH.yaml for more
# information.
phases = ct.import_phases('KOH.yaml', [
    'K_solid', 'K_liquid', 'KOH_a', 'KOH_b', 'KOH_liquid', 'K2O2_solid',
    'K2O_solid', 'KO2_solid', 'ice', 'liquid_water', 'KOH_plasma'
])

# create the Mixture object from the list of phases
mix = ct.Mixture(phases)
equil_data = []

# loop over temperature
for n in range(100):
    t = 350.0 + 50.0 * n
    print('T = {0}'.format(t))
    mix.T = t
    mix.P = ct.one_atm
    mix.species_moles = "K:1.03, H2:2.12, O2:0.9"

    # set the mixture to a state of chemical equilibrium holding
    # temperature and pressure fixed
    # mix.equilibrate("TP",maxsteps=10000,loglevel=1)
    mix.equilibrate("TP", max_steps=10000, log_level=0)
Пример #21
0
 def test_invalid_phase_type(self):
     water = ct.Water()
     with self.assertRaises(ct.CanteraError):
         self.mix = ct.Mixture([(self.phase1, 1.0), (water, 2.0)])
Пример #22
0
'''
import cantera as ct

mix = ct.Solution('liquidvapor.cti')
#initial_temp,initial_press =[float(val) for val in input().split()]
mix.TPX = 300,ct.one_atm,'H2O:1'

mix.equilibrate('HP')

print(mix.P_sat/ct.one_atm)
'''
import cantera as ct

liquid = ct.Solution('water.cti', 'liquid_water')
solid = ct.Solution('water.cti', 'ice')
gas = ct.Solution('h2o2.cti')

for T in [280, 400]:
    gas.TPX = 300, 101325, 'AR:1.0, H2O:0.0'
    mix = ct.Mixture([(gas, 0.01), (liquid, 0.99), (solid, 0.0)])
    mix.T = T
    mix.P = 101325
    mix.equilibrate('TV', solver='gibbs')
    print(gas['H2O'].X * mix.P)
    print('T = {}'.format(T))
    #mix()
Пример #23
0
import numpy as np

#==============================================================================
# set parameters
#==============================================================================
To = 298.195 # K (reference temperature)
R = ct.gas_constant # 8314.47215 Pa*m^3/K/kmol

#==============================================================================
# load components to phases
#==============================================================================
s = ct.Solution('data/min-species.xml','solid')
g = ct.Solution('data/min-species.xml','gas')
#print s.species_names
air = ct.Solution('data/air.cti','air')
f = ct.Mixture([(s,1),(g,1)])
# preallocate variable
nsp = f.n_species

#==============================================================================
# get standard state properties
#==============================================================================
# molecular weight
Mw_s = s.molecular_weights
Mw_g = g.molecular_weights
Mw = np.concatenate((Mw_s, Mw_g))
# standard enthalpy of formation
Hfo_s = s.standard_enthalpies_RT*To*R
Hfo_g = g.standard_enthalpies_RT*To*R
Hfo = np.concatenate((Hfo_s, Hfo_g))
## find important indices
Пример #24
0
    def __init__(self,
                 config_file,
                 prep_capex=0,
                 prep_opex=0,
                 prep_revenue=0,
                 prep_npv=0):
        """Constructor.
        """

        self.confDict = utilities.read_config(config_file)
        solventxHome = self.confDict["solventxHome"]
        reeComps = self.confDict['compositions']
        self.xmlData = self.confDict['xmlData']
        self.modulesData = self.confDict['modules']

        self.xml = os.path.join(
            solventxHome, self.xmlData['xml'], self.xmlData['phase'] + '_' +
            ''.join(self.modulesData["input"]) + '.xml')

        # Set required data

        self.phase_names = self.confDict["phasenames"]  # from xml input file
        self.phase = ct.import_phases(self.xml, self.phase_names)

        # Derived and/or reusable system parameters
        self.column = self.coltypes  # Column name
        self.solv = self.confDict[
            "solvents"]  # solvent list -.i.e., electrolyte, extractant and organic diluent

        # ree by modules
        self.ree = self.modulesData[
            "input"]  #self.REEs[self.moduleID] # (rare earth) metal list

        # Cantera indices
        self.mix = ct.Mixture(self.phase)
        self.aq = self.mix.phase_index(self.phase_names[0])
        self.org = self.mix.phase_index(self.phase_names[1])
        self.ns = self.mix.n_species
        self.naq = self.mix.phase(self.aq).n_species
        self.norg = self.mix.phase(self.org).n_species

        self.HA_Index = self.mix.species_index(
            self.org,
            '(HA)2(org)')  # index of extractant in canera species list
        self.Hp_Index = self.mix.species_index(
            self.aq, 'H+')  # index of H+ in cantera species list
        self.Cl_Index = self.mix.species_index(
            self.aq, 'Cl-')  # index of Cl in cantera species list

        self.canteranames = self.mix.species_names
        self.fixed_species = ['H2O(L)', 'OH-', 'Cl-', 'dodecane']
        self.canteravars = [
            ij for ij in self.canteranames if ij not in self.fixed_species
        ]  # 'Cl-',

        self.nsy = len(self.canteravars)
        self.naqy = len([
            ij for ij in self.mix.species_names[:self.naq]
            if ij not in self.fixed_species
        ])
        self.norgy = len([
            ij for ij in self.mix.species_names[self.naq:]
            if ij not in self.fixed_species
        ])

        self.mwre,\
        self.mwslv          = self.get_mw() # g/mol
        self.rhoslv = [1000, 960, 750]  # [g/L]

        self.upper = [reeComps[i]['upper'] for i in self.ree]
        self.lower = [reeComps[i]['lower'] for i in self.ree]
        ree_mass = [
            np.random.uniform(i, j) for i, j in zip(self.lower, self.upper)
        ]
        self.get_conc(ree_mass)

        self.purity_spec = .99  # not needed?
        self.recov_spec = .99  # not needed?

        self.revenue = [0, 0, 0]
        self.Ns = [0, 0, 0]

        self.nsp = pd.DataFrame()  # feed streams (aq and org) for each column
        self.nsp0 = pd.DataFrame()  # feed streams (aq and org) for each column

        self.y = {}  # all compositions
        self.Ns = {}
# phases
# complete_species = [species[S] for S in ('CH4','O2','N2','CO2','H2O')]
# gas = ct.Solution(thermo='IdealGas', species=complete_species)
gas = ct.Solution('r_creck_52.cti')
carbon = ct.Solution('graphite.xml')

# the phases that will be included in the calculation, and their initial moles
mix_phases = [(gas, 1.0), (carbon, 0.0)]

# gaseous fuel species
fuel_species = 'CH4'

##############################################################################

mix = ct.Mixture(mix_phases)

# create some arrays to hold the data
phi = 0.7

# find fuel, nitrogen, and oxygen indices
ifuel = gas.species_index(fuel_species)
io2 = gas.species_index('O2')
in2 = gas.species_index('N2')

stoich_O2 = gas.n_atoms(fuel_species,
                        'C') + 0.25 * gas.n_atoms(fuel_species, 'H')

X = np.zeros(gas.n_species)
X[ifuel] = phi
X[io2] = stoich_O2
Пример #26
0
 def test_invalid_phase_type(self):
     water = ct.Water()
     with self.assertRaises(Exception):
         self.mix = ct.Mixture([(self.phase1, 1.0), (water, 2.0)])