if __name__ == '__main__': # build a test mechanism with inert oxygen base_mech = 'gri30' test_mech = 'test_mech' file_types = ['.cti', '.xml'] funcs = [make_inert_cti, make_inert_xml] inert_species = ['O2'] init_temp = 1000 init_press = ct.one_atm for ftype, func in zip(file_types, funcs): mechs = [base_mech + ftype, test_mech + ftype] _, _, file_out = _get_file_locations(mechs[0], mechs[1]) func(mechs[0], inert_species, mechs[1]) gases = [ct.Solution(m) for m in mechs] for idx, g in enumerate(gases): g.set_equivalence_ratio(1, 'H2', 'O2') init_mf = g.mole_fraction_dict()['O2'] g.TP = init_temp, init_press r = ct.Reactor(g) n = ct.ReactorNet([r]) n.advance_to_steady_state() print(mechs[idx]) print('-' * len(mechs[idx])) print('# reactions: {:1.0f}'.format(len( g.reaction_equations()))) print('final temp: {:1.0f} K'.format(r.thermo.TP[0])) print('final pressure: {:1.0f} atm'.format(r.thermo.TP[1] / ct.one_atm)) print('Y_02 init/final: {:0.3f} / {:0.3f}'.format(
) parser.add_argument( "--yields", nargs='+', type=int, required=False, default=[-1], dest='yields', help= 'Indices of concentration yields to include in error. -1 for none. Default -1.' ) args = parser.parse_args() start = timeit.default_timer() gas = ct.Solution(args.mechanism) reactions = gas.reactions() Npoints = args.Npoints filebase = args.filebase ns = gas.n_total_species nr = gas.n_reactions expfile = open(args.experiments, 'r') measure_ind = args.measure sensitivity = args.sensitivity num_remove = args.remove num_exclude = args.retain maxes = args.maxes yields = args.yields seed = 1000 * 1000 * num_exclude + 1000 * num_remove + args.seed ktol = args.ktol outflag = args.out
def run_drgep(model_file, importance_coeffs, ignition_conditions, psr_conditions, flame_conditions, error_limit, species_targets, species_safe, phase_name='', threshold_upper=None, num_threads=1, path=''): """Main function for running DRGEP reduction. Parameters ---------- model_file : str Original model file ignition_conditions : list of InputIgnition List of autoignition initial conditions. psr_conditions : list of InputPSR List of PSR simulation conditions. flame_conditions : list of InputLaminarFlame List of laminar flame simulation conditions. error_limit : float Maximum allowable error level for reduced model species_targets : list of str List of target species names species_safe : list of str List of species names to always be retained phase_name : str, optional Optional name for phase to load from CTI file (e.g., 'gas'). threshold_upper : float, optional Upper threshold (epsilon^*) to identify limbo species for sensitivity analysis num_threads : int, optional Number of CPU threads to use for performing simulations in parallel. Optional; default = 1, in which the multiprocessing module is not used. If 0, then use the available number of cores minus one. Otherwise, use the specified number of threads. path : str, optional Optional path for writing files Returns ------- ReducedModel Return reduced model and associated metadata """ solution = ct.Solution(model_file, phase_name) assert species_targets, 'Need to specify at least one target species.' # first, sample thermochemical data and generate metrics for measuring error # (e.g, ignition delays). Also produce adjacency matrices for graphs, which # will be used to produce graphs for any threshold value. sampled_metrics, sampled_data = drgep.sample(model_file, ignition_conditions, phase_name=phase_name, num_threads=num_threads, path=path) matrices = [] for state in sampled_data: matrices.append( drgep.create_drgep_matrix((state[0], state[1], state[2:]), solution)) # For DRGEP, find the overall interaction coefficients for all species # using the maximum over all the sampled states # importance_coeffs = drgep.get_importance_coeffs( # solution.species_names, species_targets, matrices # ) # begin reduction iterations logging.info('Beginning reduction loop') logging.info(45 * '-') logging.info('Threshold | Number of species | Max error (%)') # make lists to store data threshold_data = [] num_species_data = [] error_data = [] # start with detailed (starting) model previous_model = reduce_model.ReducedModel(model=solution, filename=model_file, error=0.0) first = True error_current = 0.0 threshold = 0.01 threshold_increment = 0.01 while error_current <= error_limit: reduced_model = reduce_drgep(model_file, species_safe, threshold, importance_coeffs, ignition_conditions, sampled_metrics, phase_name=phase_name, previous_model=previous_model, num_threads=num_threads, path=path) error_current = reduced_model.error num_species = reduced_model.model.n_species # reduce threshold if past error limit on first iteration if first and error_current > error_limit: error_current = 0.0 threshold /= 10 threshold_increment /= 10 if threshold <= 1e-6: raise SystemExit( 'Threshold value dropped below 1e-6 without producing viable reduced model' ) logging.info('Threshold value too high, reducing by factor of 10') continue logging.info( f'{threshold:^9.2e} | {num_species:^17} | {error_current:^.2f}') # store data threshold_data.append(threshold) num_species_data.append(num_species) error_data.append(error_current) threshold += threshold_increment first = False # cleanup files if previous_model.model.n_species != reduced_model.model.n_species: os.remove(reduced_model.filename) previous_model = reduce_model.ReducedModel( model=reduced_model.model, filename=reduced_model.filename, error=reduced_model.error, limbo_species=reduced_model.limbo_species) if reduced_model.error > error_limit: threshold -= (2 * threshold_increment) reduced_model = reduce_drgep(model_file, species_safe, threshold, importance_coeffs, ignition_conditions, sampled_metrics, phase_name=phase_name, num_threads=num_threads, path=path) else: soln2cti.write(reduced_model, f'reduced_{reduced_model.model.n_species}.cti', path=path) if threshold_upper: for sp in reduced_model.model.species_names: if importance_coeffs[sp] < threshold_upper and ( sp not in species_safe): reduced_model.limbo_species.append(sp) logging.info(45 * '-') logging.info('Reduction complete.') logging.info( f'Skeletal model: {reduced_model.model.n_species} species and ' f'{reduced_model.model.n_reactions} reactions.') logging.info(f'Maximum error: {reduced_model.error:.2f}%') logging.info('Final reduced model saved as ' + reduced_model.filename) return threshold_data, num_species_data, error_data
# set the gas to a state with the same entropy and composition but # the perturbed pressure gas.SP = s0, p1 # frozen sound speed afrozen = math.sqrt((p1 - p0) / (gas.density - r0)) # now equilibrate the gas holding S and P constant gas.equilibrate('SP', rtol=rtol, maxiter=maxiter) # equilibrium sound speed aequil = math.sqrt((p1 - p0) / (gas.density - r0)) # compute the frozen sound speed using the ideal gas expression as a check gamma = gas.cp / gas.cv afrozen2 = math.sqrt(gamma * ct.gas_constant * gas.T / gas.mean_molecular_weight) return aequil, afrozen, afrozen2 # test program if __name__ == "__main__": gas = ct.Solution('gri30.yaml') gas.X = 'CH4:1.00, O2:2.0, N2:7.52' for n in range(27): T = 300.0 + 100.0 * n gas.TP = T, ct.one_atm print(T, equilSoundSpeeds(gas))
get_ipython().run_line_magic('matplotlib', 'inline') import sys import os import math import csv import numpy as np import cantera as ct #combustion chamber volume and mass flows assesment based on the dimensions of Rolls Royce AE3007 lambda_air = 1.5 #air–fuel equivalence ratio air = ct.Solution('air.cti') air.TP = 800, 1.4e+06 #typical temperature and pressure behind HPC air_in=ct.Reservoir(air) air_mdot=ct.Quantity(air, mass=20) fuel = ct.Solution('Dagaut_Ori.cti') fuel.TPY = 300, 3e+05, 'NC10H22:0.74,PHC3H7:0.15,CYC9H18:0.11' fuel_in=ct.Reservoir(fuel) fuel_mdot = ct.Quantity(fuel, mass=1) fuel_mdot.mass=air_mdot.mass/lambda_air/14.9 #igniter (like in "combustor.py") fuel.TPX = 1500, 2e+06, 'H:1.0' igniter = ct.Reservoir(fuel) fuel.TPX = 1100, 1.2e+6, 'N2:1.0' #combustion chamber already hot, otherwise some mechanims doesn't integrate properly when combustor temperature is below 1000 K
# composition of the inlet premixed gas for the methane/air case comp2 = 'CH4:0.095, O2:0.21, N2:0.78, AR:0.01' # The inlet/surface separation is 10 cm. width = 0.1 # m loglevel = 1 # amount of diagnostic output (0 to 5) ################ create the gas object ######################## # # This object will be used to evaluate all thermodynamic, kinetic, and # transport properties. The gas phase will be taken from the definition of # phase 'gas' in input file 'ptcombust.cti,' which is a stripped-down version # of GRI-Mech 3.0. gas = ct.Solution('ptcombust.cti', 'gas') gas.TPX = tinlet, p, comp1 ################ create the interface object ################## # # This object will be used to evaluate all surface chemical production rates. # It will be created from the interface definition 'Pt_surf' in input file # 'ptcombust.cti,' which implements the reaction mechanism of Deutschmann et # al., 1995 for catalytic combustion on platinum. # surf_phase = ct.Interface('ptcombust.cti', 'Pt_surf', [gas]) surf_phase.TP = tsurf, p # integrate the coverage equations in time for 1 s, holding the gas # composition fixed to generate a good starting estimate for the coverages. surf_phase.advance_coverages(1.0)
def f4(ER_,T_0=300,P_=1,alpha_= 0,beta_ = 0): gas_new = ct.Solution('gri30.cti') gas_new.TPX = T_0,P_*ct.one_atm,'H2:%f, O2:1, N2:3.76, H2O:%f, CO:%f'%(2.*ER_,alpha_,beta_) gas_new.equilibrate('HP') return float(gas_new.T)
start = time.time() #### Input mechanism data ####: input_file0 = 'ethanol_pt.cti' input_file = 'ethanol_pt_redux.cti' surf_name = 'Pt_surface' #### Data files path ####: basepath = os.path.dirname(__file__) filepath = os.path.join(basepath, '../..', 'data') #### Coverage dependency matrix file ####: cov_file = os.path.join(filepath, 'cov_matrix/covmatrix_et_pt.inp') #Load phases solution objects gas0 = ct.Solution(input_file0) surfCT0 = ct.Interface(input_file0, surf_name, [gas0]) #Load in-house surface phase object surf0 = pfr.SurfacePhase(gas0, surfCT0, cov_file=cov_file) #Load phases solution objects for reduced mechanism gas = ct.Solution(input_file) surfCT = ct.Interface(input_file, surf_name, [gas]) #Load in-house surface phase object surf = pfr.SurfacePhase(gas, surfCT, cov_file=cov_file) #### Current thermo state ####: X_in = 'CH3CH2OH:0.125, H2O:0.375, HE:0.50' T_in = 668
return soln, fullArrayFlowData, PdropTotal / 1e6 #%% if __name__ == '__main__': mdot = 0.3 #mass flow rate [kg/s] T0 = 300 # #ambient temperature [K]/stagnation stag = T0 P1 = psi_to_MPa( 1500 ) * 1e6 #(100/145.038)*1e6#MPa #pressure at pipe inlet [Pa] 1500 PSI PInit = P1 #define gas gas = ct.Solution('air.cti') gas.transport_model = 'Mix' gas.TPX = T0, P1, {'O2': 1, 'N2': 3.76} R = 8.314 gamma = gas.cp / gas.cv #ratio of specific heats [-] MW = gas.mean_molecular_weight step = 0.001 #(m) break tube up into 1mm increments #for loss calculations https://docs.google.com/spreadsheets/d/1gn8gLvc1uLY0blPmABOoTxjrHLD8UaT0t1OvKjpqaj4/edit#gid=0 #Minor/Major Loss calculations: #https://docs.google.com/spreadsheets/d/1gn8gLvc1uLY0blPmABOoTxjrHLD8UaT0t1OvKjpqaj4/edit#gid=89965144 Kvec = [0.75, 0.00001006424457, 0.2, 1.816115216, 7.5, 0.5, 3.30000078] Lvec = [1e-16, 1e-16, 1.2192, 0.5461, 1.5367, 1.2192, 0.0635] Dvec = [ 0.004572, 0.009398, 0.008636, 0.009398, 0.009398, 0.008636, 0.009398 ] epsvec = [
# -*- coding: utf-8 -*- """ Created on Fri Feb 02 13:01:11 2018 @author: Mark Barbet """ import os import cantera as ct import numpy as np import matplotlib.pyplot as plt import troe_rate as tr gas = ct.Solution(os.getcwd() + '\\TMRP codes\\FFCM-1\\h_c2h2') kp = [] kcalc = [] pressures = np.arange(0.0001 * ct.one_atm, 100000 * ct.one_atm, 50000) pressures = np.arange(0.00001, 100000 * ct.one_atm, 50000) high_rate = gas.reactions()[0].high_rate.pre_exponential_factor * ( 1000**gas.reactions()[0].high_rate.temperature_exponent) * np.exp( -gas.reactions()[0].high_rate.activation_energy / 1000.0 / ct.gas_constant) low_rate = gas.reactions()[0].low_rate.pre_exponential_factor * ( 1000**gas.reactions()[0].low_rate.temperature_exponent) * np.exp( gas.reactions()[0].low_rate.activation_energy / 1000.0 / ct.gas_constant) for i in np.arange(len(pressures)): gas.TP = 1000.0, pressures[i] kp.append(gas.forward_rate_constants[0]) kcalc.append( tr.rate(low_rate, high_rate, 0.215, 10.7, 1043.0, 2341.0, 1000.0,
Windows 8.1, Windows 10, Linux (Debian 9) """ import cantera as ct from sdtoolbox.thermo import soundspeed_fr, soundspeed_eq from sdtoolbox.postshock import CJspeed, PostShock_eq ## set initial state, composition, and gas object P1 = 100000. T1 = 300. #q = 'H2:2.00 O2:1.0 N2:3.76' #q = 'C2H4:1.00 O2:3 N2:11.28' q = 'C2H2:1 O2:2.5 AR:3' #q = 'C2H4:1. O2:3' #q = 'O2:1. N2:3.76' mech = 'gri30_highT.cti' gas1 = ct.Solution(mech) gas1.TPX = T1, P1, q ## Evaluate initial state R1 = gas1.density c1_fr = soundspeed_fr(gas1) cp1 = gas1.cp_mass w1 = gas1.mean_molecular_weight gamma1_fr = c1_fr**2 * R1 / P1 ## Set shock speed cj_speed = CJspeed(P1, T1, q, mech) Us = cj_speed ## Evaluate gas state # q = 'O2:1. N2:3.76'
@author: dkorff This is the object initialization file for the Li-s model. It imports input values from li_s_battery_inputs.py and initializes the necessary objects to run the simulations """ import numpy as np import cantera as ct import importlib from math import pi from li_s_battery_inputs import inputs "Import cantera objects - this step is the same regardless of test type" elyte_obj = ct.Solution(inputs.ctifile, inputs.elyte_phase) sulfur_obj = ct.Solution(inputs.ctifile, inputs.cat_phase1) Li2S_obj = ct.Solution(inputs.ctifile, inputs.cat_phase2) carbon_obj = ct.Solution(inputs.ctifile, inputs.cat_phase3) conductor_obj = ct.Solution(inputs.ctifile, inputs.metal_phase) lithium_obj = ct.Solution(inputs.ctifile, inputs.an_phase) sulfur_el_s = ct.Interface(inputs.ctifile, inputs.sulfur_elyte_phase, [sulfur_obj, elyte_obj, conductor_obj]) Li2S_el_s = ct.Interface(inputs.ctifile, inputs.Li2S_elyte_phase, [Li2S_obj, elyte_obj, conductor_obj]) carbon_el_s = ct.Interface(inputs.ctifile, inputs.graphite_elyte_phase, [carbon_obj, elyte_obj, conductor_obj]) lithium_el_s = ct.Interface(inputs.ctifile, inputs.anode_elyte_phase, [lithium_obj, elyte_obj, conductor_obj]) Li2S_tpb = ct.Interface(inputs.ctifile, 'tpb', [elyte_obj, Li2S_obj, conductor_obj])
class FlameExtinguished(Exception): pass # Create directory for output data files data_directory = 'diffusion_flame_batch_data/' if not os.path.exists(data_directory): os.makedirs(data_directory) # PART 1: INITIALIZATION # Set up an initial hydrogen-oxygen counterflow flame at 1 bar and low strain # rate (maximum axial velocity gradient = 2414 1/s) reaction_mechanism = 'h2o2.yaml' gas = ct.Solution(reaction_mechanism) width = 18e-3 # 18mm wide f = ct.CounterflowDiffusionFlame(gas, width=width) # Define the operating pressure and boundary conditions f.P = 1.e5 # 1 bar f.fuel_inlet.mdot = 0.5 # kg/m^2/s f.fuel_inlet.X = 'H2:1' f.fuel_inlet.T = 300 # K f.oxidizer_inlet.mdot = 3.0 # kg/m^2/s f.oxidizer_inlet.X = 'O2:1' f.oxidizer_inlet.T = 300 # K # Set refinement parameters, if used f.set_refine_criteria(ratio=3.0, slope=0.1, curve=0.2, prune=0.03)
def cj_speed( cls, initial_pressure, initial_temperature, species_mole_fractions, mechanism, use_multiprocessing=False, return_r_squared=False, return_state=False ): """ This function calculates CJ detonation velocity Original function: CJspeed in PostShock.py Parameters ---------- initial_pressure : float initial pressure (Pa) initial_temperature : float initial temperature (K) species_mole_fractions : str or dict string or dictionary of reactant species mole fractions mechanism : str cti file containing mechanism data (e.g. 'gri30.cti') use_multiprocessing : bool use multiprocessing to speed up CJ speed calculation return_r_squared : bool return the R^2 value of the CJ speed vs. density ratio fit return_state : bool return the CJ state corresponding to the calculated velocity Returns ------- dict """ # DECLARATIONS num_steps = 20 max_density_ratio = 2.0 min_density_ratio = 1.5 a = 0 b = 0 c = 0 if use_multiprocessing: pool = mp.Pool() # Set error tolerances for CJ state calculation error_tol_temperature = 1e-4 error_tol_velocity = 1e-4 counter = 1 r_squared = 0.0 delta_r_squared = 0.0 adjusted_density_ratio = 0.0 while (counter <= 4) and ( (r_squared < 0.99999) or (delta_r_squared < 1e-7) ): density_ratio_array = np.linspace( min_density_ratio, max_density_ratio, num_steps + 1 ) if use_multiprocessing: # parallel loop through density ratios stargs = [[number, ratio, initial_temperature, initial_pressure, species_mole_fractions, mechanism, error_tol_temperature, error_tol_velocity ] for number, ratio in zip( range(len(density_ratio_array)), density_ratio_array ) ] # noinspection PyUnboundLocalVariable result = pool.starmap(cls._calculate_over_ratio_range, stargs) else: # no multiprocessing, just use map result = list(map( cls._calculate_over_ratio_range, [item for item in range(len(density_ratio_array))], density_ratio_array, [initial_temperature for _ in density_ratio_array], [initial_pressure for _ in density_ratio_array], [species_mole_fractions for _ in density_ratio_array], [mechanism for _ in density_ratio_array], [error_tol_temperature for _ in density_ratio_array], [error_tol_velocity for _ in density_ratio_array] )) result.sort() cj_velocity_calculations = np.array( [item for (_, item) in result] ) # Get curve fit a, b, c, r_squared = cj_curve_fit( density_ratio_array, cj_velocity_calculations ) adjusted_density_ratio = -b / (2. * a) min_density_ratio = adjusted_density_ratio * (1 - 0.001) max_density_ratio = adjusted_density_ratio * (1 + 0.001) counter += 1 cj_speed = a * adjusted_density_ratio**2 + \ b * adjusted_density_ratio + c if return_state: initial_state_gas = ct.Solution(mechanism) working_gas = ct.Solution(mechanism) initial_state_gas.TPX = [ initial_temperature, initial_pressure, species_mole_fractions ] working_gas.TPX = [ initial_temperature, initial_pressure, species_mole_fractions ] cls.cj_state( working_gas, initial_state_gas, error_tol_temperature, error_tol_velocity, adjusted_density_ratio ) if return_r_squared and return_state: # noinspection PyUnboundLocalVariable return {'cj speed': cj_speed, 'R^2': r_squared, 'cj state': working_gas } elif return_state: # noinspection PyUnboundLocalVariable return {'cj speed': cj_speed, 'cj state': working_gas } elif return_r_squared: return {'cj speed': cj_speed, 'R^2': r_squared } else: return {'cj speed': cj_speed}
def setUpClass(cls): cls.gas = ct.Solution("jacobian-tests.yaml", transport_model=None) # species: [H2, H, O, O2, OH, H2O, HO2, H2O2, AR] cls.gas.TPX = 300, 2 * ct.one_atm, "H2:1, O2:3, AR:0.4" cls.gas.equilibrate("HP") super().setUpClass()
#githubtest #print(sys.version) import inspect import os print(inspect.getfile(ct)) #圧力kPa,温度K P1 = 101.325 T1 = 288.15 phi = 0.8 P2 = P1 * 1 E2 = 0.75 E4 = 0.82 P4 = P1 inigas = ct.Solution('gri30.xml') #初期条件を設定(Air) gas1 = ct.Quantity(inigas) gas1.TPX = T1, P1 * 1000, {'O2': 1, 'N2': 3.76} H1 = gas1.h #print(gas1.report()) #初期条件を設定(H2) gas2 = ct.Quantity(inigas) gas2.TPX = T1, P2 * 1000, {'H2': 2 * phi} gas1.moles = 1 nO2 = gas1.X[gas1.species_index('O2')] gas2.moles = nO2 * 2 * phi
def create_solution_mechanism(): # Defining Reaction Mechanism # Mechanism II - Marinov + Mevel marinov_species = ct.Species.listFromFile('marinov_ethanol_mechanism.cti') marinov_reactions = ct.Reaction.listFromFile( 'marinov_ethanol_mechanism.cti') mevel_species = ct.Species.listFromFile('mevel_ethanol_mechanism.cti') mevel_reactions = ct.Reaction.listFromFile('mevel_ethanol_mechanism.cti') new_species = [] new_reactions = [] # Filter species for specie in mevel_species: # Include all nitrogen compounds except for N2 if 'N' in specie.composition and specie.composition != {'N': 2}: new_species.append(specie) new_species_names = {specie.name for specie in new_species} # print('N based species: {0}'.format(', '.join(name for name in new_species_names))) marinov_mevel_species = marinov_species + new_species marinov_mevel_species_names = { specie.name.upper() for specie in marinov_mevel_species } # Filter reactions, keeping only those that only involve the selected species # print('\nReactions:') for R in mevel_reactions: if any(reactant in new_species_names for reactant in R.reactants) or any(product in new_species_names for product in R.products): # for reactant in R.reactants: # if reactant not in marinov_mevel_species_names: # print('Missing reactant:', reactant, 'when analyzing reaction', R.equation) # for product in R.products: # if product not in marinov_mevel_species_names: # print('Missing product:', product, 'when analyzing reaction', R.equation) if all(reactant in marinov_mevel_species_names for reactant in R.reactants): if all(product in marinov_mevel_species_names for product in R.products): new_reactions.append(R) # print('Accepted reaction:', R.equation) # print('\n') marinov_mevel_species = marinov_species + new_species marinov_mevel_reactions = marinov_reactions + new_reactions marinov_mevel_gas = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=marinov_mevel_species, reactions=marinov_mevel_reactions) marinov_mevel_gas = ct.Solution('sandiego2016_plus_N_CK.cti') print('Number of species:', marinov_mevel_gas.n_species) print('Number of reactions:', marinov_mevel_gas.n_reactions) return marinov_mevel_gas
_T4 = [] _X1 = [] _X2 = [] _X3 = [] _X4 = [] _h12 = [] _h23 = [] _h34 = [] _h41 = [] _s12 = [] _s23 = [] _s34 = [] _s41 = [] "Define Fluids" air_1 = ct.Solution('air.cti') air_2 = ct.Solution('air.cti') WF_1 = ct.Hfc134a() WF_2 = ct.Hfc134a() WF_3 = ct.Hfc134a() WF_4 = ct.Hfc134a() "Knowns" T1_air = 38+273.15 # T1 ambient = 38C P1_air = 1*10**5 # P1 ambient = 1 bar T2_air = 10+273.15 # T2 into cabin = 10C P2_air = P1_air # P2 = 1 bar air_1.TP = T1_air,P1_air # Define state air_2.TP = T2_air,P2_air # Define state h1_air = air_1.h h2_air = air_2.h
Requires: cantera >= 2.5.0 """ import cantera as ct # Simulation parameters p = ct.one_atm # pressure [Pa] Tin = 300.0 # unburned gas temperature [K] reactants = 'H2:1.1, O2:1, AR:5' # premixed gas composition width = 0.03 # m loglevel = 1 # amount of diagnostic output (0 to 8) # Solution object used to compute mixture properties, set to the state of the # upstream fuel-air mixture gas = ct.Solution('h2o2.yaml') gas.TPX = Tin, p, reactants # Set up flame object f = ct.FreeFlame(gas, width=width) f.set_refine_criteria(ratio=3, slope=0.06, curve=0.12) f.show_solution() # Solve with mixture-averaged transport model f.transport_model = 'Mix' f.solve(loglevel=loglevel, auto=True) # Solve with the energy equation enabled try: # save to HDF container file if h5py is installed f.write_hdf('adiabatic_flame.h5', group='mix', mode='w',
Since reactors can have multiple inlets and outlets, they can be used to implement mixers, splitters, etc. In this example, air and methane are mixed in stoichiometric proportions. Due to the low temperature, no reactions occur. Note that the air stream and the methane stream use *different* reaction mechanisms, with different numbers of species and reactions. When gas flows from one reactor or reservoir to another one with a different reaction mechanism, species are matched by name. If the upstream reactor contains a species that is not present in the downstream reaction mechanism, it will be ignored. In general, reaction mechanisms for downstream reactors should contain all species that might be present in any upstream reactor. """ import cantera as ct # Use air for stream a. gas_a = ct.Solution('air.xml') gas_a.TPX = 300.0, ct.one_atm, 'O2:0.21, N2:0.78, AR:0.01' rho_a = gas_a.density # Use GRI-Mech 3.0 for stream b (methane) and for the mixer. If it is desired # to have a pure mixer, with no chemistry, use instead a reaction mechanism # for gas_b that has no reactions. gas_b = ct.Solution('gri30.xml') gas_b.TPX = 300.0, ct.one_atm, 'CH4:1' rho_b = gas_b.density # Create reservoirs for the two inlet streams and for the outlet stream. The # upsteam reservoirs could be replaced by reactors, which might themselves be # connected to reactors further upstream. The outlet reservoir could be # replaced with a reactor with no outlet, if it is desired to integrate the # composition leaving the mixer in time, or by an arbitrary network of
def write(solution): """Function to write cantera solution object to inp file. Parameters ---------- solution : obj Cantera solution object Returns : str Name of trimmed Mechanism file (.inp) Example ------- soln2ck.write(gas) """ trimmed_solution = solution input_file_name_stripped = trimmed_solution.name cwd = os.getcwd() output_file_name = os.path.join(cwd, 'pym_' + input_file_name_stripped + '.inp') f = open(output_file_name, 'w+') #Work functions calories_constant = 4184.0 #number of calories in 1000 Joules of energy def eliminate(input_string, char_to_replace, spaces='single'): """ Eliminate characters from a string :param input_string string to be modified :param char_to_replace array of character strings to be removed """ for char in char_to_replace: input_string = input_string.replace(char, "") if spaces == 'double': input_string = input_string.replace(" ", " ") return input_string def section_break(title): """ Insert break and new section title into cti file :param title: title string for next section_break """ f.write('!' + "-" * 75 + '\n') f.write('! ' + title + '\n') f.write('!' + "-" * 75 + '\n') def replace_multiple(input_string, replace_list): """ Replace multiple characters in a string :param input_string string to be modified :param replace list list containing items to be replaced (value replaces key) """ for original_character, new_character in replace_list.items(): input_string = input_string.replace(original_character, new_character) return input_string def build_arrhenius(equation_object, equation_type): """ Builds Arrhenius coefficient string :param equation_objects cantera equation object :param equation_type: string of equation type """ coeff_sum = sum(equation_object.reactants.values()) pre_exponential_factor = equation_object.rate.pre_exponential_factor temperature_exponent = '{:.3f}'.format( equation_object.rate.temperature_exponent) activation_energy = '{:.2f}'.format( equation_object.rate.activation_energy / calories_constant) if equation_type == 'ElementaryReaction': if coeff_sum == 1: pre_exponential_factor = str( '{:.3E}'.format(pre_exponential_factor)) if coeff_sum == 2: pre_exponential_factor = str('{:.3E}'.format( pre_exponential_factor * 10**3)) if coeff_sum == 3: pre_exponential_factor = str('{:.3E}'.format( pre_exponential_factor * 10**6)) if equation_type == 'ThreeBodyReaction': if coeff_sum == 1: pre_exponential_factor = str('{:.3E}'.format( pre_exponential_factor * 10**3)) if coeff_sum == 2: pre_exponential_factor = str('{:.3E}'.format( pre_exponential_factor * 10**6)) if (equation_type != 'ElementaryReaction' and equation_type != 'ThreeBodyReaction'): pre_exponential_factor = str( '{:.3E}'.format(pre_exponential_factor)) arrhenius = [ pre_exponential_factor, temperature_exponent, activation_energy ] return arrhenius def build_modified_arrhenius(equation_object, t_range): """ Builds Arrhenius coefficient strings for high and low temperature ranges :param equation_objects cantera equation object :param t_range: simple string ('high' or 'low') to designate temperature range """ coeff_sum = sum(equation_object.products.values()) if t_range == 'high': pre_exponential_factor = equation_object.high_rate.pre_exponential_factor temperature_exponent = '{:.3f}'.format( equation_object.high_rate.temperature_exponent) activation_energy = '{:.2f}'.format( equation_object.high_rate.activation_energy / calories_constant) if coeff_sum == 1: pre_exponential_factor = str('{:.5E}'.format( pre_exponential_factor * 10**3)) else: pre_exponential_factor = str( '{:.5E}'.format(pre_exponential_factor)) arrhenius_high = [ pre_exponential_factor, temperature_exponent, activation_energy ] return arrhenius_high if t_range == 'low': pre_exponential_factor = equation_object.low_rate.pre_exponential_factor temperature_exponent = '{:.3f}'.format( equation_object.low_rate.temperature_exponent) activation_energy = '{:.2f}'.format( equation_object.low_rate.activation_energy / calories_constant) if coeff_sum == 1: pre_exponential_factor = str('{:.5E}'.format( pre_exponential_factor * 10**6)) else: pre_exponential_factor = str('{:.5E}'.format( pre_exponential_factor * 10**3)) arrhenius_low = [ pre_exponential_factor, temperature_exponent, activation_energy ] return arrhenius_low def build_nasa(nasa_coeffs, row): """ Creates string of nasa polynomial coefficients :param nasa_coeffs cantera species thermo coefficients object :param row which row to write coefficients in """ line_coeffs = '' lines = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14]] line_index = lines[row - 2] for ix, c in enumerate(nasa_coeffs): if ix in line_index: if c >= 0: line_coeffs += ' ' line_coeffs += str('{:.8e}'.format(c)) return line_coeffs def build_species_string(): """ formats species string for writing """ species_list_string = '' line = 1 for sp_index, sp_string in enumerate(trimmed_solution.species_names): sp = ' ' #get length of string next species is added length_new = len(sp_string) length_string = len(species_list_string) total = length_new + length_string + 3 #if string will go over width, wrap to new line if total >= 70 * line: species_list_string += '\n' line += 1 species_list_string += sp_string + ((16 - len(sp_string)) * sp) return species_list_string #Write title block to file section_break('Chemkin File converted from Solution Object by pyMARS') #Write phase definition to file element_names = eliminate(str(trimmed_solution.element_names), ['[', ']', '\'', ',']) element_string = Template('ELEMENTS\n' + '$element_names\n' + 'END\n') f.write(element_string.substitute(element_names=element_names)) species_names = build_species_string() species_string = Template('SPECIES\n' + '$species_names\n' + 'END\n') f.write(species_string.substitute(species_names=species_names)) #Write species to file section_break('Species data') f.write('THERMO ALL' + '\n' + ' 300.000 1000.000 5000.000' + '\n') phase_unknown_list = [] #write data for each species in the Solution object for sp_index in xrange(len(trimmed_solution.species_names)): d = 3.33564e-30 #1 debye = d coulomb-meters species = trimmed_solution.species(sp_index) name = str(trimmed_solution.species(sp_index).name) nasa_coeffs = trimmed_solution.species(sp_index).thermo.coeffs #Species attributes from trimmed solution object t_low = '{0:.3f}'.format(species.thermo.min_temp) t_max = '{0:.3f}'.format(species.thermo.max_temp) t_mid = '{0:.3f}'.format(species.thermo.coeffs[0]) temp_range = str(t_low) + ' ' + str(t_max) + ' ' + t_mid species_comp = '' for atom in species.composition: species_comp += '{:<4}'.format(atom) species_comp += str(int(species.composition[atom])) if type(species.transport).__name__ == 'GasTransportData': species_phase = 'G' else: phase_unknown_list.append(name) species_phase = 'G' line_1 = ('{:<18}'.format(name) + '{:<6}'.format(' ') + '{:<20}'.format(species_comp) + '{:<4}'.format(species_phase) + '{:<31}'.format(temp_range) + '{:<1}'.format('1') + '\n') f.write(line_1) line_2_coeffs = build_nasa(nasa_coeffs, 2) line_2 = line_2_coeffs + ' 2\n' f.write(line_2) line_3_coeffs = build_nasa(nasa_coeffs, 3) line_3 = line_3_coeffs + ' 3\n' f.write(line_3) line_4_coeffs = build_nasa(nasa_coeffs, 4) line_4 = line_4_coeffs + ' 4\n' f.write(line_4) f.write('END\n') #Write reactions to file section_break('Reaction Data') f.write('REACTIONS\n') #write data for each reaction in the Solution Object for reac_index in xrange(len(trimmed_solution.reaction_equations())): equation_string = str(trimmed_solution.reaction_equation(reac_index)) equation_string = eliminate(equation_string, ' ', 'single') equation_object = trimmed_solution.reaction(reac_index) equation_type = type(equation_object).__name__ m = str(reac_index + 1) if equation_type == 'ThreeBodyReaction': arrhenius = build_arrhenius(equation_object, equation_type) main_line = ('{:<51}'.format(equation_string) + '{:>9}'.format(arrhenius[0]) + '{:>9}'.format(arrhenius[1]) + '{:>11}'.format(arrhenius[2]) + '\n') f.write(main_line) #trimms efficiencies list efficiencies = equation_object.efficiencies trimmed_efficiencies = equation_object.efficiencies for s in efficiencies: if s not in trimmed_solution.species_names: del trimmed_efficiencies[s] replace_list_2 = {'{': '', '}': '/', '\'': '', ':': '/', ',': '/'} efficiencies_string = replace_multiple(str(trimmed_efficiencies), replace_list_2) secondary_line = str(efficiencies_string) + '\n' if bool(efficiencies) is True: f.write(secondary_line) if equation_type == 'ElementaryReaction': arrhenius = build_arrhenius(equation_object, equation_type) main_line = ('{:<51}'.format(equation_string) + '{:>9}'.format(arrhenius[0]) + '{:>9}'.format(arrhenius[1]) + '{:>11}'.format(arrhenius[2]) + '\n') f.write(main_line) if equation_type == 'FalloffReaction': arr_high = build_modified_arrhenius(equation_object, 'high') main_line = ('{:<51}'.format(equation_string) + '{:>9}'.format(arr_high[0]) + '{:>9}'.format(arr_high[1]) + '{:>11}'.format(arr_high[2]) + '\n') f.write(main_line) arr_low = build_modified_arrhenius(equation_object, 'low') second_line = (' LOW /' + ' ' + arr_low[0] + ' ' + arr_low[1] + ' ' + arr_low[2] + '/\n') f.write(second_line) j = equation_object.falloff.parameters #If optional Arrhenius data included: try: third_line = (' TROE/' + ' ' + str(j[0]) + ' ' + str(j[1]) + ' ' + str(j[2]) + ' ' + str(j[3]) + ' /\n') f.write(third_line) except IndexError: pass #trimms efficiencies list efficiencies = equation_object.efficiencies trimmed_efficiencies = equation_object.efficiencies for s in efficiencies: if s not in trimmed_solution.species_names: del trimmed_efficiencies[s] replace_list_2 = {'{': '', '}': '/', '\'': '', ':': '/', ',': '/'} efficiencies_string = replace_multiple(str(trimmed_efficiencies), replace_list_2) fourth_line = str(efficiencies_string) + '\n' if bool(efficiencies) is True: f.write(fourth_line) #dupluicate option if equation_object.duplicate is True: duplicate_line = ' DUPLICATE' + '\n' f.write(duplicate_line) f.write('END') f.close() #Test mechanism file original_solution = solution #convert written chemkin file to cti, and get solution parser = ck2cti.Parser() outName = 'test_file.cti' parser.convertMech(output_file_name, outName=outName) new_solution = ct.Solution(outName) #test new solution vs original solutoin #test(original_solution, new_solution) os.remove(outName) return output_file_name """
def setUpClass(cls): cls.gas = ct.Solution("jacobian-tests.yaml", transport_model=None) # species: [H2, H, O, O2, OH, H2O, HO2, H2O2, AR] cls.gas.X = [0.1, 1e-4, 1e-5, 0.2, 2e-4, 0.3, 1e-6, 5e-5, 0.4] cls.gas.TP = 800, 2 * ct.one_atm super().setUpClass()
fuel_inflow_temperature = 300 #[K] # mixture fraction mixture_fraction_element = 'N' # Reaction on/off reactions = 1 # Restart from previous particle list restart = 0 ## End of settings #..........................................................................# # get a mixture object going gas = ct.Solution(mech) # equilibrate the intial compposition gas.TPY = T, 101000, initial_composition gas.equilibrate('HP') for counter, mass_fraction in enumerate(gas.Y): initial_composition[gas.species_name(counter)] = mass_fraction T = gas.T # Mixture fraction setup gas.TPY = T, 101000, oxidizer_inflow_composition #elemental mass fraction of mt_element in oxidizer stream Z_oxidizer = gas.elemental_mass_fraction(mixture_fraction_element) _, rho_fuel = gas.TD gas.TPY = T, 101000, fuel_inflow_composition
def setUpClass(cls): cls.gas = ct.Solution("kineticsfromscratch.yaml", transport_model=None) # species: [AR, O, H2, H, OH, O2, H2O, H2O2, HO2] cls.gas.X = [0.1, 3e-4, 5e-5, 6e-6, 3e-3, 0.6, 0.25, 1e-6, 2e-5] cls.gas.TP = 2000, 5 * ct.one_atm super().setUpClass()
tab2 = [] for itcon in range(ncon): for k in range(noptim): tab2.append(k) return (np.array(tab), np.array(tab2)) else: return OptFn.gradient_constraints(x) if __name__ == '__main__': # Main process, common to all tasks (master and slaves) # Reading input up = imp.load_source('user_param', sys.argv[1]) # Cantera gas phase Global.gas = ct.Solution(up.mechanism) # Specific storage for flame computations Global.nflames = len(up.P_fl)*len(up.T_fl)*len(up.phi_fl) Global.flame_inits = [False for ii in range(Global.nflames)] Global.sims = [False for ii in range(Global.nflames)] Global.gases = [False for ii in range(Global.nflames)] Global.directory = up.directory Global.mechanism = up.mechanism # Define MPI message tags tags = Par.enum('READY', 'DONE', 'EXIT', 'START', 'SLEEP', 'WAKEUP') # Initializations and preliminaries Global.MPI = MPI comm = MPI.COMM_WORLD # get MPI communicator object
def setUpClass(cls): cls.gas = ct.Solution("h2o2.yaml", transport_model=None) cls.gas.TPX = 300, 5 * ct.one_atm, "H2:1, O2:3" cls.gas.equilibrate("HP") super().setUpClass()
def reduce_drgep(model_file, species_safe, threshold, importance_coeffs, ignition_conditions, sampled_metrics, phase_name='', previous_model=None, num_threads=1, path=''): """Given a threshold and DRGEP coefficients, reduce the model and determine the error. Parameters ---------- model_file : str Filename for model being reduced species_safe : list of str List of species to always be retained threshold : float DRG threshold for trimming graph importance_coeffs : dict Dictionary with species and their overall interaction coefficients. ignition_conditions : list of InputIgnition List of autoignition initial conditions. sampled_metrics: numpy.ndarray Global metrics from original model used to evaluate error phase_name : str, optional Optional name for phase to load from CTI file (e.g., 'gas'). previous_model : ReducedModel, optional Model produced at previous threshold level; used to avoid repeated work. num_threads : int, optional Number of CPU threads to use for performing simulations in parallel. Optional; default = 1, in which the multiprocessing module is not used. If 0, then use the available number of cores minus one. Otherwise, use the specified number of threads. path : str, optional Optional path for writing files Returns ------- ReducedModel Return reduced model and associated metadata """ solution = ct.Solution(model_file, phase_name) species_removed = [ sp for sp in solution.species_names if importance_coeffs[sp] < threshold and sp not in species_safe ] if (previous_model and len(species_removed) == solution.n_species - previous_model.model.n_species): return previous_model # Cut the exclusion list from the model. reduced_model = reduce_model.trim(model_file, species_removed, f'reduced_{model_file}', phase_name=phase_name) reduced_model_filename = soln2cti.write( reduced_model, f'reduced_{reduced_model.n_species}.cti', path=path) reduced_model_metrics = sampling.sample_metrics(reduced_model_filename, ignition_conditions, phase_name=phase_name, num_threads=num_threads, path=path) error = sampling.calculate_error(sampled_metrics, reduced_model_metrics) return reduce_model.ReducedModel(model=reduced_model, filename=reduced_model_filename, error=error)
def setUpClass(cls): cls.gas = ct.Solution("gri30.yaml", transport_model=None) cls.gas.TPX = 300, 5 * ct.one_atm, "CH4:1, C3H8:.1, O2:1, N2:3.76" cls.gas.equilibrate("HP") super().setUpClass()
from SDToolbox import CJspeed from scipy.optimize import fsolve import time def CJ_func(comp, A): [Vel, _] = CJspeed(101325, 298, comp, 'gri30.cti', 0) print(Vel, comp) A.append(Vel) return A, Vel start = time.time() T = 298 P = 101325 gas = ct.Solution('gri30.cti') j = 1 comp = 'C3H8:1, N2O:10, N2:{0}'.format(j) gas.TPX = T, P, comp k_N2 = gas.cp_mass / gas.cv_mass k_CO2 = 0.0 k_m = [] i = 0 i_m = [] gas2 = ct.Solution('gri30.cti') gas_check = ct.Solution('gri30.cti') gas_check.TPX = T, P, 'CO2:1' if k_N2 > gas_check.cp_mass / gas_check.cv_mass:
def test_noninteger_atomicity(self): gas = ct.Solution('noninteger-atomicity.cti') self.assertNear( gas.molecular_weights[gas.species_index('CnHm')], 10.65 * gas.atomic_weight('C') + 21.8 * gas.atomic_weight('H'))