Package: pyplume
PyPlumeThis package is intended to build reactor network models for exhaust plumes based on user input and incorporate some methods for analysis of the results.InstallationCondaThis package can be installed viacondabut the appropriate channels have to be available to conda or the install will fail. I suggest creating an environment viacondacreate--namepyplume-canthony-walker-ccantera-cconda-forgepyplumeThis should ensure that all the appropriate channels are accessible. If you know they are added, you can usecondacreate--namepyplume-canthony-walkerpyplumeOtherwise, the package can be installed withcondaascondainstall-canthony-walkerpyplumePipThis package can also bepipinstalled butpipwill not install the necessary dependencies---so make sure they're installed first by whatever means.pipinstallpyplumeTroubleshooting installationThis package relies onCanteraand other packages. If there is a failure in theconda installprocess be sure to check that the appropriate channels are added or add them to the install command, e.g.,condacreate--namepyplume-canthony-walker-ccantera-cconda-forgepyplumecondaconfig--addchannelscantera
condaconfig--addchannelsconda-forge
condaconfig--addchannelsanthony-walkerMechanism managementThe model generation two requires chemical mechanisms to run. Some of these mechanisms can be found within Cantera and exploited that way. Otherwise, mechanisms files that you want to use with this model generation software can be managed in two ways. The first way is through the command line interface (CLI). Thepyplume.mechis the command which will be used to invoke the necessary commands to manage the mechanisms.To list the functions, invoke the help menu.pyplume.mech-husage:pyplume.mech[-h][-r][-l][-aADD][-dDELETE][-t]ThisisthecommandlineinterfaceformanagingmechanismfilesofPyPlume.

optionalarguments:-h,--helpshowthishelpmessageandexit-r,--restoresetthisflagtorestoremechanismfiles.-l,--listsetthisflagtolistmechanismfiles.-aADD,--addADDthiscanbeusedtoaddamechanismfiletothecodesinternaldata.-dDELETE,--deleteDELETEthiscanbeusedtodeleteamechanismfiletothecodesinternaldata.-t,--testsetthisflagtoruntestfunctions.After that there are only 5 other options: restore, list, add, delete, and test.pyplume.mech -rrestores the original mechanisms from a backup folder. This will overwrite any mechanisms with the same name as the original set of mechanisms.pyplume.mech -llists all the mechanisms currently available to the program.pyplume.mech -a mySuperCoolMech.ctiwill addmySuperCoolMech.ctito the mechanisms available to the program.pyplume.mech -d mySuperCoolMech.ctiwill deletemySuperCoolMech.ctifrom the mechanisms available to the program.pyplume.mech -twill run a set of test functions designed to test this module.The second way of managing mechanism files is through a script. This can be done with internal functions asimportpyplume.mechimportpyplume.tests.testMechscti='mySuperCoolMech.cti'pyplume.mech.mechFileAdd(cti)#Add mechanism filepyplume.mech.mechFileDelete(cti)#Delete mechanism filepyplume.mech.mechFileRestore()#Restore mechanism filespyplume.mech.mechFileList()#list mechanism filespyplume.tests.testMechs.CLI()#Run tests for mech managementModel generation toolThe model generation tool can be implemented with the most functionality in a script but there is also a command line interface. The code works by creating an object which represents a complex reactor network created by Cantera. This reactor network is made up of a three reservoirs, a combustor, and the desired exhaust network. One reservoir is for the fuel/air mixture, one is for atmosphere entrainment, and one is for the final exhaust stage. The combustor assumes the mechanism of the fuel/air reservoir and the exhaust is the focus of the model which has the most configurable options. The reactors in the system are connected via multipleMassFlowControllerobjects based on an adjacency matrix of connections. The fuel/air reservoir is connected to the combustor with the mass flow function that follows.defmassFlow(t):returncombustor.mass/residenceTimeThe mass flow is then maintained to the first exhaust reactor with the same mass flow function to ensure continuity. Successive reactors then evenly divide their mass amongst their sinks as follows.defmdot(t,fcn=None):return(self.reactors[fcn.ridx].mass/self.residenceTime(t))/fcn.sinkTerminal exhaust reactors are connected to an exhaust reservoir by the following mass flow function, which acts as the final stage of the process.defmdot(t,fcn=None):return(self.reactors[fcn.ridx].mass/self.residenceTime(t))Finally, the entrainment functions are connected to the specified reactors via a provided entrainment function. These functions are ultimately controlled by the residence time function provided. The goal of this connection method was to implement and maintain a simple form of continuity that provided a less well mixed scenario.Creating model objectA model can be generated in multiple ways. The first is by creating an adjacency matrix, specifying mechansims for air, fuel, and exhaust, providing mass flow functions, and setting other configuration options. Forming the adjacency matrix is the most cumbersome part of this so some class methods have been included for this task. These class methods take other parameters used in determination of the adjacency matrix as well as the remaining parameters of the class constructor.Class constructorclassPlumeModel(object):"""PlumeModel class is used to generate a reactor network for modeling exhaust plume"""def__init__(self,mechs,connects,residenceTime=lambdat:0.1,entrainment=lambdat:0.1,setCanteraPath=None,build=False):"""constructor for plume model.Parameters:mechs - an array like structure with at least 3 mechanisms, [fuelMech,atmMech,eMech1,eMech2,...,eMechN]residenceTime - a function that specifies the residence time as a function of time---this is used to determine combustor and system mass flow rates.entrainment - a function that specifies entrainment mass as a function of time.connects - an 2d adjacency matrix with integer values corresponding to the appropriate mass flow function+1 in the list of mass flow functions.So, the first mass flow function, 0 index, will be represented as 1 in the matrix. This is because these values will be used for conditionalsas well. A template matrix can be generated. The matrix should specificallysetCanteraPath - path variable to cantera mech filesbuild -  boolean that builds network strictly from configuration in mechanism files (T,P) if true.default: build=false"""Simple model@classmethoddefsimpleModel(cls,mechs=["gri30.cti","air.cti","gri30.cti"],residenceTime=lambdat:0.1,entrainment=lambdat:0.1,fpath="simple.hdf5",setCanteraPath=None,build=False):"""Simple model:This classmethod builds a 1 reactor exhaust model.Network:[fuel res]->[combustor]->[ex1]->[exRes][farfield]->[ex1]"""Linear Expansion Model@classmethoddeflinearExpansionModel(cls,n=10,mechs=["gri30.cti","air.cti","gri30.cti"],residenceTime=lambdat:0.1,entrainment=lambdat:0.1,fpath="linear.hdf5",setCanteraPath=None,build=False):"""Linear Expansion Model:Use this function to generate an instance with linear expansion connects method. It takes all the parametersthat the class does except connects and replaces connects with n parameter.Parameters:n - number of reactors using linear expansion. e.g. at level 1 there is one reactorat level two there are two and so on. n must result in an integer number of stepsbased on the formula:steps=(-1+np.sqrt(1+8*n))/2Network:[fuel res]->[combustor]->[ex1]->[ex2]->[ex4]->[exRes]->[ex3]->[ex5]->[exRes]->[ex6]->[exRes][farfield]->[ex1,ex2,ex3,ex4,ex6]Notes:The farfield is connected as an inlet for each exterior reactor if you were to draw them as 2D blocks."""Grid model@classmethoddefgridModel(cls,n=3,m=3,mechs=["gri30.cti","air.cti","gri30.cti"],residenceTime=lambdat:0.1,entrainment=lambdat:0.1,fpath="grid.hdf5",setCanteraPath=None,build=False):"""Grid model:Use this function to generate an instance with grid connects method. It takes all the parametersthat the class does except connects and replaces connects with n parameter.Parameters:n - Integer number of reactor rowsm - Integer number of reactor columnsNetwork:[fuel res]->[combustor]->[ex1]->[ex2]->[ex5]->[ex8]->[exRes]->[ex3]->[ex6]->[ex9]->[exRes]->[ex4]->[ex7]->[ex10]->[exRes][farfield]->[ex1,ex2,ex4,ex5,ex7,ex8,ex10]Notes:The farfield is connected as an inlet for each exterior reactor if you were to draw them as 2D blocks."""This looks something likeimportpyplume.model.PlumeModelplumeModel=PlumeModel.linearExpansionModel()Setting Atmophere and Fuel conditionsConfiguration can be important to any simulation, this can be skipped if you want to use the configuration inside the supplied mechanism files.
Otherwise,PlumeModelhas 3 attributes that it uses to maintain the conditions of the model.fuelwhich is a Cantera Solution object for the fuel,atmospherewhich is a Cantera Solution object for the atmosphereic conditions, andexhaustswhich is a list of Cantera Solution object(s). The fuel an atmosphere conditions can be configured for each reactor as you would configure them for any other Cantera solution object. Note, that fuel is considered to be the fuel air mixture for the combustor. Since the focus on this project is the exhaust, the exhaust is produced by a single reactor which is fed into the exhaust system. The atmosphere is for entrainment purposes.In a scriptplumeModel.fuel.TPX=300.0,101325,'CH4:1, O2:0.5'#K, Pa, Mole FractionsplumeModel.atmosphere.TPX=300.0,101325,'O2:0.21, N2:0.78, AR:0.01'#K, Pa, Mole FractionsplumeModel.exhausts[3].TPX=300.0,101325,'O2:0.21, N2:0.78, AR:0.01'#Set conditions for exhaust 3Now that theplumeModel's conditions are set, it can be built and advanced to a specific time or to steady state asplumeModel.buildNetwork()#Build reactor network based on conditionsplumeModel(0.1)#advance to time=0.1 splumeModel.steadyState()The data for theplumeModelcan be viewed in one of two ways. Iffpathis specified in the constructor or class methods then anhdf5file is produced which contains the data generated. TheplumeModelcan also be called with theprintfunction.plumeModel.ptype=True#True for sparse print, False for dense printprint(plumeModel)The sparse print produces the following. Dense printing adds mass fractions of each reactor.PyPlume Network Model Summary:
fuel: T: 300.00 K, V: 1.00 m^3, mass: 0.08 kg
atmosphere: T: 300.00 K, V: 1.00 m^3, mass: 1.18 kg
combustor: T: 300.00 K, V: 1.00 m^3, mass: 0.08 kg
exhaust0: T: 300.00 K, V: 1.01 m^3, mass: 0.09 kg
exhaust: T: 300.00 K, V: 1.00 m^3, mass: 1.18 kg
Reactor Network Mass Fractions:If you want to generate the file then manage it separately, theh5Writerclass can be used for this purpose.importoutput,numpyh5w=output.h5Writer.existingFile('simple.hdf5')file=h5w.f#this gets file objecth5w(numpy.ones(h5w.dshape[1]))#This appends a vector of ones to the hdf5 file.On the command lineThe command line is currently only set up to run class method models. This can be withpyplume.model chosenModel.usage:pyplume.model[-h][-ss][-t0[T0]][-tf[TF]][-dt[DT]][-t][-v]{simple,grid,linear}Thisisthecommandlineinterfaceforrunninganexhaustnetwork.


positionalarguments:{simple,grid,linear}Thisisarequiredarguementthatspecifiesthemodelwhichwillbeused.Currentlyimplementedchoicesaresimple,grid,andlinear.

optionalarguments:-h,--helpshowthishelpmessageandexit-ss,--steadysetthisflagruntosteadystateafterintegration-t0[T0]Initialintegrationtime-tf[TF]Finalintegrationtime-dt[DT]Integrationtimeinterval-t,--testsetthisflagtoruntestfunctions.-v,--verbosesetthisflagtorunprintstatementsduringtheprocess.An example of this ispyplume.modelsimple-v-ss-twhich runs thesimplemodel with the--verbose, --steady, and --testoptions.
This producesCreating simple model and building network.
Advancing to time: 0.000.
Advancing to time: 0.100.
.
.
Advancing to time: 0.900.
Advancing to time: 1.000.
Advancing to steady state.
Running model test suite.
========================================================= test session starts ==========================================================
platform linux -- Python 3.6.10, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 -- /home/sokato/miniconda3/envs/pyplume/bin/python
cachedir: .pytest_cache
rootdir: /home/sokato
collected 5 items

../../miniconda3/envs/pyplume/lib/python3.6/site-packages/pyplume/tests/testModel.py::test_linearExpansionModel PASSED           [ 20%]
.
.PlottingThe methods for plotting the generated data are contained in the anhdf5or in script are found inpyplume.figuresBasic property plotting is currently implemented through scripting or the command line interface.In a scriptfgk=figureGenerationKit('simple.hdf5',save=True,show=True)fgk.plotProperty(['mass','CO2','H2O'])This will plot the specified properties ofsimple.hdf5as a function of time. It will also save the plots to pdf files and display them. The same functionality on the command line would look like:pyplume.figures"simple.hdf5"-w-d-p"mass""CO2","H2O"Statistical methodsThe methods for plotting the generated data are contained in the anhdf5or in script are found inpyplume.statisticsTestingEach python file has an associated test file which contains unit test functions. As the package is developed, more functions will be added and integrated function tests will be added. Likewise, more information will be included here when possible.