def load(self): """ Load the contents of the input file into a PressureDependenceJob object. """ from arkane.pdep import PressureDependenceJob from arkane.input import load_input_file # Seed with a PdepJob object if self.pdep is None: self.pdep = PressureDependenceJob(network=None) if self.inputFileExists(): job_list = load_input_file(self.getInputFilename())[0] assert len(job_list) == 1 job = job_list[0] if isinstance(job, PressureDependenceJob) is False: raise Exception('Input file given did not provide a pressure dependence network.') self.pdep = job self.pdep.initialize() if self.pdep.network is not None: self.title = self.pdep.network.label self.save() return self.pdep.network
def load(self): """ Load the contents of the input file into a PressureDependenceJob object. """ from arkane.pdep import PressureDependenceJob from arkane.input import loadInputFile # Seed with a PdepJob object if self.pdep is None: self.pdep = PressureDependenceJob(network=None) if self.inputFileExists(): jobList = loadInputFile(self.getInputFilename())[0] assert len(jobList) == 1 job = jobList[0] if isinstance(job, PressureDependenceJob) is False: raise Exception('Input file given did not provide a pressure dependence network.') self.pdep = job self.pdep.initialize() if self.pdep.network is not None: self.title = self.pdep.network.label self.save() return self.pdep.network
def pressureDependence( method, temperatures, pressures, maximumGrainSize=0.0, minimumNumberOfGrains=0, interpolation=None, maximumAtoms=None, ): from arkane.pdep import PressureDependenceJob # Setting the pressureDependence attribute to non-None enables pressure dependence rmg.pressureDependence = PressureDependenceJob(network=None) # Process method rmg.pressureDependence.method = method # Process interpolation model if isinstance(interpolation, str): interpolation = (interpolation, ) if interpolation[0].lower() not in ("chebyshev", "pdeparrhenius"): raise InputError( "Interpolation model must be set to either 'Chebyshev' or 'PDepArrhenius'." ) rmg.pressureDependence.interpolationModel = interpolation # Process temperatures Tmin, Tmax, Tunits, Tcount = temperatures rmg.pressureDependence.Tmin = Quantity(Tmin, Tunits) rmg.pressureDependence.Tmax = Quantity(Tmax, Tunits) rmg.pressureDependence.Tcount = Tcount rmg.pressureDependence.generateTemperatureList() # Process pressures Pmin, Pmax, Punits, Pcount = pressures rmg.pressureDependence.Pmin = Quantity(Pmin, Punits) rmg.pressureDependence.Pmax = Quantity(Pmax, Punits) rmg.pressureDependence.Pcount = Pcount rmg.pressureDependence.generatePressureList() # Process grain size and count rmg.pressureDependence.maximumGrainSize = Quantity(maximumGrainSize) rmg.pressureDependence.minimumGrainCount = minimumNumberOfGrains # Process maximum atoms rmg.pressureDependence.maximumAtoms = maximumAtoms rmg.pressureDependence.activeJRotor = True rmg.pressureDependence.activeKRotor = True rmg.pressureDependence.rmgmode = True
def pressureDependence(label, Tmin=None, Tmax=None, Tcount=0, Tlist=None, Pmin=None, Pmax=None, Pcount=0, Plist=None, maximumGrainSize=None, minimumGrainCount=0, method=None, interpolationModel=None, activeKRotor=True, activeJRotor=True, rmgmode=False, sensitivity_conditions=None): """Generate a pressure dependent job""" global job_list, network_dict if isinstance(interpolationModel, str): interpolationModel = (interpolationModel, ) nwk = None if label in list(network_dict.keys()): nwk = network_dict[label] job = PressureDependenceJob(network=nwk, Tmin=Tmin, Tmax=Tmax, Tcount=Tcount, Tlist=Tlist, Pmin=Pmin, Pmax=Pmax, Pcount=Pcount, Plist=Plist, maximumGrainSize=maximumGrainSize, minimumGrainCount=minimumGrainCount, method=method, interpolationModel=interpolationModel, activeKRotor=activeKRotor, activeJRotor=activeJRotor, rmgmode=rmgmode, sensitivity_conditions=sensitivity_conditions) job_list.append(job)
def saveForm(self, posted, form): """ Save form data into input.py file specified by the path. """ # Clean past history self.rmg = RMG() # Databases #self.rmg.databaseDirectory = settings['database.directory'] self.rmg.thermoLibraries = [] if posted.thermo_libraries.all(): self.rmg.thermoLibraries = [ item.thermolib.encode() for item in posted.thermo_libraries.all() ] self.rmg.reactionLibraries = [] self.rmg.seedMechanisms = [] if posted.reaction_libraries.all(): for item in posted.reaction_libraries.all(): if not item.seedmech and not item.edge: self.rmg.reactionLibraries.append( (item.reactionlib.encode(), False)) elif not item.seedmech: self.rmg.reactionLibraries.append( (item.reactionlib.encode(), True)) else: self.rmg.seedMechanisms.append(item.reactionlib.encode()) self.rmg.statmechLibraries = [] self.rmg.kineticsDepositories = 'default' self.rmg.kineticsFamilies = 'default' self.rmg.kineticsEstimator = 'rate rules' # Species self.rmg.initialSpecies = [] speciesDict = {} initialMoleFractions = {} self.rmg.reactionModel = CoreEdgeReactionModel() for item in posted.reactor_species.all(): structure = Molecule().fromAdjacencyList(item.adjlist.encode()) spec, isNew = self.rmg.reactionModel.makeNewSpecies( structure, label=item.name.encode(), reactive=False if item.inert else True) self.rmg.initialSpecies.append(spec) speciesDict[item.name.encode()] = spec initialMoleFractions[spec] = item.molefrac # Reactor systems self.rmg.reactionSystems = [] for item in posted.reactor_systems.all(): T = Quantity(item.temperature, item.temperature_units.encode()) P = Quantity(item.pressure, item.pressure_units.encode()) termination = [] if item.conversion: termination.append( TerminationConversion(speciesDict[item.species.encode()], item.conversion)) termination.append( TerminationTime( Quantity(item.terminationtime, item.time_units.encode()))) # Sensitivity Analysis sensitiveSpecies = [] if item.sensitivity: if isinstance(item.sensitivity.encode(), str): sensitivity = item.sensitivity.encode().split(',') for spec in sensitivity: sensitiveSpecies.append(speciesDict[spec.strip()]) system = SimpleReactor(T, P, initialMoleFractions, termination, sensitiveSpecies, item.sensitivityThreshold) self.rmg.reactionSystems.append(system) # Simulator tolerances self.rmg.absoluteTolerance = form.cleaned_data['simulator_atol'] self.rmg.relativeTolerance = form.cleaned_data['simulator_rtol'] self.rmg.sensitivityAbsoluteTolerance = form.cleaned_data[ 'simulator_sens_atol'] self.rmg.sensitivityRelativeTolerance = form.cleaned_data[ 'simulator_sens_rtol'] self.rmg.fluxToleranceKeepInEdge = form.cleaned_data[ 'toleranceKeepInEdge'] self.rmg.fluxToleranceMoveToCore = form.cleaned_data[ 'toleranceMoveToCore'] self.rmg.fluxToleranceInterrupt = form.cleaned_data[ 'toleranceInterruptSimulation'] self.rmg.maximumEdgeSpecies = form.cleaned_data['maximumEdgeSpecies'] self.rmg.minCoreSizeForPrune = form.cleaned_data['minCoreSizeForPrune'] self.rmg.minSpeciesExistIterationsForPrune = form.cleaned_data[ 'minSpeciesExistIterationsForPrune'] self.rmg.filterReactions = form.cleaned_data['filterReactions'] # Pressure Dependence pdep = form.cleaned_data['pdep'].encode() if pdep != 'off': self.rmg.pressureDependence = PressureDependenceJob(network=None) self.rmg.pressureDependence.method = pdep # Process interpolation model if form.cleaned_data['interpolation'].encode() == 'chebyshev': self.rmg.pressureDependence.interpolationModel = ( form.cleaned_data['interpolation'].encode(), form.cleaned_data['temp_basis'], form.cleaned_data['p_basis']) else: self.rmg.pressureDependence.interpolationModel = ( form.cleaned_data['interpolation'].encode(), ) # Temperature and pressure range self.rmg.pressureDependence.Tmin = Quantity( form.cleaned_data['temp_low'], form.cleaned_data['temprange_units'].encode()) self.rmg.pressureDependence.Tmax = Quantity( form.cleaned_data['temp_high'], form.cleaned_data['temprange_units'].encode()) self.rmg.pressureDependence.Tcount = form.cleaned_data[ 'temp_interp'] self.rmg.pressureDependence.generateTemperatureList() self.rmg.pressureDependence.Pmin = Quantity( form.cleaned_data['p_low'], form.cleaned_data['prange_units'].encode()) self.rmg.pressureDependence.Pmax = Quantity( form.cleaned_data['p_high'], form.cleaned_data['prange_units'].encode()) self.rmg.pressureDependence.Pcount = form.cleaned_data['p_interp'] self.rmg.pressureDependence.generatePressureList() # Process grain size and count self.rmg.pressureDependence.grainSize = Quantity( form.cleaned_data['maximumGrainSize'], form.cleaned_data['grainsize_units'].encode()) self.rmg.pressureDependence.grainCount = form.cleaned_data[ 'minimumNumberOfGrains'] self.rmg.pressureDependence.maximumAtoms = form.cleaned_data[ 'maximumAtoms'] # Additional Options self.rmg.units = 'si' self.rmg.saveRestartPeriod = Quantity( form.cleaned_data['saveRestartPeriod'], form.cleaned_data['saveRestartPeriodUnits'].encode( )) if form.cleaned_data['saveRestartPeriod'] else None self.rmg.generateOutputHTML = form.cleaned_data['generateOutputHTML'] self.rmg.generatePlots = form.cleaned_data['generatePlots'] self.rmg.saveSimulationProfiles = form.cleaned_data[ 'saveSimulationProfiles'] self.rmg.saveEdgeSpecies = form.cleaned_data['saveEdgeSpecies'] self.rmg.verboseComments = form.cleaned_data['verboseComments'] # Species Constraints speciesConstraints = form.cleaned_data['speciesConstraints'] if speciesConstraints == 'on': allowed = [] if form.cleaned_data['allowed_inputSpecies']: allowed.append('input species') if form.cleaned_data['allowed_seedMechanisms']: allowed.append('seed mechanisms') if form.cleaned_data['allowed_reactionLibraries']: allowed.append('reaction libraries') self.rmg.speciesConstraints['allowed'] = allowed self.rmg.speciesConstraints[ 'maximumCarbonAtoms'] = form.cleaned_data['maximumCarbonAtoms'] self.rmg.speciesConstraints[ 'maximumOxygenAtoms'] = form.cleaned_data['maximumOxygenAtoms'] self.rmg.speciesConstraints[ 'maximumNitrogenAtoms'] = form.cleaned_data[ 'maximumNitrogenAtoms'] self.rmg.speciesConstraints[ 'maximumSiliconAtoms'] = form.cleaned_data[ 'maximumSiliconAtoms'] self.rmg.speciesConstraints[ 'maximumSulfurAtoms'] = form.cleaned_data['maximumSulfurAtoms'] self.rmg.speciesConstraints[ 'maximumHeavyAtoms'] = form.cleaned_data['maximumHeavyAtoms'] self.rmg.speciesConstraints[ 'maximumRadicalElectrons'] = form.cleaned_data[ 'maximumRadicalElectrons'] self.rmg.speciesConstraints['allowSingletO2'] = form.cleaned_data[ 'allowSingletO2'] # Quantum Calculations quantumCalc = form.cleaned_data['quantumCalc'] if quantumCalc == 'on': from rmgpy.qm.main import QMCalculator self.rmg.quantumMechanics = QMCalculator( software=form.cleaned_data['software'].encode(), method=form.cleaned_data['method'].encode(), fileStore=form.cleaned_data['fileStore'].encode(), scratchDirectory=form.cleaned_data['scratchDirectory'].encode( ), onlyCyclics=form.cleaned_data['onlyCyclics'], maxRadicalNumber=form.cleaned_data['maxRadicalNumber'], ) # Save the input.py file self.rmg.saveInput(self.savepath)
class Network(models.Model): """ A Django model of a pressure-dependent reaction network. """ id = models.CharField(max_length=32, primary_key=True, default=_createId) title = models.CharField(max_length=50) input_file = models.FileField(upload_to=uploadTo, verbose_name='Input file') input_text = models.TextField(blank=True, verbose_name='') user = models.ForeignKey(User, on_delete=models.CASCADE) def __init__(self, *args, **kwargs): super(Network, self).__init__(*args, **kwargs) self.pdep = None def getDirname(self): """ Return the absolute path of the directory that the Network object uses to store files. """ return os.path.join(settings.MEDIA_ROOT, 'pdep', 'networks', str(self.pk)) def getInputFilename(self): """ Return the absolute path of the input file. """ return os.path.join(self.getDirname(), 'input.py') def getOutputFilename(self): """ Return the absolute path of the output file. """ return os.path.join(self.getDirname(), 'output.py') def getLogFilename(self): """ Return the absolute path of the log file. """ return os.path.join(self.getDirname(), 'arkane.log') def getSurfaceFilenamePNG(self): """ Return the absolute path of the PES image file in PNG format. """ return os.path.join(self.getDirname(), 'network.png') def getSurfaceFilenamePDF(self): """ Return the absolute path of the PES image file in PDF format. """ return os.path.join(self.getDirname(), 'network.pdf') def getSurfaceFilenameSVG(self): """ Return the absolute path of the PES image file in SVG format. """ return os.path.join(self.getDirname(), 'network.svg') def getLastModifiedDate(self): """ Return the date on which the network was most recently modified. """ if not self.inputFileExists(): return 'unknown' mtime = os.path.getmtime(self.getInputFilename()) if self.outputFileExists(): mtime0 = os.path.getmtime(self.getOutputFilename()) if mtime < mtime0: mtime = mtime0 if self.surfaceFilePDFExists(): mtime0 = os.path.getmtime(self.getSurfaceFilenamePDF()) if mtime < mtime0: mtime = mtime0 if self.surfaceFilePNGExists(): mtime0 = os.path.getmtime(self.getSurfaceFilenamePNG()) if mtime < mtime0: mtime = mtime0 if self.surfaceFileSVGExists(): mtime0 = os.path.getmtime(self.getSurfaceFilenameSVG()) if mtime < mtime0: mtime = mtime0 gmtime = time.gmtime(mtime) return time.strftime("%d %b %Y", gmtime) def inputFileExists(self): """ Return ``True`` if the input file exists on the server or ``False`` if not. """ return os.path.exists(self.getInputFilename()) def outputFileExists(self): """ Return ``True`` if the output file exists on the server or ``False`` if not. """ return os.path.exists(self.getOutputFilename()) def logFileExists(self): """ Return ``True`` if the log file exists on the server or ``False`` if not. """ return os.path.exists(self.getLogFilename()) def surfaceFilePNGExists(self): """ Return ``True`` if a potential energy surface PNG image file exists or ``False`` if not. """ return os.path.exists(self.getSurfaceFilenamePNG()) def surfaceFilePDFExists(self): """ Return ``True`` if a potential energy surface PDF image file exists or ``False`` if not. """ return os.path.exists(self.getSurfaceFilenamePDF()) def surfaceFileSVGExists(self): """ Return ``True`` if a potential energy surface SVG image file exists or ``False`` if not. """ return os.path.exists(self.getSurfaceFilenameSVG()) def outputFileOutOfDate(self): """ Return ``True`` if the output file is out of date or ``False`` if not. """ return self.outputFileExists() and os.path.getmtime(self.getInputFilename()) > os.path.getmtime(self.getOutputFilename()) def surfaceFilePNGOutOfDate(self): """ Return ``True`` if a potential energy surface PNG image file is out of date or ``False`` if not. """ return self.surfaceFilePNGExists() and os.path.getmtime(self.getInputFilename()) > os.path.getmtime(self.getSurfaceFilenamePNG()) def surfaceFilePDFOutOfDate(self): """ Return ``True`` if a potential energy surface PDF image file is out of date or ``False`` if not. """ return self.surfaceFilePDFExists() and os.path.getmtime(self.getInputFilename()) > os.path.getmtime(self.getSurfaceFilenamePDF()) def surfaceFileSVGOutOfDate(self): """ Return ``True`` if a potential energy surface SVG image file is out of date or ``False`` if not. """ return self.surfaceFileSVGExists() and os.path.getmtime(self.getInputFilename()) > os.path.getmtime(self.getSurfaceFilenameSVG()) def createDir(self): """ Create the directory (and any other needed parent directories) that the Network uses for storing files. """ try: os.makedirs(self.getDirname()) except OSError: # Fail silently on any OS errors pass def deleteInputFile(self): """ Delete the input file for this network from the server. """ if self.inputFileExists(): os.remove(self.getInputFilename()) def deleteOutputFile(self): """ Delete the output file for this network from the server. """ if self.outputFileExists(): os.remove(self.getOutputFilename()) def deleteSurfaceFilePNG(self): """ Delete the PES image file in PNF format for this network from the server. """ if os.path.exists(self.getSurfaceFilenamePNG()): os.remove(self.getSurfaceFilenamePNG()) def deleteSurfaceFilePDF(self): """ Delete the PES image file in PDF format for this network from the server. """ if os.path.exists(self.getSurfaceFilenamePDF()): os.remove(self.getSurfaceFilenamePDF()) def deleteSurfaceFileSVG(self): """ Delete the PES image file in SVG format for this network from the server. """ if os.path.exists(self.getSurfaceFilenameSVG()): os.remove(self.getSurfaceFilenameSVG()) def loadInputText(self): """ Load the input file text into the inputText field. """ self.inputText = '' if self.inputFileExists(): f = open(self.getInputFilename(), 'r') for line in f: self.inputText += line f.close() def saveInputText(self): """ Save the contents of the inputText field to the input file. """ f_path = self.getInputFilename() self.createDir() f = open(f_path, 'w') for line in self.inputText.splitlines(): f.write(line + '\n') f.close() def load(self): """ Load the contents of the input file into a PressureDependenceJob object. """ from arkane.pdep import PressureDependenceJob from arkane.input import load_input_file # Seed with a PdepJob object if self.pdep is None: self.pdep = PressureDependenceJob(network=None) if self.inputFileExists(): job_list = load_input_file(self.getInputFilename())[0] assert len(job_list) == 1 job = job_list[0] if isinstance(job, PressureDependenceJob) is False: raise Exception('Input file given did not provide a pressure dependence network.') self.pdep = job self.pdep.initialize() if self.pdep.network is not None: self.title = self.pdep.network.label self.save() return self.pdep.network
def loadFAMEInput(path, moleculeDict=None): """ Load the contents of a FAME input file into the MEASURE object. FAME is an early version of MEASURE written in Fortran and used by RMG-Java. This script enables importing FAME input files into MEASURE so we can use the additional functionality that MEASURE provides. Note that it is mostly designed to load the FAME input files generated automatically by RMG-Java, and may not load hand-crafted FAME input files. If you specify a `moleculeDict`, then this script will use it to associate the species with their structures. """ def readMeaningfulLine(f): line = f.readline() while line != '': line = line.strip() if len(line) > 0 and line[0] != '#': return line else: line = f.readline() return '' moleculeDict = moleculeDict or {} logging.info('Loading file "{0}"...'.format(path)) f = open(path) job = PressureDependenceJob(network=None) # Read method method = readMeaningfulLine(f).lower() if method == 'modifiedstrongcollision': job.method = 'modified strong collision' elif method == 'reservoirstate': job.method = 'reservoir state' # Read temperatures Tcount, Tunits, Tmin, Tmax = readMeaningfulLine(f).split() job.Tmin = Quantity(float(Tmin), Tunits) job.Tmax = Quantity(float(Tmax), Tunits) job.Tcount = int(Tcount) Tlist = [] for i in range(int(Tcount)): Tlist.append(float(readMeaningfulLine(f))) job.Tlist = Quantity(Tlist, Tunits) # Read pressures Pcount, Punits, Pmin, Pmax = readMeaningfulLine(f).split() job.Pmin = Quantity(float(Pmin), Punits) job.Pmax = Quantity(float(Pmax), Punits) job.Pcount = int(Pcount) Plist = [] for i in range(int(Pcount)): Plist.append(float(readMeaningfulLine(f))) job.Plist = Quantity(Plist, Punits) # Read interpolation model model = readMeaningfulLine(f).split() if model[0].lower() == 'chebyshev': job.interpolationModel = ('chebyshev', int(model[1]), int(model[2])) elif model[0].lower() == 'pdeparrhenius': job.interpolationModel = ('pdeparrhenius', ) # Read grain size or number of grains job.minimumGrainCount = 0 job.maximumGrainSize = None for i in range(2): data = readMeaningfulLine(f).split() if data[0].lower() == 'numgrains': job.minimumGrainCount = int(data[1]) elif data[0].lower() == 'grainsize': job.maximumGrainSize = (float(data[2]), data[1]) # A FAME file is almost certainly created during an RMG job, so use RMG mode job.rmgmode = True # Create the Network job.network = Network() # Read collision model data = readMeaningfulLine(f) assert data.lower() == 'singleexpdown' alpha0units, alpha0 = readMeaningfulLine(f).split() T0units, T0 = readMeaningfulLine(f).split() n = readMeaningfulLine(f) energyTransferModel = SingleExponentialDown( alpha0=Quantity(float(alpha0), alpha0units), T0=Quantity(float(T0), T0units), n=float(n), ) speciesDict = {} # Read bath gas parameters bathGas = Species(label='bath_gas', energyTransferModel=energyTransferModel) molWtunits, molWt = readMeaningfulLine(f).split() if molWtunits == 'u': molWtunits = 'amu' bathGas.molecularWeight = Quantity(float(molWt), molWtunits) sigmaLJunits, sigmaLJ = readMeaningfulLine(f).split() epsilonLJunits, epsilonLJ = readMeaningfulLine(f).split() assert epsilonLJunits == 'J' bathGas.transportData = TransportData( sigma=Quantity(float(sigmaLJ), sigmaLJunits), epsilon=Quantity(float(epsilonLJ) / constants.kB, 'K'), ) job.network.bathGas = {bathGas: 1.0} # Read species data Nspec = int(readMeaningfulLine(f)) for i in range(Nspec): species = Species() species.conformer = Conformer() species.energyTransferModel = energyTransferModel # Read species label species.label = readMeaningfulLine(f) speciesDict[species.label] = species if species.label in moleculeDict: species.molecule = [moleculeDict[species.label]] # Read species E0 E0units, E0 = readMeaningfulLine(f).split() species.conformer.E0 = Quantity(float(E0), E0units) species.conformer.E0.units = 'kJ/mol' # Read species thermo data H298units, H298 = readMeaningfulLine(f).split() S298units, S298 = readMeaningfulLine(f).split() Cpcount, Cpunits = readMeaningfulLine(f).split() Cpdata = [] for i in range(int(Cpcount)): Cpdata.append(float(readMeaningfulLine(f))) if S298units == 'J/mol*K': S298units = 'J/(mol*K)' if Cpunits == 'J/mol*K': Cpunits = 'J/(mol*K)' species.thermo = ThermoData( H298=Quantity(float(H298), H298units), S298=Quantity(float(S298), S298units), Tdata=Quantity([300, 400, 500, 600, 800, 1000, 1500], "K"), Cpdata=Quantity(Cpdata, Cpunits), Cp0=(Cpdata[0], Cpunits), CpInf=(Cpdata[-1], Cpunits), ) # Read species collision parameters molWtunits, molWt = readMeaningfulLine(f).split() if molWtunits == 'u': molWtunits = 'amu' species.molecularWeight = Quantity(float(molWt), molWtunits) sigmaLJunits, sigmaLJ = readMeaningfulLine(f).split() epsilonLJunits, epsilonLJ = readMeaningfulLine(f).split() assert epsilonLJunits == 'J' species.transportData = TransportData( sigma=Quantity(float(sigmaLJ), sigmaLJunits), epsilon=Quantity(float(epsilonLJ) / constants.kB, 'K'), ) # Read species vibrational frequencies freqCount, freqUnits = readMeaningfulLine(f).split() frequencies = [] for j in range(int(freqCount)): frequencies.append(float(readMeaningfulLine(f))) species.conformer.modes.append( HarmonicOscillator(frequencies=Quantity(frequencies, freqUnits), )) # Read species external rotors rotCount, rotUnits = readMeaningfulLine(f).split() if int(rotCount) > 0: raise NotImplementedError( 'Cannot handle external rotational modes in FAME input.') # Read species internal rotors freqCount, freqUnits = readMeaningfulLine(f).split() frequencies = [] for j in range(int(freqCount)): frequencies.append(float(readMeaningfulLine(f))) barrCount, barrUnits = readMeaningfulLine(f).split() barriers = [] for j in range(int(barrCount)): barriers.append(float(readMeaningfulLine(f))) if barrUnits == 'cm^-1': barrUnits = 'J/mol' barriers = [ barr * constants.h * constants.c * constants.Na * 100. for barr in barriers ] elif barrUnits in ['Hz', 's^-1']: barrUnits = 'J/mol' barriers = [barr * constants.h * constants.Na for barr in barriers] elif barrUnits != 'J/mol': raise Exception( 'Unexpected units "{0}" for hindered rotor barrier height.'. format(barrUnits)) inertia = [ V0 / 2.0 / (nu * constants.c * 100.)**2 / constants.Na for nu, V0 in zip(frequencies, barriers) ] for I, V0 in zip(inertia, barriers): species.conformer.modes.append( HinderedRotor( inertia=Quantity(I, "kg*m^2"), barrier=Quantity(V0, barrUnits), symmetry=1, semiclassical=False, )) # Read overall symmetry number species.conformer.spinMultiplicity = int(readMeaningfulLine(f)) # Read isomer, reactant channel, and product channel data Nisom = int(readMeaningfulLine(f)) Nreac = int(readMeaningfulLine(f)) Nprod = int(readMeaningfulLine(f)) for i in range(Nisom): data = readMeaningfulLine(f).split() assert data[0] == '1' job.network.isomers.append(speciesDict[data[1]]) for i in range(Nreac): data = readMeaningfulLine(f).split() assert data[0] == '2' job.network.reactants.append( [speciesDict[data[1]], speciesDict[data[2]]]) for i in range(Nprod): data = readMeaningfulLine(f).split() if data[0] == '1': job.network.products.append([speciesDict[data[1]]]) elif data[0] == '2': job.network.products.append( [speciesDict[data[1]], speciesDict[data[2]]]) # Read path reactions Nrxn = int(readMeaningfulLine(f)) for i in range(Nrxn): # Read and ignore reaction equation equation = readMeaningfulLine(f) reaction = Reaction(transitionState=TransitionState(), reversible=True) job.network.pathReactions.append(reaction) reaction.transitionState.conformer = Conformer() # Read reactant and product indices data = readMeaningfulLine(f).split() reac = int(data[0]) - 1 prod = int(data[1]) - 1 if reac < Nisom: reaction.reactants = [job.network.isomers[reac]] elif reac < Nisom + Nreac: reaction.reactants = job.network.reactants[reac - Nisom] else: reaction.reactants = job.network.products[reac - Nisom - Nreac] if prod < Nisom: reaction.products = [job.network.isomers[prod]] elif prod < Nisom + Nreac: reaction.products = job.network.reactants[prod - Nisom] else: reaction.products = job.network.products[prod - Nisom - Nreac] # Read reaction E0 E0units, E0 = readMeaningfulLine(f).split() reaction.transitionState.conformer.E0 = Quantity(float(E0), E0units) reaction.transitionState.conformer.E0.units = 'kJ/mol' # Read high-pressure limit kinetics data = readMeaningfulLine(f) assert data.lower() == 'arrhenius' Aunits, A = readMeaningfulLine(f).split() if '/' in Aunits: index = Aunits.find('/') Aunits = '{0}/({1})'.format(Aunits[0:index], Aunits[index + 1:]) Eaunits, Ea = readMeaningfulLine(f).split() n = readMeaningfulLine(f) reaction.kinetics = Arrhenius( A=Quantity(float(A), Aunits), Ea=Quantity(float(Ea), Eaunits), n=Quantity(float(n)), ) reaction.kinetics.Ea.units = 'kJ/mol' f.close() job.network.isomers = [ Configuration(isomer) for isomer in job.network.isomers ] job.network.reactants = [ Configuration(*reactants) for reactants in job.network.reactants ] job.network.products = [ Configuration(*products) for products in job.network.products ] return job
def loadFAMEInput(path, moleculeDict=None): """ Load the contents of a FAME input file into the MEASURE object. FAME is an early version of MEASURE written in Fortran and used by RMG-Java. This script enables importing FAME input files into MEASURE so we can use the additional functionality that MEASURE provides. Note that it is mostly designed to load the FAME input files generated automatically by RMG-Java, and may not load hand-crafted FAME input files. If you specify a `moleculeDict`, then this script will use it to associate the species with their structures. """ def readMeaningfulLine(f): line = f.readline() while line != '': line = line.strip() if len(line) > 0 and line[0] != '#': return line else: line = f.readline() return '' moleculeDict = moleculeDict or {} logging.info('Loading file "{0}"...'.format(path)) f = open(path) job = PressureDependenceJob(network=None) # Read method method = readMeaningfulLine(f).lower() if method == 'modifiedstrongcollision': job.method = 'modified strong collision' elif method == 'reservoirstate': job.method = 'reservoir state' # Read temperatures Tcount, Tunits, Tmin, Tmax = readMeaningfulLine(f).split() job.Tmin = Quantity(float(Tmin), Tunits) job.Tmax = Quantity(float(Tmax), Tunits) job.Tcount = int(Tcount) Tlist = [] for i in range(int(Tcount)): Tlist.append(float(readMeaningfulLine(f))) job.Tlist = Quantity(Tlist, Tunits) # Read pressures Pcount, Punits, Pmin, Pmax = readMeaningfulLine(f).split() job.Pmin = Quantity(float(Pmin), Punits) job.Pmax = Quantity(float(Pmax), Punits) job.Pcount = int(Pcount) Plist = [] for i in range(int(Pcount)): Plist.append(float(readMeaningfulLine(f))) job.Plist = Quantity(Plist, Punits) # Read interpolation model model = readMeaningfulLine(f).split() if model[0].lower() == 'chebyshev': job.interpolationModel = ('chebyshev', int(model[1]), int(model[2])) elif model[0].lower() == 'pdeparrhenius': job.interpolationModel = ('pdeparrhenius',) # Read grain size or number of grains job.minimumGrainCount = 0 job.maximumGrainSize = None for i in range(2): data = readMeaningfulLine(f).split() if data[0].lower() == 'numgrains': job.minimumGrainCount = int(data[1]) elif data[0].lower() == 'grainsize': job.maximumGrainSize = (float(data[2]), data[1]) # A FAME file is almost certainly created during an RMG job, so use RMG mode job.rmgmode = True # Create the Network job.network = Network() # Read collision model data = readMeaningfulLine(f) assert data.lower() == 'singleexpdown' alpha0units, alpha0 = readMeaningfulLine(f).split() T0units, T0 = readMeaningfulLine(f).split() n = readMeaningfulLine(f) energyTransferModel = SingleExponentialDown( alpha0 = Quantity(float(alpha0), alpha0units), T0 = Quantity(float(T0), T0units), n = float(n), ) speciesDict = {} # Read bath gas parameters bathGas = Species(label='bath_gas', energyTransferModel=energyTransferModel) molWtunits, molWt = readMeaningfulLine(f).split() if molWtunits == 'u': molWtunits = 'amu' bathGas.molecularWeight = Quantity(float(molWt), molWtunits) sigmaLJunits, sigmaLJ = readMeaningfulLine(f).split() epsilonLJunits, epsilonLJ = readMeaningfulLine(f).split() assert epsilonLJunits == 'J' bathGas.transportData = TransportData( sigma = Quantity(float(sigmaLJ), sigmaLJunits), epsilon = Quantity(float(epsilonLJ) / constants.kB, 'K'), ) job.network.bathGas = {bathGas: 1.0} # Read species data Nspec = int(readMeaningfulLine(f)) for i in range(Nspec): species = Species() species.conformer = Conformer() species.energyTransferModel = energyTransferModel # Read species label species.label = readMeaningfulLine(f) speciesDict[species.label] = species if species.label in moleculeDict: species.molecule = [moleculeDict[species.label]] # Read species E0 E0units, E0 = readMeaningfulLine(f).split() species.conformer.E0 = Quantity(float(E0), E0units) species.conformer.E0.units = 'kJ/mol' # Read species thermo data H298units, H298 = readMeaningfulLine(f).split() S298units, S298 = readMeaningfulLine(f).split() Cpcount, Cpunits = readMeaningfulLine(f).split() Cpdata = [] for i in range(int(Cpcount)): Cpdata.append(float(readMeaningfulLine(f))) if S298units == 'J/mol*K': S298units = 'J/(mol*K)' if Cpunits == 'J/mol*K': Cpunits = 'J/(mol*K)' species.thermo = ThermoData( H298 = Quantity(float(H298), H298units), S298 = Quantity(float(S298), S298units), Tdata = Quantity([300,400,500,600,800,1000,1500], "K"), Cpdata = Quantity(Cpdata, Cpunits), Cp0 = (Cpdata[0], Cpunits), CpInf = (Cpdata[-1], Cpunits), ) # Read species collision parameters molWtunits, molWt = readMeaningfulLine(f).split() if molWtunits == 'u': molWtunits = 'amu' species.molecularWeight = Quantity(float(molWt), molWtunits) sigmaLJunits, sigmaLJ = readMeaningfulLine(f).split() epsilonLJunits, epsilonLJ = readMeaningfulLine(f).split() assert epsilonLJunits == 'J' species.transportData = TransportData( sigma = Quantity(float(sigmaLJ), sigmaLJunits), epsilon = Quantity(float(epsilonLJ) / constants.kB, 'K'), ) # Read species vibrational frequencies freqCount, freqUnits = readMeaningfulLine(f).split() frequencies = [] for j in range(int(freqCount)): frequencies.append(float(readMeaningfulLine(f))) species.conformer.modes.append(HarmonicOscillator( frequencies = Quantity(frequencies, freqUnits), )) # Read species external rotors rotCount, rotUnits = readMeaningfulLine(f).split() if int(rotCount) > 0: raise NotImplementedError('Cannot handle external rotational modes in FAME input.') # Read species internal rotors freqCount, freqUnits = readMeaningfulLine(f).split() frequencies = [] for j in range(int(freqCount)): frequencies.append(float(readMeaningfulLine(f))) barrCount, barrUnits = readMeaningfulLine(f).split() barriers = [] for j in range(int(barrCount)): barriers.append(float(readMeaningfulLine(f))) if barrUnits == 'cm^-1': barrUnits = 'J/mol' barriers = [barr * constants.h * constants.c * constants.Na * 100. for barr in barriers] elif barrUnits in ['Hz', 's^-1']: barrUnits = 'J/mol' barriers = [barr * constants.h * constants.Na for barr in barriers] elif barrUnits != 'J/mol': raise Exception('Unexpected units "{0}" for hindered rotor barrier height.'.format(barrUnits)) inertia = [V0 / 2.0 / (nu * constants.c * 100.)**2 / constants.Na for nu, V0 in zip(frequencies, barriers)] for I, V0 in zip(inertia, barriers): species.conformer.modes.append(HinderedRotor( inertia = Quantity(I,"kg*m^2"), barrier = Quantity(V0,barrUnits), symmetry = 1, semiclassical = False, )) # Read overall symmetry number species.conformer.spinMultiplicity = int(readMeaningfulLine(f)) # Read isomer, reactant channel, and product channel data Nisom = int(readMeaningfulLine(f)) Nreac = int(readMeaningfulLine(f)) Nprod = int(readMeaningfulLine(f)) for i in range(Nisom): data = readMeaningfulLine(f).split() assert data[0] == '1' job.network.isomers.append(speciesDict[data[1]]) for i in range(Nreac): data = readMeaningfulLine(f).split() assert data[0] == '2' job.network.reactants.append([speciesDict[data[1]], speciesDict[data[2]]]) for i in range(Nprod): data = readMeaningfulLine(f).split() if data[0] == '1': job.network.products.append([speciesDict[data[1]]]) elif data[0] == '2': job.network.products.append([speciesDict[data[1]], speciesDict[data[2]]]) # Read path reactions Nrxn = int(readMeaningfulLine(f)) for i in range(Nrxn): # Read and ignore reaction equation equation = readMeaningfulLine(f) reaction = Reaction(transitionState=TransitionState(), reversible=True) job.network.pathReactions.append(reaction) reaction.transitionState.conformer = Conformer() # Read reactant and product indices data = readMeaningfulLine(f).split() reac = int(data[0]) - 1 prod = int(data[1]) - 1 if reac < Nisom: reaction.reactants = [job.network.isomers[reac]] elif reac < Nisom+Nreac: reaction.reactants = job.network.reactants[reac-Nisom] else: reaction.reactants = job.network.products[reac-Nisom-Nreac] if prod < Nisom: reaction.products = [job.network.isomers[prod]] elif prod < Nisom+Nreac: reaction.products = job.network.reactants[prod-Nisom] else: reaction.products = job.network.products[prod-Nisom-Nreac] # Read reaction E0 E0units, E0 = readMeaningfulLine(f).split() reaction.transitionState.conformer.E0 = Quantity(float(E0), E0units) reaction.transitionState.conformer.E0.units = 'kJ/mol' # Read high-pressure limit kinetics data = readMeaningfulLine(f) assert data.lower() == 'arrhenius' Aunits, A = readMeaningfulLine(f).split() if '/' in Aunits: index = Aunits.find('/') Aunits = '{0}/({1})'.format(Aunits[0:index], Aunits[index+1:]) Eaunits, Ea = readMeaningfulLine(f).split() n = readMeaningfulLine(f) reaction.kinetics = Arrhenius( A = Quantity(float(A), Aunits), Ea = Quantity(float(Ea), Eaunits), n = Quantity(float(n)), ) reaction.kinetics.Ea.units = 'kJ/mol' f.close() job.network.isomers = [Configuration(isomer) for isomer in job.network.isomers] job.network.reactants = [Configuration(*reactants) for reactants in job.network.reactants] job.network.products = [Configuration(*products) for products in job.network.products] return job
class Network(models.Model): """ A Django model of a pressure-dependent reaction network. """ id = models.CharField(max_length=32, primary_key=True, default=_createId) title = models.CharField(max_length=50) inputFile = models.FileField(upload_to=uploadTo, verbose_name='Input file') inputText = models.TextField(blank=True, verbose_name='') user = models.ForeignKey(User) def __init__(self, *args, **kwargs): super(Network, self).__init__(*args, **kwargs) self.pdep = None def getDirname(self): """ Return the absolute path of the directory that the Network object uses to store files. """ return os.path.join(settings.MEDIA_ROOT, 'pdep', 'networks', str(self.pk)) def getInputFilename(self): """ Return the absolute path of the input file. """ return os.path.join(self.getDirname(), 'input.py') def getOutputFilename(self): """ Return the absolute path of the output file. """ return os.path.join(self.getDirname(), 'output.py') def getLogFilename(self): """ Return the absolute path of the log file. """ return os.path.join(self.getDirname(), 'arkane.log') def getSurfaceFilenamePNG(self): """ Return the absolute path of the PES image file in PNG format. """ return os.path.join(self.getDirname(), 'network.png') def getSurfaceFilenamePDF(self): """ Return the absolute path of the PES image file in PDF format. """ return os.path.join(self.getDirname(), 'network.pdf') def getSurfaceFilenameSVG(self): """ Return the absolute path of the PES image file in SVG format. """ return os.path.join(self.getDirname(), 'network.svg') def getLastModifiedDate(self): """ Return the date on which the network was most recently modified. """ if not self.inputFileExists(): return 'unknown' mtime = os.path.getmtime(self.getInputFilename()) if self.outputFileExists(): mtime0 = os.path.getmtime(self.getOutputFilename()) if mtime < mtime0: mtime = mtime0 if self.surfaceFilePDFExists(): mtime0 = os.path.getmtime(self.getSurfaceFilenamePDF()) if mtime < mtime0: mtime = mtime0 if self.surfaceFilePNGExists(): mtime0 = os.path.getmtime(self.getSurfaceFilenamePNG()) if mtime < mtime0: mtime = mtime0 if self.surfaceFileSVGExists(): mtime0 = os.path.getmtime(self.getSurfaceFilenameSVG()) if mtime < mtime0: mtime = mtime0 gmtime = time.gmtime(mtime) return time.strftime("%d %b %Y", gmtime) def inputFileExists(self): """ Return ``True`` if the input file exists on the server or ``False`` if not. """ return os.path.exists(self.getInputFilename()) def outputFileExists(self): """ Return ``True`` if the output file exists on the server or ``False`` if not. """ return os.path.exists(self.getOutputFilename()) def logFileExists(self): """ Return ``True`` if the log file exists on the server or ``False`` if not. """ return os.path.exists(self.getLogFilename()) def surfaceFilePNGExists(self): """ Return ``True`` if a potential energy surface PNG image file exists or ``False`` if not. """ return os.path.exists(self.getSurfaceFilenamePNG()) def surfaceFilePDFExists(self): """ Return ``True`` if a potential energy surface PDF image file exists or ``False`` if not. """ return os.path.exists(self.getSurfaceFilenamePDF()) def surfaceFileSVGExists(self): """ Return ``True`` if a potential energy surface SVG image file exists or ``False`` if not. """ return os.path.exists(self.getSurfaceFilenameSVG()) def outputFileOutOfDate(self): """ Return ``True`` if the output file is out of date or ``False`` if not. """ return self.outputFileExists() and os.path.getmtime(self.getInputFilename()) > os.path.getmtime(self.getOutputFilename()) def surfaceFilePNGOutOfDate(self): """ Return ``True`` if a potential energy surface PNG image file is out of date or ``False`` if not. """ return self.surfaceFilePNGExists() and os.path.getmtime(self.getInputFilename()) > os.path.getmtime(self.getSurfaceFilenamePNG()) def surfaceFilePDFOutOfDate(self): """ Return ``True`` if a potential energy surface PDF image file is out of date or ``False`` if not. """ return self.surfaceFilePDFExists() and os.path.getmtime(self.getInputFilename()) > os.path.getmtime(self.getSurfaceFilenamePDF()) def surfaceFileSVGOutOfDate(self): """ Return ``True`` if a potential energy surface SVG image file is out of date or ``False`` if not. """ return self.surfaceFileSVGExists() and os.path.getmtime(self.getInputFilename()) > os.path.getmtime(self.getSurfaceFilenameSVG()) def createDir(self): """ Create the directory (and any other needed parent directories) that the Network uses for storing files. """ try: os.makedirs(self.getDirname()) except OSError: # Fail silently on any OS errors pass def deleteInputFile(self): """ Delete the input file for this network from the server. """ if self.inputFileExists(): os.remove(self.getInputFilename()) def deleteOutputFile(self): """ Delete the output file for this network from the server. """ if self.outputFileExists(): os.remove(self.getOutputFilename()) def deleteSurfaceFilePNG(self): """ Delete the PES image file in PNF format for this network from the server. """ if os.path.exists(self.getSurfaceFilenamePNG()): os.remove(self.getSurfaceFilenamePNG()) def deleteSurfaceFilePDF(self): """ Delete the PES image file in PDF format for this network from the server. """ if os.path.exists(self.getSurfaceFilenamePDF()): os.remove(self.getSurfaceFilenamePDF()) def deleteSurfaceFileSVG(self): """ Delete the PES image file in SVG format for this network from the server. """ if os.path.exists(self.getSurfaceFilenameSVG()): os.remove(self.getSurfaceFilenameSVG()) def loadInputText(self): """ Load the input file text into the inputText field. """ self.inputText = '' if self.inputFileExists(): f = open(self.getInputFilename(),'r') for line in f: self.inputText += line f.close() def saveInputText(self): """ Save the contents of the inputText field to the input file. """ fpath = self.getInputFilename() self.createDir() f = open(fpath,'w') for line in self.inputText.splitlines(): f.write(line + '\n') f.close() def load(self): """ Load the contents of the input file into a PressureDependenceJob object. """ from arkane.pdep import PressureDependenceJob from arkane.input import loadInputFile # Seed with a PdepJob object if self.pdep is None: self.pdep = PressureDependenceJob(network=None) if self.inputFileExists(): jobList = loadInputFile(self.getInputFilename())[0] assert len(jobList) == 1 job = jobList[0] if isinstance(job, PressureDependenceJob) is False: raise Exception('Input file given did not provide a pressure dependence network.') self.pdep = job self.pdep.initialize() if self.pdep.network is not None: self.title = self.pdep.network.label self.save() return self.pdep.network