From b11115fb5e7d97f809de496a2d496b479d27266c Mon Sep 17 00:00:00 2001 From: Max Liu Date: Mon, 3 Jun 2019 22:33:06 -0400 Subject: [PATCH] Update ignition delay demo notebook --- ...ustion_model_and_ignition_delay_demo.ipynb | 225 ++++++++++-------- 1 file changed, 125 insertions(+), 100 deletions(-) diff --git a/ipython/combustion_model_and_ignition_delay_demo.ipynb b/ipython/combustion_model_and_ignition_delay_demo.ipynb index b8c51dd129..bc8c5e8bff 100644 --- a/ipython/combustion_model_and_ignition_delay_demo.ipynb +++ b/ipython/combustion_model_and_ignition_delay_demo.ipynb @@ -19,26 +19,25 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ - "Fuel = 'CCO'\n", - "Equivalence_Ratio = 1.0\n", + "fuel = 'OC'\n", + "equivalence_ratio = 1.0\n", "\n", - "Temperature = 1500.0 # (K)\n", - "Pressure = 1.0 # (atm)\n", - "simtime = 2 # (ms)\n", - "topSA = 10 # number of top sensitive reactions and thermo to display\n", + "temperature = 1500.0 # (K)\n", + "pressure = 1.0 # (atm)\n", + "sim_time = 2 # (ms)\n", + "top_sens = 10 # number of top sensitive reactions and thermo to display\n", "\n", "rmgpy_path = '../rmg.py' # Change to your rmg.py path\n", "\n", - "\n", "from IPython.display import display, Image\n", "from rmgpy.molecule import Molecule\n", - "Fuel_Molecule = Molecule().fromSMILES(Fuel)\n", - "print(\"The fuel molecule is:\");display(Fuel_Molecule)" + "\n", + "fuel_molecule = Molecule(SMILES=fuel)\n", + "print(\"The fuel molecule is:\")\n", + "display(fuel_molecule)" ] }, { @@ -52,23 +51,22 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, "scrolled": true }, "outputs": [], "source": [ - "Fuel_Molecule = Molecule().fromSMILES(Fuel)\n", - "nC = int(Fuel_Molecule.getNumAtoms('C'))\n", - "nH = int(Fuel_Molecule.getNumAtoms('H'))\n", - "nO = int(Fuel_Molecule.getNumAtoms('O'))\n", + "fuel_molecule = Molecule(SMILES=fuel)\n", + "nC = int(fuel_molecule.getNumAtoms('C'))\n", + "nH = int(fuel_molecule.getNumAtoms('H'))\n", + "nO = int(fuel_molecule.getNumAtoms('O'))\n", "\n", - "A = str(Equivalence_Ratio/(nC+(nH/4.0)-(nO/2.0)))\n", + "fuel_stoich = equivalence_ratio/(nC+(nH/4.0)-(nO/2.0))\n", "\n", - "Input_file = '''\n", + "input_file = '''\n", "# Data sources\n", "database(\n", - " thermoLibraries = ['BurkeH2O2','primaryThermoLibrary','thermo_DFT_CCSDTF12_BAC','DFT_QCI_thermo','FFCM1(-)','JetSurF2.0'],\n", - " reactionLibraries = ['BurkeH2O2inN2','FFCM1(-)','JetSurF2.0'],\n", + " thermoLibraries = ['BurkeH2O2','primaryThermoLibrary','thermo_DFT_CCSDTF12_BAC','DFT_QCI_thermo','FFCM1(-)'],\n", + " reactionLibraries = ['BurkeH2O2inN2','FFCM1(-)'],\n", " seedMechanisms = [],\n", " kineticsDepositories = ['training'],\n", " kineticsFamilies = 'default',\n", @@ -79,7 +77,7 @@ "species(\n", " label='fuel',\n", " reactive=True,\n", - " structure=SMILES('''+\"'\"+Fuel+\"'\"+'''),\n", + " structure=SMILES('''+\"'\"+fuel+\"'\"+'''),\n", ")\n", "\n", "species(\n", @@ -102,14 +100,14 @@ "\n", "# Reaction system\n", "simpleReactor(\n", - " temperature=('''+str(Temperature)+''','K'),\n", - " pressure=('''+str(Pressure)+''','atm'),\n", + " temperature=('''+str(temperature)+''','K'),\n", + " pressure=('''+str(pressure)+''','atm'),\n", " initialMoleFractions={\n", - " 'fuel': '''+A+''',\n", + " 'fuel': '''+str(fuel_stoich)+''',\n", " 'O2': 1,\n", " 'N2': 3.76,\n", " },\n", - " terminationTime=(0.001,'s'),\n", + " terminationTime=('''+str(sim_time/1000.0)+''','s'),\n", " sensitivity=['OH'],\n", " sensitivityThreshold=0.01,\n", ")\n", @@ -123,9 +121,13 @@ "\n", "model(\n", " toleranceKeepInEdge=0,\n", - " toleranceMoveToCore=0.05,\n", - " toleranceInterruptSimulation=0.05,\n", - " maximumEdgeSpecies=300000\n", + " toleranceMoveToCore=0.1,\n", + " toleranceInterruptSimulation=0.1,\n", + " maximumEdgeSpecies=100000,\n", + " filterReactions=True,\n", + " maxNumObjsPerIter=2,\n", + " terminateAtMaxObjects=True,\n", + " maxNumSpecies=50,\n", ")\n", "\n", "#pressureDependence(\n", @@ -163,12 +165,15 @@ "'''\n", "\n", "import os\n", - "if not os.path.exists('RMG'):\n", - " os.mkdir('RMG')\n", - "os.system('rm -r RMG/*')\n", - "with open('RMG/Demo.py','w') as RMG_Input_File:\n", - " RMG_Input_File.write(Input_file)\n", - "print(\"Created RMG input file\")" + "import shutil\n", + "directory = './rmg_demo'\n", + "if os.path.exists(directory):\n", + " shutil.rmtree(directory)\n", + "os.mkdir(directory)\n", + "input_path = os.path.join(directory, 'input.py')\n", + "with open(input_path,'w') as f:\n", + " f.write(input_file)\n", + "print('Created RMG input file at ' + os.path.abspath(input_path))" ] }, { @@ -181,17 +186,27 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ - "os.system('python {0} RMG/Demo.py'.format(rmgpy_path)) \n", - "\n", - "print(\"RMG Simulation Completed. Summary of log file:\\n\")\n", - "RMG_log = open('RMG/RMG.log','r').readlines()\n", - "lines = [x for x in RMG_log[-13:-1] if x != \"\\n\"]\n", - "for line in lines: print(line)" + "import time\n", + "import datetime\n", + "import subprocess\n", + "start = time.time()\n", + "\n", + "# Execute RMG job\n", + "subprocess.check_call(['python', rmgpy_path, input_path])\n", + "\n", + "end = time.time()\n", + "print 'Total simulation time: ' + str(datetime.timedelta(seconds=round(end-start)))\n", + "\n", + "with open(os.path.join(directory, 'RMG.log'),'r') as f:\n", + " begin = False\n", + " for line in f:\n", + " if 'MODEL GENERATION COMPLETED' in line:\n", + " begin = True\n", + " if begin:\n", + " print line.strip()" ] }, { @@ -205,48 +220,41 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, "scrolled": true }, "outputs": [], "source": [ - "from rmgpy.chemkin import *\n", - "from rmgpy.tools.canteraModel import *\n", + "from rmgpy.chemkin import loadChemkinFile\n", + "from rmgpy.tools.canteraModel import Cantera, getRMGSpeciesFromUserSpecies\n", "from rmgpy.species import Species\n", "import time\n", "\n", - "path = \"RMG/chemkin/\"\n", - "speciesList, reactionList = loadChemkinFile(path+'chem_annotated.inp',\n", - " path+'species_dictionary.txt',\n", - " path+'tran.dat')\n", - "\n", - "nC = int(Fuel_Molecule.getNumAtoms('C'))\n", - "nH = int(Fuel_Molecule.getNumAtoms('H'))\n", - "nO = int(Fuel_Molecule.getNumAtoms('O'))\n", - "phi = Equivalence_Ratio\n", - "FuelStoich = phi/(nC+(nH/4.0)-(nO/2.0))\n", + "chem_path = os.path.join(directory, 'chemkin')\n", + "species_list, reaction_list = loadChemkinFile(os.path.join(chem_path, 'chem_annotated.inp'),\n", + " os.path.join(chem_path, 'species_dictionary.txt'),\n", + " os.path.join(chem_path, 'tran.dat'))\n", "\n", - "Fuel_Species=Species().fromSMILES(Fuel)\n", - "O2_Species=Species().fromSMILES('[O][O]')\n", - "N2_Species=Species().fromSMILES('N#N')\n", - "OH_Species=Species().fromSMILES('[OH]')\n", - "species_dict = getRMGSpeciesFromUserSpecies([Fuel_Species,O2_Species,N2_Species,OH_Species], speciesList)\n", + "fuel_species=Species(SMILES=fuel)\n", + "O2_species=Species(SMILES='[O][O]')\n", + "N2_species=Species(SMILES='N#N')\n", + "OH_species=Species(SMILES='[OH]')\n", + "species_dict = getRMGSpeciesFromUserSpecies([fuel_species, O2_species, N2_species, OH_species], species_list)\n", "\n", - "reactorTypeList = ['IdealGasReactor']\n", - "reactionTimeList = ([simtime], 'ms')\n", + "reactor_type_list = ['IdealGasReactor']\n", + "reaction_time_list = ([sim_time], 'ms')\n", "\n", - "molFracList=[{species_dict[Fuel_Species]: FuelStoich,\n", - " species_dict[O2_Species]: 1,\n", - " species_dict[N2_Species]: 3.76}]\n", - "Tlist = ([Temperature],'K')\n", - "Plist = ([Pressure],'atm')\n", + "mol_frac_list=[{species_dict[fuel_species]: fuel_stoich,\n", + " species_dict[O2_species]: 1,\n", + " species_dict[N2_species]: 3.76}]\n", + "T_list = ([temperature],'K')\n", + "P_list = ([pressure],'atm')\n", "\n", - "job = Cantera(speciesList=speciesList, reactionList=reactionList, outputDirectory='')\n", - "job.loadChemkinModel(path+'chem_annotated.inp',transportFile=path+'tran.dat')\n", - "job.generateConditions(reactorTypeList, reactionTimeList, molFracList, Tlist, Plist)\n", + "job = Cantera(speciesList=species_list, reactionList=reaction_list, outputDirectory=directory)\n", + "job.loadChemkinModel(os.path.join(chem_path, 'chem_annotated.inp'), os.path.join(chem_path, 'tran.dat'))\n", + "job.generateConditions(reactor_type_list, reaction_time_list, mol_frac_list, T_list, P_list)\n", "\n", "alldata = job.simulate()\n", - "print(\"Done.\")" + "print(\"Simulation Completed\")" ] }, { @@ -260,7 +268,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false + "scrolled": false }, "outputs": [], "source": [ @@ -269,13 +277,14 @@ "########################################\n", "\n", "import matplotlib.pyplot as plt\n", + "import numpy as np\n", "import pandas as pd\n", "from rmgpy.tools import plot as rmg_plot\n", "from operator import itemgetter\n", - "from rmgpy.tools.sensitivity import runSensitivity\n", "%matplotlib notebook\n", "\n", "times = alldata[0][0].data\n", + "temperatures = alldata[0][1][0].data\n", "pressures = alldata[0][1][1].data\n", "\n", "dpdt = (pressures[1:] - pressures[:-1]) / (times[1:] - times[:-1])\n", @@ -283,9 +292,9 @@ "ign_delay_time = times[idi]\n", "\n", "for spc in xrange(len(alldata[0][1][:])):\n", - " if alldata[0][1][spc].label == str(species_dict[Fuel_Species]):\n", + " if alldata[0][1][spc].label == str(species_dict[fuel_species]):\n", " Fuel_idx = spc\n", - " if alldata[0][1][spc].label == str(species_dict[OH_Species]):\n", + " if alldata[0][1][spc].label == str(species_dict[OH_species]):\n", " OH_idx = spc\n", "\n", "for i in range(len(alldata[0][1][Fuel_idx].data)):\n", @@ -293,10 +302,10 @@ " Fuel_Depletion_Time = times[i]\n", " break\n", "\n", - "files = os.listdir('RMG/solver')\n", + "files = os.listdir(os.path.join(directory, 'solver'))\n", "\n", "sensitivity_file = str(filter(lambda x: ('sensitivity' in x) and ('.csv' in x),files)[0])\n", - "SA_time, SA_data = rmg_plot.parseCSVData('RMG/solver/'+sensitivity_file)\n", + "SA_time, SA_data = rmg_plot.parseCSVData(os.path.join(directory, 'solver', sensitivity_file))\n", "\n", "time_error = 1\n", "\n", @@ -322,7 +331,7 @@ "num1 = sorted(num1, key=itemgetter(0),reverse=True)\n", "SA_k_data = []\n", "SA_k_label = []\n", - "for i in xrange(min(topSA, Gidx)):\n", + "for i in xrange(min(top_sens, Gidx)):\n", " SA_k_data.append(SA_data[int(num1[i][1])].data[ign_delay_idx]) # make sorted lists size topSA of SA values and rxns labels\n", " SA_k_label.append(SA_data[int(num1[i][1])].label)\n", " \n", @@ -334,9 +343,11 @@ "num2 = sorted(num2, key=itemgetter(0),reverse=True)\n", "SA_G_data = []\n", "SA_G_label = []\n", - "for i in xrange(min(topSA, len(SA_data)-Gidx)):\n", + "for i in xrange(min(top_sens, len(SA_data)-Gidx)):\n", " SA_G_data.append(SA_data[int(num2[i][1])+Gidx].data[ign_delay_idx]) # make sorted lists size topSA of SA values and rxns labels\n", " SA_G_label.append(SA_data[int(num2[i][1])+Gidx].label)\n", + " \n", + "print \"Ignition delay time is {0:.4f} ms\".format(ign_delay_time * 1000)\n", " \n", "plt.rcParams['axes.labelsize'] = 18\n", "plt.rcParams['xtick.labelsize'] = 12\n", @@ -355,30 +366,47 @@ "plt.title('Fuel profile')\n", "plt.xlim([0,2000*ign_delay_time])\n", "\n", + "max_oh = max(alldata[0][1][OH_idx].data)\n", + "\n", "plt.subplot(1,2,2)\n", "plt.plot(alldata[0][0].data*1000, alldata[0][1][OH_idx].data,'-o')\n", "plt.xlabel('Time (ms)')\n", "plt.ylabel('$Y_{OH}$')\n", "plt.title('OH profile')\n", "plt.xlim([0,2000*ign_delay_time])\n", - "plt.arrow(0, alldata[0][1][OH_idx].data[idi], ign_delay_time*1000, 0, width=0.0001, head_width=0.0005, head_length=0.001, length_includes_head=True, color='r', shape='full')\n", + "plt.arrow(0, alldata[0][1][OH_idx].data[idi], ign_delay_time*1000, 0, width=max_oh*0.01, head_width=max_oh*0.05, head_length=ign_delay_time*120, length_includes_head=True, color='r', shape='full')\n", "plt.annotate(r'$Ignition Delay: \\tau_{ign}$', xy=(0,0), xytext=(0, alldata[0][1][OH_idx].data[idi]+0.0005), fontsize=10);\n", "\n", + "fig = plt.figure(figsize=fsize)\n", + "\n", + "plt.subplot(1,2,1)\n", + "plt.plot(alldata[0][0].data*1000, temperatures,'-o')\n", + "plt.xlabel('Time (ms)')\n", + "plt.ylabel('Temperature (K)')\n", + "plt.title('Temperature')\n", + "plt.xlim([0,2000*ign_delay_time])\n", + "\n", + "plt.subplot(1,2,2)\n", + "plt.plot(alldata[0][0].data*1000, pressures,'-o')\n", + "plt.xlabel('Time (ms)')\n", + "plt.ylabel('Pressure (Pa)')\n", + "plt.title('Pressure')\n", + "plt.xlim([0,2000*ign_delay_time])\n", "\n", "fig = plt.figure(figsize=fsize)\n", - "plt.barh(np.arange(min(topSA, Gidx)), SA_k_data, 1/1.5, color=\"blue\")\n", + "plt.barh(np.arange(min(top_sens, Gidx)), SA_k_data, 1/1.5, color=\"blue\")\n", "plt.gca().invert_yaxis()\n", "plt.xlabel(r'Sensitivity: $\\frac{\\partial\\:\\ln{[OH]}}{\\partial\\:\\ln{k}}$');\n", "plt.rcParams.update({'axes.labelsize': 20})\n", - "plt.yticks(np.arange(min(topSA, Gidx)),SA_k_label)\n", + "plt.yticks(np.arange(min(top_sens, Gidx)),SA_k_label)\n", "plt.title(\"[OH] sensitivity to kinetics\")\n", "\n", "fig = plt.figure(figsize=fsize)\n", - "plt.barh(np.arange(min(topSA, len(SA_data)-Gidx)), SA_G_data, 1/1.5, color=\"blue\")\n", + "plt.barh(np.arange(min(top_sens, len(SA_data)-Gidx)), SA_G_data, 1/1.5, color=\"blue\")\n", "plt.gca().invert_yaxis()\n", "plt.xlabel(r'Sensitivity: $\\frac{\\partial\\:\\ln{[OH]}}{\\partial\\:G_i}$ $[mol/kcal]$');\n", "plt.rcParams.update({'axes.labelsize': 20})\n", - "plt.yticks(np.arange(min(topSA, len(SA_data)-Gidx)),SA_G_label)\n", + "plt.yticks(np.arange(min(top_sens, len(SA_data)-Gidx)),SA_G_label)\n", "plt.title(\"[OH] sensitivity to thermo\")\n", "\n", "plt.show()" @@ -387,14 +415,13 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ - "gas = ct.Solution('RMG/cantera/chem.cti')\n", - "comp = str(species_dict[Fuel_Species])+\":\"+str(FuelStoich)+\",\"+str(species_dict[O2_Species])+\":1,\"+str(species_dict[N2_Species])+\":3.76\"\n", - "gas.TPX = Temperature, Pressure, comp\n", + "import cantera as ct\n", + "gas = ct.Solution(os.path.join(directory, 'cantera', 'chem.cti'))\n", + "comp = str(species_dict[fuel_species])+\":\"+str(fuel_stoich)+\",\"+str(species_dict[O2_species])+\":1,\"+str(species_dict[N2_species])+\":3.76\"\n", + "gas.TPX = temperature, pressure, comp\n", "reactor = ct.IdealGasConstPressureReactor(gas)\n", "network = ct.ReactorNet([reactor])\n", "network.advance(ign_delay_time)\n", @@ -402,24 +429,22 @@ "\n", "from PIL import Image as PILimg\n", "ROP1 = plt.subplot(1,1,1)\n", - "dot_file = 'RMG/cantera/rxnpathC.dot'\n", - "img_file = 'RMG/cantera/rxnpathC.png'\n", + "dot_file = os.path.join(directory, 'cantera', 'rxnpathC.dot')\n", + "img_file = os.path.join(directory, 'cantera', 'rxnpathC.png')\n", "ROP_C.title = 'Reaction path diagram following C'\n", "ROP_C.threshold = 0.01\n", "ROP_C.label_threshold = 0.01\n", "ROP_C.show_details = True\n", "ROP_C.write_dot(dot_file) # write dot file\n", - "os.system('dot {0} -Tpng -o{1} -Gdpi=300'.format(dot_file, img_file)) # write png file\n", + "os.system('dot {0} -Tpng -o{1} -Gdpi=300'.format(dot_file, img_file)) # write png file\n", "fullpath = os.getcwd() + '/' + img_file\n", - "Image(fullpath)" + "display(Image(fullpath))" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [] } @@ -441,7 +466,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.13" + "version": "2.7.15" } }, "nbformat": 4,