diff --git a/bld.bat b/.conda/bld.bat similarity index 100% rename from bld.bat rename to .conda/bld.bat diff --git a/build.sh b/.conda/build.sh similarity index 100% rename from build.sh rename to .conda/build.sh diff --git a/meta.yaml b/.conda/meta.yaml similarity index 96% rename from meta.yaml rename to .conda/meta.yaml index 142f12d0ce..f7b5531ae4 100644 --- a/meta.yaml +++ b/.conda/meta.yaml @@ -4,7 +4,7 @@ package: version: {{ environ.get('GIT_DESCRIBE_TAG', '') }} source: - path: . + path: ../ build: number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} @@ -48,6 +48,7 @@ requirements: - matplotlib >=1.5 - mock - mopac + - mpmath - nose - {{ pin_compatible('numpy') }} - openbabel >=2.4.1 @@ -62,11 +63,12 @@ requirements: - pyzmq - quantities - rdkit >=2015.09.2 - - rmgdatabase >=2.2.0 + - rmgdatabase >=2.3.0 - scipy - scoop - symmetry - xlwt + - dde test: source_files: diff --git a/.coveragerc b/.coveragerc index d24eb6b540..19ce464b9f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -17,6 +17,7 @@ exclude_lines = raise NotImplementedError if 0: if __name__ == .__main__.: +omit = *Test.py [html] directory = testing/coverage diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index bf4564a626..f32d24944a 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -11,7 +11,7 @@ General area which your question is related to. - [ ] Installation of RMG - [ ] Running an RMG job - [ ] Using RMG API - - [ ] CanTherm + - [ ] Arkane (formerly CanTherm) - [ ] Dependencies - [ ] An error message diff --git a/.gitignore b/.gitignore index bb319a69c9..1d51b886bc 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,9 @@ nbproject/* .pydevproject .settings/* +# PyCharm project files +.idea/* + # Unit test files .coverage testing/* diff --git a/.travis.yml b/.travis.yml index 2ff0742ff3..7407fd804d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,10 @@ env: stages: - test + - name: documentation + if: branch = master AND type = push - name: deploy - if: branch = stable + if: branch = stable AND type = push before_install: - cd .. @@ -24,6 +26,9 @@ before_install: # Update conda - conda update --yes conda - conda info -a + # Set git info + - git config --global user.name "Travis Deploy" + - git config --global user.email "rmg_dev@mit.edu" jobs: include: @@ -47,6 +52,21 @@ jobs: after_success: - codecov - bash ./deploy.sh + - stage: documentation + install: + - cd RMG-Py + - conda env create -q -f environment_linux.yml + - source activate rmg_env + # Install sphinx for building documentation + - conda install -y sphinx + - conda list + # Modify setup.py + - sed -i '/embedsignature/s/^#//g' setup.py + - make + - cd documentation + - export COMMITMESSAGE="Automatic documentation rebuild" + script: + - make travis_setup clean html publish - stage: deploy install: # Setup conda build @@ -55,7 +75,7 @@ jobs: - conda config --add channels rmg - conda config --set anaconda_upload yes script: - - conda build --token $CONDA_TOKEN --user rmg RMG-Py + - conda build --token $CONDA_TOKEN --user rmg RMG-Py/.conda - os: osx install: # Setup conda build @@ -64,4 +84,4 @@ jobs: - conda config --add channels rmg - conda config --set anaconda_upload yes script: - - conda build --token $CONDA_TOKEN --user rmg RMG-Py + - conda build --token $CONDA_TOKEN --user rmg RMG-Py/.conda diff --git a/Makefile b/Makefile index f0839efcb9..19bc621288 100644 --- a/Makefile +++ b/Makefile @@ -33,8 +33,8 @@ else endif python setup.py build_ext solver --build-lib . --build-temp build --pyrex-c-in-temp -cantherm: - python setup.py build_ext cantherm --build-lib . --build-temp build --pyrex-c-in-temp +arkane: + python setup.py build_ext arkane --build-lib . --build-temp build --pyrex-c-in-temp check: @ python utilities.py check-dependencies @@ -88,21 +88,21 @@ ifneq ($(OS),Windows_NT) mkdir -p testing/coverage rm -rf testing/coverage/* endif - nosetests --nocapture --nologcapture --all-modules --verbose --with-coverage --cover-inclusive --cover-package=rmgpy --cover-erase --cover-html --cover-html-dir=testing/coverage --exe rmgpy + nosetests --nocapture --nologcapture --all-modules --verbose --with-coverage --cover-inclusive --cover-package=rmgpy --cover-erase --cover-html --cover-html-dir=testing/coverage --exe rmgpy arkane test test-unittests: ifneq ($(OS),Windows_NT) mkdir -p testing/coverage rm -rf testing/coverage/* endif - nosetests --nocapture --nologcapture --all-modules -A 'not functional' --verbose --with-coverage --cover-inclusive --cover-package=rmgpy --cover-erase --cover-html --cover-html-dir=testing/coverage --exe rmgpy + nosetests --nocapture --nologcapture --all-modules -A 'not functional' --verbose --with-coverage --cover-inclusive --cover-package=rmgpy --cover-erase --cover-html --cover-html-dir=testing/coverage --exe rmgpy arkane test-functional: ifneq ($(OS),Windows_NT) mkdir -p testing/coverage rm -rf testing/coverage/* endif - nosetests --nocapture --nologcapture --all-modules -A 'functional' --verbose --exe rmgpy + nosetests --nocapture --nologcapture --all-modules -A 'functional' --verbose --exe rmgpy arkane test-database: nosetests -v -d testing/databaseTest.py diff --git a/cantherm.py b/arkane.py similarity index 83% rename from cantherm.py rename to arkane.py index 135af90e1e..76222501a5 100644 --- a/cantherm.py +++ b/arkane.py @@ -29,19 +29,19 @@ ############################################################################### """ -This is the main executable script for CanTherm, a tool for computing chemical +This is the main executable script for Arkane, a tool for computing chemical reaction rates and other properties used in detailed kinetics models using -various methodologies and theories. To run CanTherm, use the command :: +various methodologies and theories. To run Arkane, use the command :: - $ python cantherm.py FILE + $ python arkane.py FILE -where ``FILE`` is the path to a CanTherm input file describing the job to -execute. CanTherm will run the specified job, writing the output to -``output.py`` and a log to both the console and to ``cantherm.log``, with both +where ``FILE`` is the path to an Arkane input file describing the job to +execute. Arkane will run the specified job, writing the output to +``output.py`` and a log to both the console and to ``Arkane.log``, with both files appearing in the same directory as the input file. Some additional command-line arguments are available; run the command :: - $ python cantherm.py -h + $ python arkane.py -h for more information. """ @@ -49,15 +49,15 @@ import os import logging -from rmgpy.cantherm.main import * +from arkane.main import * -cantherm = CanTherm() +arkane = Arkane() # Parse and validate the command-line arguments -cantherm.parseCommandLineArguments() +arkane.parseCommandLineArguments() # Execute the job -cantherm.execute() +arkane.execute() try: import psutil diff --git a/rmgpy/cantherm/common.py b/arkane/__init__.py similarity index 70% rename from rmgpy/cantherm/common.py rename to arkane/__init__.py index 60f741961a..56cc9d8cac 100644 --- a/rmgpy/cantherm/common.py +++ b/arkane/__init__.py @@ -28,21 +28,8 @@ # # ############################################################################### -import numpy -import os.path -import logging -import rmgpy.constants as constants -################################################################################ - -def checkConformerEnergy(Vlist,path): - """ - Check to see that the starting energy of the species in the potential energy scan calculation - is not 0.5 kcal/mol (or more) higher than any other energies in the scan. If so, print and - log a warning message. - """ - Vlist = numpy.array(Vlist, numpy.float64) - Vdiff = (Vlist[0] - numpy.min(Vlist))*constants.E_h*constants.Na/1000 - if Vdiff >= 2: #we choose 2 kJ/mol to be the critical energy - logging.warning('the species corresponding to ' + str(os.path.basename(path)) + ' is different in energy from the lowest energy conformer by ' + "%0.2f" % Vdiff + ' kJ/mol. This can cause significant errors in your computed rate constants. ') - - +from arkane.main import Arkane +from arkane.statmech import StatMechJob +from arkane.thermo import ThermoJob +from arkane.kinetics import KineticsJob +from arkane.pdep import PressureDependenceJob diff --git a/arkane/common.py b/arkane/common.py new file mode 100644 index 0000000000..11c02e07bf --- /dev/null +++ b/arkane/common.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2018 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +import numpy +import os.path +import logging + +import rmgpy.constants as constants + +################################################################################ + + +def check_conformer_energy(Vlist,path): + """ + Check to see that the starting energy of the species in the potential energy scan calculation + is not 0.5 kcal/mol (or more) higher than any other energies in the scan. If so, print and + log a warning message. + """ + Vlist = numpy.array(Vlist, numpy.float64) + Vdiff = (Vlist[0] - numpy.min(Vlist))*constants.E_h*constants.Na/1000 + if Vdiff >= 2: #we choose 2 kJ/mol to be the critical energy + logging.warning('the species corresponding to ' + str(os.path.basename(path)) + ' is different in energy from the lowest energy conformer by ' + "%0.2f" % Vdiff + ' kJ/mol. This can cause significant errors in your computed rate constants. ') + + +def get_element_mass(input_element, isotope=None): + """ + Returns the mass and z number of the requested isotop for a given element. + 'input_element' can be wither the atomic number (integer) or an element symbol. + 'isotope' is an integer of the atomic z number. If 'isotope' is None, returns the most common isotope. + Data taken from NIST, https://physics.nist.gov/cgi-bin/Compositions/stand_alone.pl (accessed October 2018) + """ + symbol = None + number = None + + if isinstance(input_element, int): + symbol = symbol_by_number[input_element] + number = input_element + elif isinstance(input_element, str): + symbol = input_element + number = next(key for key, value in symbol_by_number.items() if value == input_element) + + if symbol is None or number is None: + raise ValueError('Could not identify element {0}'.format(input_element)) + + mass_list = mass_by_symbol[symbol] + + if isotope is not None: + # a specific isotope is required + for iso_mass in mass_list: + if iso_mass[0] == isotope: + mass = iso_mass[1] + break + else: + raise ValueError("Could not find requested isotop {0} for element {1}".format(isotope, symbol)) + else: + # no specific isotope is required + if len(mass_list[0]) == 2: + # isotop weight is unavailable, use the first entry + mass = mass_list[0][1] + logging.warn("Assuming isotop {0} is representative of element {1}".format(mass_list[0][0], symbol)) + else: + # use the most common isotope + max_weight = mass_list[0][2] + mass = mass_list[0][1] + for iso_mass in mass_list: + if iso_mass[2] > max_weight: + max_weight = iso_mass[2] + mass = iso_mass[1] + return mass, number + + +symbol_by_number = {1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 7: 'N', 8: 'O', 9: 'F', 10: 'Ne', 11: 'Na', + 12: 'Mg', 13: 'Al', 14: 'Si', 15: 'P', 16: 'S', 17: 'Cl', 18: 'Ar', 19: 'K', 20: 'Ca', 21: 'Sc', + 22: 'Ti', 23: 'V', 24: 'Cr', 25: 'Mn', 26: 'Fe', 27: 'Co', 28: 'Ni', 29: 'Cu', 30: 'Zn', 31: 'Ga', + 32: 'Ge', 33: 'As', 34: 'Se', 35: 'Br', 36: 'Kr', 37: 'Rb', 38: 'Sr', 39: 'Y', 40: 'Zr', 41: 'Nb', + 42: 'Mo', 43: 'Tc', 44: 'Ru', 45: 'Rh', 46: 'Pd', 47: 'Ag', 48: 'Cd', 49: 'In', 50: 'Sn', 51: 'Sb', + 52: 'Te', 53: 'I', 54: 'Xe', 55: 'Cs', 56: 'Ba', 57: 'La', 58: 'Ce', 59: 'Pr', 60: 'Nd', 61: 'Pm', + 62: 'Sm', 63: 'Eu', 64: 'Gd', 65: 'Tb', 66: 'Dy', 67: 'Ho', 68: 'Er', 69: 'Tm', 70: 'Yb', 71: 'Lu', + 72: 'Hf', 73: 'Ta', 74: 'W', 75: 'Re', 76: 'Os', 77: 'Ir', 78: 'Pt', 79: 'Au', 80: 'Hg', 81: 'Tl', + 82: 'Pb', 83: 'Bi', 84: 'Po', 85: 'At', 86: 'Rn', 87: 'Fr', 88: 'Ra', 89: 'Ac', 90: 'Th', 91: 'Pa', + 92: 'U', 93: 'Np', 94: 'Pu', 95: 'Am', 96: 'Cm', 97: 'Bk', 98: 'Cf', 99: 'Es', 100: 'Fm', 101: 'Md', + 102: 'No', 103: 'Lr', 104: 'Rf', 105: 'Db', 106: 'Sg', 107: 'Bh', 108: 'Hs', 109: 'Mt', 110: 'Ds', + 111: 'Rg', 112: 'Cn', 113: 'Nh', 114: 'Fl', 115: 'Mc', 116: 'Lv', 117: 'Ts', 118: 'Og'} + +# Structure of mass_by_symbol items: list(list(isotope1, mass1, weight1), list(isotope2, mass2, weight2), ...) +mass_by_symbol = {'H': [[1, 1.00782503224, 0.999885], [2, 2.01410177812, 0.000115], [3, 3.0160492779, 0]], +'He': [[3, 3.0160293201, 0.00000134], [4, 4.00260325414, 0.99999866]], +'Li': [[6, 6.0151228874, 0.0759], [7, 7.0160034366, 0.9241]], +'Be': [[9, 9.012183066, 1]], +'B': [[10, 10.01293695, 0.199], [11, 11.00930536, 0.801]], +'C': [[12, 12.0000000, 0.9893], [13, 13.00335483507, 0.0107], [14, 14.0032419884, 0]], +'N': [[14, 14.00307400443, 0.99636], [15, 15.00010889889, 0.00364]], +'O': [[16, 15.99491461957, 0.99757], [17, 16.99913175651, 0.00038], [18, 17.99915961287, 0.00205]], +'F': [[19, 18.99840316274, 1]], +'Ne': [[20, 19.9924401762, 0.9048], [21, 20.993846685, 0.0027], [22, 21.991385114, 0.0925]], +'Na': [[23, 22.9897692820, 1]], +'Mg': [[24, 23.985041697, 0.7899], [25, 24.985836976, 0.1000], [26, 25.982592968, 0.1101]], +'Al': [[27, 26.98153853, 1]], +'Si': [[28, 27.97692653465, 0.92223], [29, 28.97649466491, 0.04685], [30, 29.973770136, 0.03092]], +'P': [[31, 30.97376199843, 1]], +'S': [[32, 31.9720711744, 0.9499], [33, 32.9714589098, 0.0075], [34, 33.967867004, 0.0425], [36, 35.96708071, 0.0001]], +'Cl': [[35, 34.968852682, 0.7576], [37, 36.965902603, 0.2424]], +'Ar': [[36, 35.967545105, 0.003336], [38, 37.96273211, 0.000629], [40, 39.9623831237, 0.996035]], +'K': [[39, 38.9637064864, 0.932581], [40, 39.963998167, 0.000117], [41, 40.9618252579, 0.067302]], +'Ca': [[40, 39.962590863, 0.96941], [42, 41.95861783, 0.00647], [43, 42.95876644, 0.00135], [44, 43.95548156, 0.02086], [46, 45.9536890, 0.00004], [48, 47.95252276, 0.00187]], +'Sc': [[45, 44.95590829, 1]], +'Ti': [[46, 45.95262772, 0.0825], [47, 46.95175879, 0.0744], [48, 47.94794198, 0.7372], [49, 48.94786568, 0.0541], [50, 49.94478689, 0.0518]], +'V': [[50, 49.94715602, 0.00250], [51, 50.94395705, 0.99750]], +'Cr': [[50, 49.94604184, 0.04345], [52, 51.94050624, 0.83789], [53, 52.94064816, 0.09501], [54, 53.93887917, 0.02365]], +'Mn': [[55, 54.93804391, 1]], +'Fe': [[54, 53.93960900, 0.05845], [56, 55.93493633, 0.91754], [57, 56.93539284, 0.02119], [58, 57.93327444, 0.00282]], +'Co': [[59, 58.93319430, 1]], +'Ni': [[58, 57.93534242, 0.68077], [60, 59.93078589, 0.26223], [61, 60.93105558, 0.011399], [62, 61.92834538, 0.036346], [64, 63.92796682, 0.009255]], +'Cu': [[63, 62.92959773, 0.6915], [65, 64.92778971, 0.3085]], +'Zn': [[64, 63.92914202, 0.4917], [66, 65.92603382, 0.2773], [67, 66.92712776, 0.0404], [68, 67.92484456, 0.1845], [70, 69.9253192, 0.0061]], +'Ga': [[69, 68.9255735, 0.60108], [71, 70.92470259, 0.39892]], +'Ge': [[70, 69.92424876, 0.2057], [72, 71.922075827, 0.2745], [73, 72.923458957, 0.0775], [74, 73.921177761, 0.3650], [76, 75.921402726, 0.0773]], +'As': [[75, 74.92159458, 1]], +'Se': [[74, 73.922475934, 0.0089], [76, 75.919213704, 0.0937], [77, 76.919914155, 0.0763], [78, 77.91730928, 0.2377], [80, 79.9165218, 0.4961], [82, 81.9166995, 0.0873]], +'Br': [[79, 78.9183376, 0.5069], [81, 80.9162897, 0.4931]], +'Kr': [[78, 77.92036495, 0.00355], [80, 79.91637809, 0.02286], [82, 81.91348274, 0.11593], [83, 82.91412716, 0.11500], [84, 83.9114977282, 0.56987], [86, 85.9106106269, 0.17279]], +'Rb': [[85, 84.9117897380, 0.7217], [87, 86.9091805311, 0.2783]], +'Sr': [[84, 83.9134191, 0.0056], [86, 85.9092606, 0.0986], [87, 86.9088775, 0.0700], [88, 87.9056125, 0.8258]], +'Y': [[89, 88.9058403, 1]], +'Zr': [[90, 89.9046977, 0.5145], [91, 90.9056396, 0.1122], [92, 91.9050347, 0.1715], [94, 93.9063108, 0.1738], [96, 95.9082714, 0.0280]], +'Nb': [[93, 92.9063730, 1]], +'Mo': [[92, 91.90680797, 0.1453], [94, 93.90508490, 0.0915], [95, 94.90583877, 0.1584], [96, 95.90467612, 0.1667], [97, 96.90601812, 0.0960], [98, 97.90540482, 0.2439], [100, 99.9074718, 0.0982]], +'Tc': [[97, 96.9063667,], [98, 97.9072124], [99, 98.9062508]], +'Ru': [[96, 95.90759025, 0.0554], [98, 97.9052869, 0.0187], [99, 98.9059341, 0.1276], [100, 99.9042143, 0.1260], [101, 100.9055769, 0.1706], [102, 101.9043441, 0.3155], [104, 103.9054275, 0.1862]], +'Rh': [[103, 102.905498, 1]], +'Pd': [[102, 101.9056022, 0.0102], [104, 103.9040305, 0.1114], [105, 104.9050796, 0.2233], [106, 105.9034804, 0.2733], [108, 107.9038916, 0.2646], [110, 109.90517221, 0.1172]], +'Ag': [[107, 106.9050916, 0.51839], [109, 108.9047553, 0.48161]], +'Cd': [[106, 105.9064599, 0.0125], [108, 107.9041834, 0.0089], [110, 109.90300662, 0.1249], [111, 110.90418288, 0.1280], [112, 111.9027629, 0.2413], [113, 112.9044081, 0.1222], [114, 113.9033651, 0.2873], [116, 115.9047632, 0.0749]], +'In': [[113, 112.9040618, 0.0429], [115, 114.9038788, 0.9571]], +'Sn': [[112, 111.9048239, 0.0097], [114, 113.9027827, 0.0066], [115, 114.9033447, 0.0034], [116, 115.9017428, 0.1454], [117, 116.902954, 0.0768], [118, 117.9016066, 0.2422], [119, 118.9033112, 0.0859], [120, 119.9022016, 0.3258], [122, 121.9034438, 0.0463], [124, 123.9052766, 0.0579]], +'Sb': [[121, 120.903812, 0.5721], [123, 122.9042132, 0.4279]], +'Te': [[120, 119.9040593, 0.0009], [122, 121.9030435, 0.0255], [123, 122.9042698, 0.0089], [124, 123.9028171, 0.0474], [125, 124.9044299, 0.0707], [126, 125.9033109, 0.1884], [128, 127.9044613, 0.3174], [130, 129.9062227, 0.3408]], +'I': [[127, 126.9044719, 1]], +'Xe': [[124, 123.905892, 0.000952], [126, 125.9042983, 0.000890], [128, 127.903531, 0.019102], [129, 128.9047809, 0.264006], [130, 129.9035093, 0.040710], [131, 130.9050841, 0.212324], [132, 131.9041551, 0.269086], [134, 133.9053947, 0.104357], [136, 135.9072145, 0.088573]], +'Cs': [[133, 132.905452, 1]], +'Ba': [[130, 129.9063207, 0.00106], [132, 131.9050611, 0.00101], [134, 133.9045082, 0.02417], [135, 134.9056884, 0.06592], [136, 135.9045757, 0.07854], [137, 136.9058271, 0.11232], [138, 137.905247, 0.71698]], +'La': [[138, 137.9071149, 0.0008881], [139, 138.9063563, 0.9991119]], +'Ce': [[136, 135.9071292, 0.00185], [138, 137.905991, 0.00251], [140, 139.9054431, 0.88450], [142, 141.9092504, 0.11114]], +'Pr': [[141, 140.9076576, 1]], +'Nd': [[142, 141.907729, 0.27152], [143, 142.90982, 0.12174], [144, 143.910093, 0.23798], [145, 144.9125793, 0.08293], [146, 145.9131226, 0.17189], [148, 147.9168993, 0.05756], [150, 149.9209022, 0.05638]], +'Pm': [[145, 144.9127559], [147, 146.915145]], +'Sm': [[144, 143.9120065, 0.0307], [147, 146.9149044, 0.1499], [148, 147.9148292, 0.1124], [149, 148.9171921, 0.1382], [150, 149.9172829, 0.0738], [152, 151.9197397, 0.2675], [154, 153.9222169, 0.2275]], +'Eu': [[151, 150.9198578, 0.4781], [153, 152.921238, 0.5219]], +'Gd': [[152, 151.9197995, 0.0020], [154, 153.9208741, 0.0218], [155, 154.9226305, 0.1480], [156, 155.9221312, 0.2047], [157, 156.9239686, 0.1565], [158, 157.9241123, 0.2484], [160, 159.9270624, 0.2186]], +'Tb': [[159, 158.9253547, 1]], +'Dy': [[156, 155.9242847, 0.00056], [158, 157.9244159, 0.00095], [160, 159.9252046, 0.02329], [161, 160.9269405, 0.18889], [162, 161.9268056, 0.25475], [163, 162.9287383, 0.24896], [164, 163.9291819, 0.28260]], +'Ho': [[165, 164.9303288, 1]], +'Er': [[162, 161.9287884, 0.00139], [164, 163.9292088, 0.01601], [166, 165.9302995, 0.33503], [167, 166.9320546, 0.22869], [168, 167.9323767, 0.26978], [170, 169.9354702, 0.14910]], +'Tm': [[169, 168.9342179, 1]], +'Yb': [[168, 167.9338896, 0.00123], [170, 169.9347664, 0.02982], [171, 170.9363302, 0.1409], [172, 171.9363859, 0.2168], [173, 172.9382151, 0.16103], [174, 173.9388664, 0.32026], [176, 175.9425764, 0.12996]], +'Lu': [[175, 174.9407752, 0.97401], [176, 175.9426897, 0.02599]], +'Hf': [[174, 173.9400461, 0.0016], [176, 175.9414076, 0.0526], [177, 176.9432277, 0.1860], [178, 177.9437058, 0.2728], [179, 178.9458232, 0.1362], [180, 179.946557, 0.3508]], +'Ta': [[180, 179.9474648, 0.0001201], [181, 180.9479958, 0.9998799]], +'W': [[180, 179.9467108, 0.0012], [182, 181.9482039, 0.2650], [183, 182.9502228, 0.1431], [184, 183.9509309, 0.3064], [186, 185.9543628, 0.2843]], +'Re': [[185, 184.9529545, 0.3740], [187, 186.9557501, 0.6260]], +'Os': [[184, 183.9524885, 0.0002], [186, 185.953835, 0.0159], [187, 186.9557474, 0.0196], [188, 187.9558352, 0.1324], [189, 188.9581442, 0.1615], [190, 189.9584437, 0.2626], [192, 191.961477, 0.4078]], +'Ir': [[191, 190.9605893, 0.373], [193, 192.9629216, 0.627]], +'Pt': [[190, 189.9599297, 0.00012], [192, 191.9610387, 0.00782], [194, 193.9626809, 0.3286], [195, 194.9647917, 0.3378], [196, 195.9649521, 0.2521], [198, 197.9678949, 0.07356]], +'Au': [[197, 196.9665688, 1]], +'Hg': [[196, 195.9658326, 0.0015], [198, 197.9667686, 0.0997], [199, 198.9682806, 0.1687], [200, 199.9683266, 0.2310], [201, 200.9703028, 0.1318], [202, 201.9706434, 0.2986], [204, 203.973494, 0.0687]], +'Tl': [[203, 202.9723446, 0.2952], [205, 204.9744278, 0.7048]], +'Pb': [[204, 203.973044, 0.014], [206, 205.9744657, 0.241], [207, 206.9758973, 0.221], [208, 207.9766525, 0.524]], +'Bi': [[209, 208.9803991, 1]], +'Po': [[209, 208.9824308], [210, 209.9828741]], +'At': [[210, 209.9871479], [211, 210.9874966]], +'Rn': [[211, 210.9906011], [220, 220.0113941], [222, 222.0175782]], +'Fr': [[223, 223.019736]], +'Ra': [[223, 223.0185023], [224, 224.020212], [226, 226.0254103], [228, 228.0310707]], +'Ac': [[227, 227.0277523]], +'Th': [[230, 230.0331341, 0], [232, 232.0380558, 1]], +'Pa': [[231, 231.0358842, 1]], +'U': [[233, 233.0396355, 0], [234, 234.0409523, 0.000054], [235, 235.0439301, 0.007204], [236, 236.0455682, 0], [238, 238.0507884, 0.992742]], +'Np': [[236, 236.04657], [237, 237.0481736]], +'Pu': [[238, 238.0495601], [239, 239.0521636], [240, 240.0538138], [241, 241.0568517], [242, 242.0587428], [244, 244.0642053]], +'Am': [[241, 241.0568293], [243, 243.0613813]], +'Cm': [[243, 243.0613893], [244, 244.0627528], [245, 245.0654915], [246, 246.0672238], [247, 247.0703541], [248, 248.0723499]], +'Bk': [[247, 247.0703073], [249, 249.0749877]], +'Cf': [[249, 249.0748539], [250, 250.0764062], [251, 251.0795886], [252, 252.0816272]], +'Es': [[252, 252.08298]], 'Fm': [[257, 257.0951061]], 'Md': [[258, 258.0984315], [260, 260.10365]], +'No': [[259, 259.10103]], 'Lr': [[262, 262.10961]], 'Rf': [[267, 267.12179]], 'Db': [[268, 268.12567]], +'Sg': [[271, 271.13393]], 'Bh': [[272, 272.13826]], 'Hs': [[270, 270.13429]], 'Mt': [[276, 276.15159]], +'Ds': [[281, 281.16451]], 'Rg': [[280, 280.16514]], 'Cn': [[285, 285.17712]], 'Nh': [[284, 284.17873]], +'Fl': [[289, 289.19042]], 'Mc': [[288, 288.19274]], 'Lv': [[293, 293.20449]], 'Ts': [[292, 292.20746]], +'Og': [[294, 294.21392]]} diff --git a/rmgpy/cantherm/commonTest.py b/arkane/commonTest.py similarity index 75% rename from rmgpy/cantherm/commonTest.py rename to arkane/commonTest.py index 5bc817baab..ec182293d0 100644 --- a/rmgpy/cantherm/commonTest.py +++ b/arkane/commonTest.py @@ -29,42 +29,51 @@ ############################################################################### """ -This script contains unit tests of the :mod:`rmgpy.quantity` module. +This script contains unit tests of the :mod:`arkane.common` module. """ + import unittest import numpy import os + import rmgpy -from rmgpy.cantherm import CanTherm, input -from input import jobList import rmgpy.constants as constants -from rmgpy.cantherm.statmech import InputError +from rmgpy.species import Species, TransitionState + +from arkane.common import get_element_mass +from arkane import Arkane, input +from arkane.statmech import InputError, StatMechJob +from arkane.input import jobList + ################################################################################ + class CommonTest(unittest.TestCase): """ - Contains unit tests of the Cantherm common functions. + Contains unit tests of Arkane's common functions. """ - - def test_checkConformerEnergy(self): + def test_check_conformer_energy(self): """ - test the checkConformerEnergy function with an list of energies. + test the check_conformer_energy function with an list of energies. """ - Vlist = [-272.2779012225, -272.2774933703, -272.2768397635, -272.2778432059, -272.278645477, -272.2789602654, -272.2788749196, -272.278496709, -272.2779350675, -272.2777008843, -272.2777167286, -272.2780937643, -272.2784838846, -272.2788050464, -272.2787865352, -272.2785091607, -272.2779977452, -272.2777957743, -272.2779134906, -272.2781827547, -272.278443339, -272.2788244214, -272.2787748749] + Vlist = [-272.2779012225, -272.2774933703, -272.2768397635, -272.2778432059, -272.278645477, -272.2789602654, + -272.2788749196, -272.278496709, -272.2779350675, -272.2777008843, -272.2777167286, -272.2780937643, + -272.2784838846, -272.2788050464, -272.2787865352, -272.2785091607, -272.2779977452, -272.2777957743, + -272.2779134906, -272.2781827547, -272.278443339, -272.2788244214, -272.2787748749] Vlist = numpy.array(Vlist, numpy.float64) Vdiff = (Vlist[0] - numpy.min(Vlist)) * constants.E_h * constants.Na / 1000 self.assertAlmostEqual(Vdiff / 2.7805169838282797, 1, 5) -class testCanthermJob(unittest.TestCase): +class TestArkaneJob(unittest.TestCase): """ - Contains unit tests of the Cantherm module and its interactions with other RMG modules. + Contains unit tests of the Arkane module and its interactions with other RMG modules. """ + @classmethod def setUp(self): - - cantherm = CanTherm() - - jobList = cantherm.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)),'data','methoxy.py')) + arkane = Arkane() + jobList = arkane.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'data', 'methoxy.py')) pdepjob = jobList[-1] self.kineticsjob = jobList[0] pdepjob.activeJRotor = True @@ -87,7 +96,7 @@ def setUp(self): self.method = pdepjob.method self.rmgmode = pdepjob.rmgmode -# test Cantherm's interactions with the network module + # test Arkane's interactions with the network module def testNisom(self): """ Test the number of isomers identified. @@ -118,7 +127,7 @@ def testPathReactions(self): """ self.assertEqual(str(self.PathReaction2), 'CH2OH <=> methoxy', msg=None) -# test Cantherm's interactions with the pdep module + # test Arkane's interactions with the pdep module def testTemperaturesUnits(self): """ Test the Temperature Units. @@ -185,13 +194,15 @@ def testRmgmode(self): """ self.assertEqual(self.rmgmode, False, msg=None) -# Test cantherms interactions with the kinetics module + # Test Arkane's interactions with the kinetics module def testCalculateTSTRateCoefficient(self): """ Test the calculation of the high-pressure limit rate coef for one of the kinetics jobs at Tmin and Tmax. """ - self.assertEqual("%0.7f" % self.kineticsjob.reaction.calculateTSTRateCoefficient(self.TminValue), str(46608.5904933), msg=None) - self.assertEqual("%0.5f" % self.kineticsjob.reaction.calculateTSTRateCoefficient(self.Tmaxvalue), str(498796.64535), msg=None) + self.assertEqual("%0.7f" % self.kineticsjob.reaction.calculateTSTRateCoefficient(self.TminValue), + str(46608.5904933), msg=None) + self.assertEqual("%0.5f" % self.kineticsjob.reaction.calculateTSTRateCoefficient(self.Tmaxvalue), + str(498796.64535), msg=None) def testTunneling(self): """ @@ -200,13 +211,14 @@ def testTunneling(self): self.assertEqual(self.kineticsjob.reaction.transitionState.tunneling, None, msg=None) -class testCanthermInput(unittest.TestCase): +class TestArkaneInput(unittest.TestCase): """ - Contains unit tests for loading and processing Cantherm input files. + Contains unit tests for loading and processing Arkane input files. """ + @classmethod def setUp(self): """Preparation for all unit tests in this class.""" - self.directory = os.path.join(os.path.dirname(os.path.dirname(rmgpy.__file__)), 'examples', 'cantherm') + self.directory = os.path.join(os.path.dirname(os.path.dirname(rmgpy.__file__)), 'examples', 'arkane') self.modelChemistry = "cbs-qb3" self.frequencyScaleFactor = 0.99 self.useHinderedRotors = False @@ -215,22 +227,18 @@ def setUp(self): def testSpecies(self): """Test loading of species input file.""" spec = input.species('C2H4', os.path.join(self.directory, 'species', 'C2H4', 'ethene.py')) - - self.assertTrue(isinstance(spec, rmgpy.species.Species)) + self.assertTrue(isinstance(spec, Species)) self.assertEqual(len(spec.molecule), 0) def testSpeciesStatmech(self): """Test loading of statmech job from species input file.""" job = jobList[-1] - - self.assertTrue(isinstance(job, rmgpy.cantherm.statmech.StatMechJob)) - + self.assertTrue(isinstance(job, StatMechJob)) job.modelChemistry = self.modelChemistry job.frequencyScaleFactor = self.frequencyScaleFactor job.includeHinderedRotors = self.useHinderedRotors job.applyBondEnergyCorrections = self.useBondCorrections job.load() - self.assertTrue(isinstance(job.species.props['elementCounts'], dict)) self.assertEqual(job.species.props['elementCounts']['C'], 2) self.assertEqual(job.species.props['elementCounts']['H'], 4) @@ -239,47 +247,58 @@ def testSpeciesThermo(self): """Test thermo job execution for species from separate input file.""" input.thermo('C2H4', 'NASA') job = jobList[-1] - filepath = os.path.join(self.directory, 'reactions', 'H+C2H4=C2H5', 'output.py') job.execute(outputFile=filepath) - self.assertTrue(os.path.isfile(os.path.join(os.path.dirname(filepath), 'output.py'))) self.assertTrue(os.path.isfile(os.path.join(os.path.dirname(filepath), 'chem.inp'))) - os.remove(os.path.join(os.path.dirname(filepath), 'output.py')) os.remove(os.path.join(os.path.dirname(filepath), 'chem.inp')) def testTransitionState(self): """Test loading of transition state input file.""" ts = input.transitionState('TS', os.path.join(self.directory, 'reactions', 'H+C2H4=C2H5', 'TS.py')) - - self.assertTrue(isinstance(ts, rmgpy.species.TransitionState)) + self.assertTrue(isinstance(ts, TransitionState)) def testTransitionStateStatmech(self): """Test loading of statmech job from transition state input file.""" job = jobList[-1] - - self.assertTrue(isinstance(job, rmgpy.cantherm.statmech.StatMechJob)) - + self.assertTrue(isinstance(job, StatMechJob)) job.modelChemistry = self.modelChemistry job.frequencyScaleFactor = self.frequencyScaleFactor job.includeHinderedRotors = self.useHinderedRotors job.applyBondEnergyCorrections = self.useBondCorrections job.load() - -class testStatmech(unittest.TestCase): + + +class TestStatmech(unittest.TestCase): """ Contains unit tests of statmech.py """ + @classmethod def setUp(self): - cantherm = CanTherm() - jobList = cantherm.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)),'data','Benzyl','input.py')) - - def testGaussianLogFileError(self): + arkane = Arkane() + self.job_list = arkane.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'data', 'Benzyl', 'input.py')) + + def test_gaussian_log_file_error(self): """Test that the proper error is raised if gaussian geometry and frequency file paths are the same""" - job = jobList[-1] - self.assertTrue(isinstance(job, rmgpy.cantherm.statmech.StatMechJob)) - self.assertRaises(InputError,job.load()) - + job = self.job_list[-2] + self.assertTrue(isinstance(job, StatMechJob)) + with self.assertRaises(InputError): + job.load() + + +class TestGetMass(unittest.TestCase): + """ + Contains unit tests of common.py + """ + def test_get_mass(self): + """Test that the correct mass/number/isotop is returned from get_element_mass""" + self.assertEquals(get_element_mass(1), (1.00782503224, 1)) # test input by integer + self.assertEquals(get_element_mass('Si'), (27.97692653465, 14)) # test string input and most common isotope + self.assertEquals(get_element_mass('C', 13), (13.00335483507, 6)) # test specific isotope + self.assertEquals(get_element_mass('Bk'), (247.0703073, 97)) # test a two-element array (no isotope data) + + if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(verbosity=2)) diff --git a/rmgpy/cantherm/data/.gitignore b/arkane/data/.gitignore similarity index 70% rename from rmgpy/cantherm/data/.gitignore rename to arkane/data/.gitignore index 46d7def7ab..1959ae69e5 100644 --- a/rmgpy/cantherm/data/.gitignore +++ b/arkane/data/.gitignore @@ -1,4 +1,4 @@ -cantherm.log +arkane.log chem.inp network.pdf output.py diff --git a/examples/cantherm/species/Benzyl/BenzylEnergy.log b/arkane/data/Benzyl/BenzylEnergy.log similarity index 100% rename from examples/cantherm/species/Benzyl/BenzylEnergy.log rename to arkane/data/Benzyl/BenzylEnergy.log diff --git a/examples/cantherm/species/Benzyl/BenzylFreq.log b/arkane/data/Benzyl/BenzylFreq.log similarity index 100% rename from examples/cantherm/species/Benzyl/BenzylFreq.log rename to arkane/data/Benzyl/BenzylFreq.log diff --git a/examples/cantherm/species/Benzyl/BenzylRot1.log b/arkane/data/Benzyl/BenzylRot1.log similarity index 100% rename from examples/cantherm/species/Benzyl/BenzylRot1.log rename to arkane/data/Benzyl/BenzylRot1.log diff --git a/rmgpy/cantherm/data/Benzyl/benzyl.py b/arkane/data/Benzyl/benzyl.py similarity index 100% rename from rmgpy/cantherm/data/Benzyl/benzyl.py rename to arkane/data/Benzyl/benzyl.py diff --git a/rmgpy/cantherm/data/Benzyl/input.py b/arkane/data/Benzyl/input.py similarity index 100% rename from rmgpy/cantherm/data/Benzyl/input.py rename to arkane/data/Benzyl/input.py diff --git a/rmgpy/cantherm/data/HOSI_ccsd_t1.out b/arkane/data/HOSI_ccsd_t1.out similarity index 100% rename from rmgpy/cantherm/data/HOSI_ccsd_t1.out rename to arkane/data/HOSI_ccsd_t1.out diff --git a/rmgpy/cantherm/data/OH_f12.out b/arkane/data/OH_f12.out similarity index 100% rename from rmgpy/cantherm/data/OH_f12.out rename to arkane/data/OH_f12.out diff --git a/rmgpy/cantherm/data/co.out b/arkane/data/co.out similarity index 100% rename from rmgpy/cantherm/data/co.out rename to arkane/data/co.out diff --git a/rmgpy/cantherm/data/ethylene.log b/arkane/data/ethylene.log similarity index 100% rename from rmgpy/cantherm/data/ethylene.log rename to arkane/data/ethylene.log diff --git a/rmgpy/cantherm/data/ethylene_G3.log b/arkane/data/ethylene_G3.log similarity index 100% rename from rmgpy/cantherm/data/ethylene_G3.log rename to arkane/data/ethylene_G3.log diff --git a/rmgpy/cantherm/data/ethylene_f12_dz.out b/arkane/data/ethylene_f12_dz.out similarity index 100% rename from rmgpy/cantherm/data/ethylene_f12_dz.out rename to arkane/data/ethylene_f12_dz.out diff --git a/rmgpy/cantherm/data/ethylene_f12_qz.out b/arkane/data/ethylene_f12_qz.out similarity index 100% rename from rmgpy/cantherm/data/ethylene_f12_qz.out rename to arkane/data/ethylene_f12_qz.out diff --git a/rmgpy/cantherm/data/methoxy.py b/arkane/data/methoxy.py similarity index 88% rename from rmgpy/cantherm/data/methoxy.py rename to arkane/data/methoxy.py index 3a06cd3426..bfa13b0d4c 100644 --- a/rmgpy/cantherm/data/methoxy.py +++ b/arkane/data/methoxy.py @@ -4,11 +4,12 @@ description = \ frequencyScaleFactor = 1.0 """ -This example illustrates how to manually set up a CanTherm input file for a small P-dep reaction system [using only the -RRHO assumption, and without tunneling, although this can be easily implemented]. Such a calculation is desireable if the user -wishes to supply experimentally determined freqeuncies, for example. Althgou some coommented notes below may be useful, -see http://reactionmechanismgenerator.github.io/RMG-Py/users/cantherm/index.html for more documented information about CanTherm and -creating input files. (information pertaining this file is adopted by Dames and Golden, 2013, JPCA 117 (33) 7686-96.) +This example illustrates how to manually set up an Arkane input file for a small P-dep reaction system [using only the +RRHO assumption, and without tunneling, although this can be easily implemented]. Such a calculation is desireable if +the user wishes to supply experimentally determined freqeuncies, for example. Althgou some coommented notes below may be +useful, see http://reactionmechanismgenerator.github.io/RMG-Py/users/arkane/index.html for more documented information +about Arkane and creating input files. +(information pertaining this file is adopted by Dames and Golden, 2013, JPCA 117 (33) 7686-96.) """ transitionState( label = 'TS3', @@ -149,6 +150,7 @@ molecularWeight = (4.003,'amu'), collisionModel = TransportData(sigma=(2.55e-10,'m'), epsilon=(0.0831,'kJ/mol')), energyTransferModel = SingleExponentialDown(alpha0=(0.956,'kJ/mol'), T0=(300,'K'), n=0.95), + thermo=NASA(polynomials=[NASAPolynomial(coeffs=[2.5,0,0,0,0,-745.375,0.928724], Tmin=(200,'K'), Tmax=(1000,'K')), NASAPolynomial(coeffs=[2.5,0,0,0,0,-745.375,0.928724], Tmin=(1000,'K'), Tmax=(6000,'K'))], Tmin=(200,'K'), Tmax=(6000,'K'), Cp0=(20.7862,'J/(mol*K)'), CpInf=(20.7862,'J/(mol*K)'), label="""He""", comment="""Thermo library: primaryThermoLibrary"""), ) reaction( @@ -219,6 +221,6 @@ #Other methods include: 'reservoir state', 'chemically-significant eigenvalues', interpolationModel = ('pdeparrhenius'), activeKRotor = True, -# activeJRotor = False, #causes cantherm to crash +# activeJRotor = False, # causes Arkane to crash rmgmode = False, ) diff --git a/arkane/data/methoxy_explore.py b/arkane/data/methoxy_explore.py new file mode 100644 index 0000000000..5073e54af5 --- /dev/null +++ b/arkane/data/methoxy_explore.py @@ -0,0 +1,243 @@ +title = 'methoxy decomposition to H + CH2O' + +description = \ +""" +This example illustrates how to manually set up an Arkane input file for a exploration of a P-dep reaction system +""" +database( + thermoLibraries = ['primaryThermoLibrary'], + reactionLibraries = [], + kineticsDepositories = ['training'], + kineticsFamilies = 'default', + kineticsEstimator = 'rate rules', +) + +transitionState( + label = 'TS3', + E0 = (34.1,'kcal/mol'), # this INCLUDES the ZPE. Note that other energy units are also possible (e.g., kJ/mol) + spinMultiplicity = 2, + opticalIsomers = 1, + frequency = (-967,'cm^-1'), + modes = [ # these modes are used to compute the partition functions + HarmonicOscillator(frequencies=([466,581,1169,1242,1499,1659,2933,3000],'cm^-1')), + NonlinearRotor(rotationalConstant=([0.970, 1.029, 3.717],"cm^-1"),symmetry=1, quantum=False), + IdealGasTranslation(mass=(31.01843,"g/mol")) #this must be included for every species/ts + ], + +) + +transitionState( + label = 'TS2', + E0 = (38.9,'kcal/mol'), + spinMultiplicity = 2, + opticalIsomers = 1, + frequency = (-1934,'cm^-1'), + modes = [ + HarmonicOscillator(frequencies=([792, 987 ,1136, 1142, 1482 ,2441 ,3096, 3183],'cm^-1')), + NonlinearRotor(rotationalConstant=([0.928,0.962,5.807],"cm^-1"),symmetry=1, quantum=False), + IdealGasTranslation(mass=(31.01843,"g/mol")) + ], + +) +transitionState( + label = 'TS1', + E0 = (39.95,'kcal/mol'), + spinMultiplicity = 2, + opticalIsomers = 1, + frequency = (-1756,'cm^-1'), + modes = [ + HarmonicOscillator(frequencies=([186 ,626 ,1068, 1234, 1474, 1617, 2994 ,3087],'cm^-1')), + NonlinearRotor(rotationalConstant=([0.966,0.986,5.253],"cm^-1"),symmetry=1, quantum=False), + IdealGasTranslation(mass=(31.01843,"g/mol")) + ], + +) + +species( + label = 'methoxy', + structure = SMILES('C[O]'), + E0 = (9.44,'kcal/mol'), + modes = [ + HarmonicOscillator(frequencies=([758,960,1106 ,1393,1403,1518,2940,3019,3065],'cm^-1')), + NonlinearRotor(rotationalConstant=([0.916, 0.921, 5.251],"cm^-1"),symmetry=3, quantum=False), + IdealGasTranslation(mass=(31.01843,"g/mol")), + ], + spinMultiplicity = 3.88, # 3+exp(-89/T) + opticalIsomers = 1, + molecularWeight = (31.01843,'amu'), + collisionModel = TransportData(sigma=(3.69e-10,'m'), epsilon=(4.0,'kJ/mol')), + energyTransferModel = SingleExponentialDown(alpha0=(0.956,'kJ/mol'), T0=(300,'K'), n=0.95), +) + + +species( + label = 'CH2O', + structure = SMILES('C=O'), + E0 = (28.69,'kcal/mol'), + molecularWeight = (30.0106,"g/mol"), + collisionModel = TransportData(sigma=(3.69e-10,'m'), epsilon=(4.0,'kJ/mol')), + energyTransferModel = SingleExponentialDown(alpha0=(0.956,'kJ/mol'), T0=(300,'K'), n=0.95), + spinMultiplicity = 1, + opticalIsomers = 1, + modes = [ + HarmonicOscillator(frequencies=([1180,1261,1529,1764,2931,2999],'cm^-1')), + NonlinearRotor(rotationalConstant=([1.15498821005263, 1.3156969584727, 9.45570474524524],"cm^-1"),symmetry=2, quantum=False), + IdealGasTranslation(mass=(30.0106,"g/mol")), + ], +) + +species( + label = 'H', + structure = SMILES('[H]'), + E0 = (0.000,'kcal/mol'), + molecularWeight = (1.00783,"g/mol"), + collisionModel = TransportData(sigma=(3.69e-10,'m'), epsilon=(4.0,'kJ/mol')), + energyTransferModel = SingleExponentialDown(alpha0=(0.956,'kJ/mol'), T0=(300,'K'), n=0.95), + modes = [ + IdealGasTranslation(mass=(1.00783,"g/mol")), + ], + spinMultiplicity = 2, + opticalIsomers = 1, + +) + +species( + label = 'CH2Ob', #this is a special system with two chemically equivalent product channels. Thus, different labels are used. + structure = SMILES('C=O'), + E0 = (28.69,'kcal/mol'), + molecularWeight = (30.0106,"g/mol"), + collisionModel = TransportData(sigma=(3.69e-10,'m'), epsilon=(4.0,'kJ/mol')), + energyTransferModel = SingleExponentialDown(alpha0=(0.956,'kJ/mol'), T0=(300,'K'), n=0.95), + spinMultiplicity = 1, + opticalIsomers = 1, + modes = [ + HarmonicOscillator(frequencies=([1180,1261,1529,1764,2931,2999],'cm^-1')), + NonlinearRotor(rotationalConstant=([1.15498821005263, 1.3156969584727, 9.45570474524524],"cm^-1"),symmetry=2, quantum=False), + IdealGasTranslation(mass=(30.0106,"g/mol")), + ], +) + +species( + label = 'Hb', + structure = SMILES('[H]'), + E0 = (0.0001,'kcal/mol'), + molecularWeight = (1.00783,"g/mol"), + collisionModel = TransportData(sigma=(3.69e-10,'m'), epsilon=(4.0,'kJ/mol')), + energyTransferModel = SingleExponentialDown(alpha0=(0.956,'kJ/mol'), T0=(300,'K'), n=0.95), + modes = [ + IdealGasTranslation(mass=(1.00783,"g/mol")), + ], + spinMultiplicity = 2, + opticalIsomers = 1, + +) +species( + label = 'CH2OH', + structure = SMILES('[CH2]O'), + E0 = (0.00,'kcal/mol'), + molecularWeight = (31.01843,"g/mol"), + modes = [ + HarmonicOscillator(frequencies=([418,595, 1055, 1198, 1368, 1488, 3138, 3279, 3840],'cm^-1')), + NonlinearRotor(rotationalConstant=([0.868,0.993,6.419],"cm^-1"),symmetry=1, quantum=False), + IdealGasTranslation(mass=(31.01843,"g/mol")), + ], + spinMultiplicity = 2, + opticalIsomers = 2, + collisionModel = TransportData(sigma=(3.69e-10,'m'), epsilon=(4.0,'kJ/mol')), + energyTransferModel = SingleExponentialDown(alpha0=(0.956,'kJ/mol'), T0=(300,'K'), n=0.95), +) + +species( + label = 'He', + structure = SMILES('[He]'), + reactive=False, + molecularWeight = (4.003,'amu'), + collisionModel = TransportData(sigma=(2.55e-10,'m'), epsilon=(0.0831,'kJ/mol')), + energyTransferModel = SingleExponentialDown(alpha0=(0.956,'kJ/mol'), T0=(300,'K'), n=0.95), +) + +reaction( + label = 'CH2O+H=Methoxy', + reactants = ['CH2O','H'], + products = ['methoxy'], + transitionState = 'TS3', + kinetics = Arrhenius( + A = (1.5339e+09, 'cm^3/(mol*s)'), + n = 1.3717, + Ea = (18.6161, 'kJ/mol'), + T0 = (1, 'K'), + Tmin = (303.03, 'K'), + Tmax = (2500, 'K'), + comment = 'Fitted to 59 data points; dA = *|/ 1.06037, dn = +|- 0.00769361, dEa = +|- 0.0423225 kJ/mol', + ), +) + +reaction( + label = 'CH2OH = CH2Ob+Hb', + reactants = ['CH2OH'], + products = ['CH2Ob', 'Hb'], + transitionState = 'TS1', + kinetics = Arrhenius( + A = (5.51244e+10, 's^-1'), + n = 0.868564, + Ea = (168.41, 'kJ/mol'), + T0 = (1, 'K'), + Tmin = (303.03, 'K'), + Tmax = (2500, 'K'), + comment = 'Fitted to 59 data points; dA = *|/ 1.05152, dn = +|- 0.00659302, dEa = +|- 0.0362682 kJ/mol', + ), +) + +reaction( + label = 'CH2OH = Methoxy', + products = ['methoxy'], + reactants = ['CH2OH'], + transitionState = 'TS2', + kinetics = Arrhenius( + A = (5.63501e+11, 's^-1'), + n = 0.320211, + Ea = (163.376, 'kJ/mol'), + T0 = (1, 'K'), + Tmin = (303.03, 'K'), + Tmax = (2500, 'K'), + comment = 'Fitted to 59 data points; dA = *|/ 1.02731, dn = +|- 0.00353557, dEa = +|- 0.0194492 kJ/mol', + ), +) + +network( + label = 'methoxy', + isomers = [ + 'methoxy', + 'CH2OH', + ], + + reactants = [ + ('CH2O','H'), + ], + + bathGas = { + 'He': 1, + }, +) + +pressureDependence( + label = 'methoxy', + Tmin = (450,'K'), Tmax = (1200,'K'), Tcount = 3, + Tlist = ([450,800,1000,1200],'K'), + Pmin = (0.01,'atm'), Pmax = (1000.0,'atm'), Pcount = 3, + Plist = ([.01,1.0,1000.0],'atm'), + maximumGrainSize = (0.5,'kcal/mol'), + minimumGrainCount = 500, + method = 'modified strong collision', + interpolationModel = ('pdeparrhenius'), + activeKRotor = True, + rmgmode = False, +) + +explorer( + source=['methoxy'], + explore_tol=(1e-2,'s'), + energy_tol=4.5e1, + flux_tol=1e-10, +) + diff --git a/arkane/data/molpro_mrci+q.out b/arkane/data/molpro_mrci+q.out new file mode 100644 index 0000000000..30c0bfc2a8 --- /dev/null +++ b/arkane/data/molpro_mrci+q.out @@ -0,0 +1,806 @@ + + Primary working directories : /tmp + Secondary working directories : /tmp + Wavefunction directory : /home/alongd/wfu/ + Main file repository : /tmp/ + + SHA1 : 5e3d8ac6839c721e2824de82269b4736200146bd + NAME : 2015.1.37 + ARCHNAME : linux/x86_64 + FC : /opt/intel/composer_xe_2015.1.133/bin/intel64/ifort + BLASLIB : -Wl,-_start-group /opt/intel/mkl/lib/intel64/libmkl_intel_ilp64.a /opt/intel/mkl/lib/intel64/libmkl_intel_thread.a /opt/intel/mkl/lib/intel64/libmkl_core.a -Wl,-_end-group + id : phalgunlolur + + Nodes nprocs + node07 1 + + Using customized tuning parameters: mindgm=1; mindgv=20; mindgc=4; mindgr=1; noblas=0; minvec=7 + default implementation of scratch files=df + + ***,name + memory,500,m; + + geometry={angstrom; + N 0.7033634988 0.0974820728 -0.0730473920 + N -0.7033634988 -0.0974820728 -0.0730473920 + H 1.0539960456 0.3871635195 0.8315583036 + H -1.0539960456 -0.3871635195 0.8315583036 + H 1.1434808787 -0.7765990298 -0.3202265599 + H -1.1434808787 0.7765990298 -0.3202265599 + } + + gprint,orbitals; + + basis=aug-cc-pVTZ + + {hf; + maxit,1000; + wf,spin=0,charge=0} + + put,molden,orbitals_1_hf.mol + + {multi; + noextra,failsafe,config,csf; + wf,spin=0,charge=0; + natorb,print,ci;} + + {mrci; + wf,spin=0,charge=0} + + E_mrci=energy; + E_mrci_Davidson=energd; + + table,E_mrci,E_mrci_Davidson; + + + Variables initialized (889), CPU time= 0.01 sec + Commands initialized (702), CPU time= 0.01 sec, 572 directives. + Default parameters read. Elapsed time= 0.07 sec + + Checking input... + Passed +1 + + + *** PROGRAM SYSTEM MOLPRO *** + Copyright, TTI GmbH Stuttgart, 2015 + Version 2015.1 linked Aug 10 2018 15:00:15 + + + ********************************************************************************************************************************** + LABEL * name + 64 bit serial version DATE: 31-Oct-18 TIME: 06:23:05 + ********************************************************************************************************************************** + + SHA1: 5e3d8ac6839c721e2824de82269b4736200146bd + ********************************************************************************************************************************** + +Geometry recognized as XYZ + + + + Variable memory set to 500000000 words, buffer space 230000 words + + SETTING BASIS = AUG-CC-PVTZ + + + Recomputing integrals since basis changed + + + Using spherical harmonics + + Library entry N S aug-cc-pVTZ selected for orbital group 1 + Library entry N P aug-cc-pVTZ selected for orbital group 1 + Library entry N D aug-cc-pVTZ selected for orbital group 1 + Library entry N F aug-cc-pVTZ selected for orbital group 1 + Library entry H S aug-cc-pVTZ selected for orbital group 2 + Library entry H P aug-cc-pVTZ selected for orbital group 2 + Library entry H D aug-cc-pVTZ selected for orbital group 2 + + + PROGRAM * SEWARD (Integral evaluation for generally contracted gaussian basis sets) Author: Roland Lindh, 1990 + + Geometry written to block 1 of record 700 + + + Point group C2 + + + + ATOMIC COORDINATES + + NR ATOM CHARGE X Y Z + + 1 N 7.00 1.329164379 0.184214420 -0.138039565 + 2 N 7.00 -1.329164379 -0.184214420 -0.138039565 + 3 H 1.00 1.991763863 0.731633017 1.571417450 + 4 H 1.00 -1.991763863 -0.731633017 1.571417450 + 5 H 1.00 2.160865689 -1.467559475 -0.605140496 + 6 H 1.00 -2.160865689 1.467559475 -0.605140496 + + Bond lengths in Bohr (Angstrom) + + 1-2 2.683738361 1-3 1.913360521 1-5 1.907424271 2-4 1.913360521 2-6 1.907424271 + ( 1.420173181) ( 1.012506784) ( 1.009365456) ( 1.012506784) ( 1.009365456) + + Bond angles + + 1-2-4 112.47618938 1-2-6 108.24151671 2-1-3 112.47618938 2-1-5 108.24151671 + + 3-1-5 108.39381540 4-2-6 108.39381540 + + NUCLEAR CHARGE: 18 + NUMBER OF PRIMITIVE AOS: 242 + NUMBER OF SYMMETRY AOS: 216 + NUMBER OF CONTRACTIONS: 184 ( 92A + 92B ) + NUMBER OF CORE ORBITALS: 2 ( 1A + 1B ) + NUMBER OF VALENCE ORBITALS: 12 ( 6A + 6B ) + + + NUCLEAR REPULSION ENERGY 41.78471756 + + Eigenvalues of metric + + 1 0.189E-03 0.324E-03 0.107E-02 0.168E-02 0.262E-02 0.292E-02 0.299E-02 0.382E-02 + 2 0.745E-04 0.179E-03 0.324E-03 0.433E-03 0.138E-02 0.196E-02 0.245E-02 0.301E-02 + + + Contracted 2-electron integrals neglected if value below 1.0D-11 + AO integral compression algorithm 1 Integral accuracy 1.0D-11 + + 419.430 MB (compressed) written to integral file ( 51.9%) + + + NUMBER OF SORTED TWO-ELECTRON INTEGRALS: 73209414. BUFFER LENGTH: 32768 + NUMBER OF SEGMENTS: 5 SEGMENT LENGTH: 15999809 RECORD LENGTH: 524288 + + Memory used in sort: 16.56 MW + + SORT1 READ 101111688. AND WROTE 70607682. INTEGRALS IN 204 RECORDS. CPU TIME: 1.31 SEC, REAL TIME: 2.12 SEC + SORT2 READ 70607682. AND WROTE 73209414. INTEGRALS IN 1600 RECORDS. CPU TIME: 1.60 SEC, REAL TIME: 2.05 SEC + + FILE SIZES: FILE 1: 440.3 MBYTE, FILE 4: 855.7 MBYTE, TOTAL: 1295.9 MBYTE + + OPERATOR DM FOR CENTER 0 COORDINATES: 0.000000 0.000000 0.000000 + + + ********************************************************************************************************************************** + DATASETS * FILE NREC LENGTH (MB) RECORD NAMES + 1 19 336.96 500 610 700 900 950 970 1000 129 960 1100 + VAR BASINP GEOM SYMINP ZMAT AOBASIS BASIS P2S ABASIS S + 1400 1410 1200 1210 1080 1600 1650 1300 1700 + T V H0 H01 AOSYM SMH MOLCAS ERIS OPER + + PROGRAMS * TOTAL INT + CPU TIMES * 7.60 7.47 + REAL TIME * 34.76 SEC + DISK USED * 1.30 GB + ********************************************************************************************************************************** + + + PROGRAM * RHF-SCF (CLOSED SHELL) Authors: W. Meyer, H.-J. Werner + + + NUMBER OF ELECTRONS: 9+ 9- + CONVERGENCE THRESHOLDS: 1.00E-05 (Density) 1.00E-07 (Energy) + MAX. NUMBER OF ITERATIONS: 1000 + INTERPOLATION TYPE: DIIS + INTERPOLATION STEPS: 2 (START) 1 (STEP) + LEVEL SHIFTS: 0.00 (CLOSED) 0.00 (OPEN) + + + + Orbital guess generated from atomic densities. Full valence occupancy: 7 7 + + Molecular orbital dump at record 2100.2 + + Initial occupancy: 5 4 + + ITERATION DDIFF GRAD ENERGY 2-EL.EN. DIPOLE MOMENTS DIIS ORB. + 1 0.000D+00 0.000D+00 -111.20146194 162.183852 0.00000 0.00000 1.05870 0 start + 2 0.000D+00 0.571D-02 -111.22566575 160.629648 0.00000 0.00000 0.68797 1 diag + 3 0.614D-02 0.180D-02 -111.22778162 161.505282 0.00000 0.00000 0.78591 2 diag + 4 0.147D-02 0.604D-03 -111.22809585 161.219331 0.00000 0.00000 0.77644 3 diag + 5 0.519D-03 0.142D-03 -111.22812007 161.265894 0.00000 0.00000 0.77787 4 diag + 6 0.959D-04 0.265D-04 -111.22812161 161.261433 0.00000 0.00000 0.77945 5 diag + 7 0.286D-04 0.643D-05 -111.22812174 161.261637 0.00000 0.00000 0.77971 6 diag + 8 0.118D-04 0.184D-05 -111.22812175 161.261629 0.00000 0.00000 0.77981 7 diag + 9 0.406D-05 0.416D-06 -111.22812175 161.261592 0.00000 0.00000 0.77981 0 orth + + Final occupancy: 5 4 + + !RHF STATE 1.1 Energy -111.228121747966 + Nuclear energy 41.78471756 + One-electron energy -233.64363506 + Two-electron energy 80.63079575 + Virial quotient -1.00155086 + !RHF STATE 1.1 Dipole moment 0.00000000 0.00000000 0.77980560 + Dipole moment /Debye 0.00000000 0.00000000 1.98193833 + + ELECTRON ORBITALS + ================= + + + Orb Occ Energy Couls-En Coefficients + + 1 1s 1 1s 1 1s 1 1s 1 1s 1 2pz 1 2px 1 2py 1 2pz 1 2px + 1 2py 1 2pz 1 2px 1 2py 1 2pz 1 2px 1 2py 1 3d0 1 3d2- 1 3d2+ + 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ + 1 3d1+ 1 3d1- 1 4f0 1 4f2- 1 4f2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 1 4f0 + 1 4f2- 1 4f2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 2 1s 2 1s 2 1s 2 1s + 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 3d0 + 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 2 3d0 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 3 1s + 3 1s 3 1s 3 1s 3 2pz 3 2px 3 2py 3 2pz 3 2px 3 2py 3 2pz + 3 2px 3 2py 3 3d0 3 3d2- 3 3d2+ 3 3d1+ 3 3d1- 3 3d0 3 3d2- 3 3d2+ + 3 3d1+ 3 3d1- + + 1.1 2 -15.5688 -44.1782 0.999650 0.001134 0.000986 -0.000950 0.001382 0.003546 -0.002517 -0.003563 -0.002373 0.001172 + 0.002280 -0.001682 -0.000546 0.002362 0.000063 -0.000354 -0.000050 -0.000039 -0.000039 0.000058 + 0.000095 0.000119 0.000292 0.000041 -0.000331 -0.000237 0.000124 -0.000256 -0.000851 0.000643 + -0.000492 -0.000050 0.000202 0.000187 0.000031 0.000084 0.000200 -0.000173 0.000080 -0.000100 + -0.000409 0.000225 -0.000330 -0.000423 0.000490 0.000344 0.001662 -0.000206 -0.000790 -0.000065 + 0.000192 0.000077 0.000054 -0.000060 0.000407 0.000141 -0.000166 0.000290 -0.000154 -0.000256 + -0.000120 -0.000128 -0.000285 -0.000143 0.000128 0.000193 -0.000237 0.000136 0.000008 0.001212 + 0.000393 -0.002908 -0.000089 -0.000025 0.000135 -0.000213 0.000424 0.000455 0.000294 -0.000068 + 0.000469 -0.000421 0.000195 0.000342 0.000137 0.000011 -0.000049 0.000151 -0.000095 -0.000369 + -0.000011 0.000200 + + 2.1 2 -1.2593 -10.8982 -0.011849 0.848436 -0.012605 -0.116716 0.010403 0.058998 -0.147408 -0.068617 0.004013 -0.001166 + -0.004130 -0.018708 0.033885 0.034793 -0.001771 0.002511 0.001022 -0.003536 0.000492 0.005900 + 0.000281 0.002697 -0.007854 0.001972 0.014655 0.000935 0.002733 -0.001455 -0.004369 0.007321 + -0.000628 -0.007011 0.001268 0.001094 0.001110 0.004354 0.002328 -0.005534 -0.001492 -0.001371 + -0.000744 0.001360 0.000954 -0.000914 0.000193 -0.001152 0.310785 -0.082321 -0.123747 -0.000114 + -0.007656 -0.004324 -0.002942 -0.003014 -0.008936 -0.002225 0.007832 0.000037 0.003134 0.000303 + 0.000751 0.000802 0.001565 0.000298 -0.003906 0.001236 -0.000216 0.000502 -0.002294 0.309379 + -0.076651 -0.130009 -0.002267 0.002581 -0.005279 0.007582 0.003401 -0.007594 0.002654 0.000174 + 0.003329 -0.010047 -0.000863 -0.001429 0.000407 -0.000701 0.000211 0.003263 0.001247 0.001709 + -0.001195 -0.001646 + + 3.1 2 -0.6802 -8.9801 -0.001099 -0.075065 0.001594 -0.019639 -0.009278 0.627882 0.288389 0.218962 -0.028169 -0.010266 + -0.016313 -0.069322 -0.044578 -0.039463 0.007030 -0.000078 0.001824 0.013511 0.002078 -0.002631 + 0.001366 0.000291 0.026743 0.000233 -0.009553 -0.007994 -0.001194 0.010671 0.008695 -0.009225 + 0.000836 -0.000888 -0.002567 0.000829 0.002546 -0.002000 0.001490 0.002644 0.000762 0.001747 + -0.001093 0.001016 -0.000930 -0.001110 0.003329 0.001668 0.699297 -0.088457 -0.233063 -0.005406 + -0.015764 -0.006439 -0.005601 -0.025258 -0.006607 -0.007891 0.013562 0.008160 0.006152 0.005036 + 0.001158 0.000015 0.003493 0.003648 -0.000388 -0.002393 0.000633 -0.004649 -0.001842 -0.262810 + 0.040661 0.116153 0.006014 0.002991 0.006356 -0.005954 0.012084 0.015721 -0.009011 0.009105 + -0.002478 0.010602 0.002454 0.003368 0.000147 -0.000117 0.000879 0.001837 0.003276 0.001240 + -0.000605 0.002892 + + 4.1 2 -0.6131 -9.2487 -0.000935 0.005851 0.003991 0.045543 0.008822 -0.165790 0.752552 -0.231357 0.008349 -0.020873 + 0.015405 0.027554 -0.069476 0.030094 0.000071 0.007254 0.001669 0.002089 -0.012169 -0.014266 + 0.003648 0.002833 0.011205 -0.023815 -0.037677 0.009679 0.007357 0.013142 -0.006502 -0.021211 + 0.004082 0.004235 0.001067 0.001105 0.000055 -0.004307 -0.000656 0.004853 0.001861 0.002776 + -0.003882 -0.000385 -0.003637 0.002370 0.000346 0.006732 0.067149 -0.027476 -0.038632 -0.000533 + -0.003203 0.006194 -0.002390 -0.003371 0.024407 -0.004703 0.001607 0.009371 -0.000579 0.002392 + -0.001003 -0.002361 -0.002903 0.001257 0.001220 -0.002470 -0.002025 -0.006292 0.000463 0.638301 + -0.093293 -0.182553 -0.000181 0.003861 -0.001920 0.016050 0.002779 0.013284 0.025682 0.000113 + 0.013959 -0.002003 -0.002069 -0.001915 -0.006548 -0.000180 0.002926 0.000265 0.008866 -0.004306 + 0.002152 -0.002284 + + 5.1 2 -0.4073 -8.5581 0.001992 0.205454 0.001466 0.161014 0.082435 -0.397480 0.233009 0.727686 0.005251 0.005337 + -0.020700 -0.015386 0.012510 0.024389 -0.020514 0.012122 0.040328 0.004674 0.006494 0.001245 + 0.006738 0.004254 0.011950 0.013533 -0.000448 0.020082 0.014017 0.003801 -0.011391 -0.003530 + 0.007581 0.010783 0.000573 0.001371 -0.003913 -0.001273 -0.000865 0.002776 -0.000603 0.004572 + 0.000340 -0.001617 0.003978 0.000359 0.001976 -0.001074 0.118432 -0.039833 -0.023900 0.003957 + -0.006290 0.002547 0.007080 -0.007714 0.011364 0.026345 -0.013765 0.007928 0.013978 0.003688 + -0.001516 0.000207 -0.000558 -0.002202 0.005626 -0.000566 0.001378 -0.002296 -0.004338 -0.399053 + 0.018451 0.022312 -0.010715 -0.007693 0.006501 -0.003087 -0.019605 0.016646 -0.002772 -0.017471 + 0.006402 0.006830 0.000439 0.003155 -0.000226 0.002146 -0.003218 -0.002298 0.001883 -0.005861 + 0.001633 -0.000820 + + 1 1s 1 1s 1 1s 1 1s 1 1s 1 2px 1 2py 1 2pz 1 2px 1 2py + 1 2pz 1 2px 1 2py 1 2pz 1 2px 1 2py 1 2pz 1 3d1+ 1 3d1- 1 3d0 + 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 + 1 3d2- 1 3d2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 1 4f0 1 4f2- 1 4f2+ 1 4f1+ + 1 4f1- 1 4f3+ 1 4f3- 1 4f0 1 4f2- 1 4f2+ 2 1s 2 1s 2 1s 2 1s + 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 3d1+ + 2 3d1- 2 3d0 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 2 3d0 2 3d2- 2 3d2+ 3 1s + 3 1s 3 1s 3 1s 3 2px 3 2py 3 2pz 3 2px 3 2py 3 2pz 3 2px + 3 2py 3 2pz 3 3d1+ 3 3d1- 3 3d0 3 3d2- 3 3d2+ 3 3d1+ 3 3d1- 3 3d0 + 3 3d2- 3 3d2+ + + 1.2 2 -15.5684 -44.1781 0.999333 -0.000306 0.001609 -0.010679 -0.004683 -0.002751 -0.003626 0.003590 0.004802 0.002699 + -0.002473 0.005930 0.002803 -0.003788 0.001519 0.000248 0.000261 0.000065 0.000192 0.000098 + -0.000148 -0.000162 0.000104 -0.000277 0.000921 -0.000419 -0.001722 0.001115 -0.000127 0.000205 + 0.000043 -0.000635 0.000082 0.000208 -0.000149 0.000058 0.000181 0.000221 0.000076 -0.000676 + -0.000323 0.000689 -0.000038 -0.000269 -0.000389 -0.000530 0.001300 0.001474 -0.001717 -0.000430 + 0.000092 0.000085 0.000234 -0.000045 -0.000394 -0.000097 0.000034 -0.000080 0.000534 -0.000245 + -0.000145 -0.000391 -0.000013 0.000076 -0.000116 0.000118 0.000032 -0.000020 -0.000241 0.001511 + 0.000459 -0.000805 -0.000177 0.000088 -0.000234 -0.000092 -0.000151 -0.000248 -0.000132 0.000140 + -0.000207 -0.000250 0.000071 -0.000165 0.000186 0.000288 0.000325 -0.000080 -0.000103 0.000102 + 0.000039 0.000005 + + 2.2 2 -1.0098 -9.6395 -0.008232 0.787505 -0.007976 -0.004692 0.022089 0.254919 -0.089988 0.089736 -0.014027 -0.002064 + 0.001436 -0.045221 0.019539 -0.019945 0.003154 0.001245 0.000248 0.003134 0.004185 0.003795 + -0.003887 -0.006627 0.008315 0.006854 0.005289 -0.007077 -0.009574 0.000582 -0.002969 -0.001195 + 0.000078 -0.000190 0.001164 0.001899 -0.001529 -0.000734 0.001132 0.001333 0.000911 0.001424 + 0.001198 -0.001273 -0.000125 0.001528 0.001595 -0.000555 0.466413 -0.116589 -0.181609 -0.004641 + -0.003580 -0.004750 -0.012509 -0.001019 -0.005248 -0.006531 0.003778 -0.000591 0.010737 0.001533 + 0.001631 0.002252 0.000527 0.000082 -0.002637 -0.001269 -0.002990 -0.000187 -0.001296 0.485311 + -0.121446 -0.198097 -0.002529 -0.005227 0.012821 0.004482 -0.002303 0.007639 0.004803 0.005627 + -0.012295 -0.004382 -0.000659 0.001417 -0.001372 -0.002169 -0.001725 0.001159 -0.001557 0.002369 + 0.002447 0.001725 + + 3.2 2 -0.6699 -8.8210 0.000283 0.112462 -0.000627 0.098458 0.034117 -0.036137 0.650136 0.279474 0.003116 -0.031169 + -0.019870 -0.013730 -0.084102 -0.039802 -0.005883 0.005670 -0.003089 0.005870 0.001977 0.009574 + 0.000515 0.006709 0.007836 0.006448 0.016203 -0.010562 0.013771 -0.000305 0.005472 -0.002309 + -0.001788 0.004302 0.000548 -0.000101 -0.001011 0.003582 -0.000742 0.000286 -0.001463 0.001430 + -0.000344 -0.000617 0.000277 0.003203 -0.000588 0.000363 0.509245 -0.081031 -0.168796 -0.003570 + -0.005893 0.000568 -0.012702 -0.006171 0.009983 -0.018565 0.006324 0.008253 0.008225 0.003367 + 0.000811 0.004514 0.000065 0.000892 -0.000212 -0.003945 0.002387 -0.001551 0.001310 -0.587856 + 0.055899 0.181449 0.004500 0.009283 -0.012185 -0.003298 0.017514 -0.023475 -0.005386 -0.005550 + 0.006808 0.005036 0.001360 -0.002354 0.002935 0.004964 0.002057 -0.000983 0.001472 0.000222 + -0.000792 -0.000568 + + 4.2 2 -0.4141 -8.5110 -0.002842 -0.289065 0.000034 -0.268178 -0.268859 -0.051823 -0.388259 0.731925 -0.000128 0.007007 + -0.023721 0.030318 -0.004190 0.011090 0.042844 -0.014801 0.040234 0.008149 -0.001676 0.006288 + 0.005883 -0.000612 0.017671 -0.009072 0.014547 0.018441 -0.003308 -0.004766 -0.010404 0.011037 + 0.005677 -0.008876 0.001119 0.002796 0.000613 -0.002569 0.001459 -0.002072 0.000156 0.001726 + -0.001448 0.004337 -0.003471 0.001353 -0.002808 -0.002231 0.487635 -0.018547 -0.027897 0.003833 + -0.004426 -0.008472 -0.005298 -0.010999 -0.021630 -0.008669 -0.003937 -0.016325 0.008094 0.002396 + 0.003983 0.001495 0.001613 -0.000486 -0.001424 0.000726 -0.005536 0.000585 -0.000009 -0.066865 + 0.045166 0.029537 -0.007943 -0.001461 -0.005003 0.007412 -0.010241 -0.004210 0.025011 -0.003515 + -0.009169 0.009579 -0.001515 0.002380 0.001659 0.000200 0.002216 0.000935 0.003609 0.003433 + 0.000580 0.003314 + + HOMO 5.1 -0.407323 = -11.0838eV + LUMO 6.1 0.029650 = 0.8068eV + LUMO-HOMO 0.436973 = 11.8906eV + + + ********************************************************************************************************************************** + DATASETS * FILE NREC LENGTH (MB) RECORD NAMES + 1 19 336.96 500 610 700 900 950 970 1000 129 960 1100 + VAR BASINP GEOM SYMINP ZMAT AOBASIS BASIS P2S ABASIS S + 1400 1410 1200 1210 1080 1600 1650 1300 1700 + T V H0 H01 AOSYM SMH MOLCAS ERIS OPER + + 2 4 3.20 700 1000 520 2100 + GEOM BASIS MCVARS RHF + + PROGRAMS * TOTAL HF INT + CPU TIMES * 12.35 4.75 7.47 + REAL TIME * 40.34 SEC + DISK USED * 1.30 GB + ********************************************************************************************************************************** + + Dump information in style MOLDEN to orbitals_1_hf.mol + + Molecular orbitals read from record 2100.2 Type=RHF/CANONICAL (state 1.1) + Occupation numbers read from record 2100.2 Type=RHF/RHF (state 1.1) + Orbital energies read from record 2100.2 Type=RHF/CANONICAL (state 1.1) + Redundancy group numbers read from rec 2100.2 Type=RHF/RHF (state 1.1) + + DUMP ORBITAL 1.1 AS ORBITAL 1 occ= 2.0000 eig= -15.5688 GROUP= 2 + DUMP ORBITAL 1.2 AS ORBITAL 2 occ= 2.0000 eig= -15.5684 GROUP= 2 + DUMP ORBITAL 2.1 AS ORBITAL 3 occ= 2.0000 eig= -1.2593 GROUP= 2 + DUMP ORBITAL 2.2 AS ORBITAL 4 occ= 2.0000 eig= -1.0098 GROUP= 2 + DUMP ORBITAL 3.1 AS ORBITAL 5 occ= 2.0000 eig= -0.6802 GROUP= 2 + DUMP ORBITAL 3.2 AS ORBITAL 6 occ= 2.0000 eig= -0.6699 GROUP= 2 + DUMP ORBITAL 4.1 AS ORBITAL 7 occ= 2.0000 eig= -0.6131 GROUP= 2 + DUMP ORBITAL 4.2 AS ORBITAL 8 occ= 2.0000 eig= -0.4141 GROUP= 2 + DUMP ORBITAL 5.1 AS ORBITAL 9 occ= 2.0000 eig= -0.4073 GROUP= 2 + + Total charge: 18.000000 + + ********************************************************************************************************************************** + + + PROGRAM * MULTI (Direct Multiconfiguration SCF) Authors: P.J. Knowles, H.-J. Werner (1984) S.T. Elbert (1988) + + + Number of closed-shell orbitals: 2 ( 1 1 ) + Number of active orbitals: 12 ( 6 6 ) + Number of external orbitals: 170 ( 85 85 ) + + State symmetry 1 + + Number of electrons: 14 Spin symmetry=Singlet Space symmetry=1 + Number of states: 1 + Number of CSFs: 85092 (313632 determinants, 627264 intermediate states) + + Molecular orbitals read from record 2100.2 Type=RHF/CANONICAL (state 1.1) + + Wavefunction dump at record 2140.2 + + Convergence thresholds 0.10E-01 (gradient) 0.10E-05 (energy) 0.10E-02 (step length) + + Number of orbital rotations: 1202 ( 12 Core/Active 170 Core/Virtual 0 Active/Active 1020 Active/Virtual) + Total number of variables: 314834 + + + ITER. MIC NCI NEG ENERGY(VAR) ENERGY(PROJ) ENERGY CHANGE GRAD(0) GRAD(ORB) GRAD(CI) STEP TIME + + 1 80 22 0 -111.22824300 -111.37280951 -0.14456652 0.00072114 0.00529068 0.06570182 0.19D+01 15.18 + 2 37 30 0 -111.35750945 -111.36172482 -0.00421537 0.07436063 0.00000354 0.00013192 0.29D+00 36.16 + 3 40 19 0 -111.36172900 -111.36172907 -0.00000006 0.00030586 0.00000169 0.00002137 0.80D-03 49.85 + + ** WVFN **** CONVERGENCE REACHED, FINAL GRADIENT: 0.28D-05 + + + First order charge density matrix for state 1.1 saved on record 2140.2 (density set 1) + + Results for state 1.1 + ===================== + + !MCSCF STATE 1.1 Energy -111.361729066869 + Nuclear energy 41.78471756 + Kinetic energy 111.41243376 + One electron energy -233.60673323 + Two electron energy 80.46028660 + Virial ratio 1.99954489 + + !MCSCF STATE 1.1 Dipole moment 0.00000000 0.00000000 0.72629767 + Dipole moment /Debye 0.00000000 0.00000000 1.84594363 + + + NATURAL ORBITALS + ================ + + Orb Occ Energy Coefficients + + 1 1s 1 1s 1 1s 1 1s 1 1s 1 2pz 1 2px 1 2py 1 2pz 1 2px + 1 2py 1 2pz 1 2px 1 2py 1 2pz 1 2px 1 2py 1 3d0 1 3d2- 1 3d2+ + 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ + 1 3d1+ 1 3d1- 1 4f0 1 4f2- 1 4f2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 1 4f0 + 1 4f2- 1 4f2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 2 1s 2 1s 2 1s 2 1s + 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 3d0 + 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 2 3d0 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 3 1s + 3 1s 3 1s 3 1s 3 2pz 3 2px 3 2py 3 2pz 3 2px 3 2py 3 2pz + 3 2px 3 2py 3 3d0 3 3d2- 3 3d2+ 3 3d1+ 3 3d1- 3 3d0 3 3d2- 3 3d2+ + 3 3d1+ 3 3d1- + + 1.1 2.00000 -15.483138 0.997552 -0.049885 0.001966 -0.003550 -0.002987 0.027748 -0.014130 -0.025776 -0.003134 0.000945 + 0.002854 -0.001273 -0.002196 -0.001279 0.001150 -0.001121 -0.001853 0.000040 -0.000136 -0.000084 + -0.000258 -0.000233 0.000282 -0.000222 -0.000554 -0.001410 -0.000781 -0.000440 -0.000004 0.000645 + -0.000844 -0.000257 0.000072 0.000066 0.000175 -0.000022 0.000154 -0.000077 0.000156 -0.000252 + -0.000363 0.000246 -0.000508 -0.000440 0.000445 0.000346 -0.011553 0.004999 0.004274 -0.000289 + 0.000703 0.000003 -0.000139 0.000138 -0.000106 -0.000896 0.000167 -0.000072 -0.000829 -0.000409 + -0.000065 -0.000137 -0.000254 -0.000044 0.000065 0.000173 -0.000247 0.000258 0.000272 -0.008767 + 0.005363 0.006639 0.000601 0.000161 0.000208 -0.000758 0.001199 0.000069 -0.000177 0.000784 + -0.000142 -0.000136 0.000277 0.000346 0.000228 -0.000044 0.000041 0.000109 -0.000346 -0.000139 + -0.000063 0.000379 + + 2.1 1.99834 -0.890681 0.060890 0.731252 -0.007757 0.045544 0.066217 -0.375078 0.177195 0.342885 0.012487 0.000958 + -0.009043 -0.004670 0.022913 0.053962 -0.016445 0.011389 0.027196 -0.001237 0.001401 0.002200 + 0.005430 0.005491 0.000375 0.004693 0.003114 0.017642 0.013139 0.002675 -0.013381 -0.000045 + 0.005390 0.003291 0.001910 0.001734 -0.002240 0.001433 0.000576 -0.001190 -0.001088 0.002414 + -0.001010 -0.000433 0.002619 0.000225 0.000939 -0.000121 0.182473 -0.073620 -0.068993 0.003470 + -0.007264 0.001335 0.003129 -0.003424 0.008143 0.016135 -0.006049 0.005377 0.010097 0.002271 + -0.000932 0.000123 -0.000624 -0.001621 0.001427 0.000338 0.000177 -0.001845 -0.003988 0.133911 + -0.069879 -0.139530 -0.010424 -0.002990 -0.000878 0.007883 -0.012038 0.005854 0.007857 -0.013171 + 0.009238 -0.003821 -0.001203 0.000093 -0.001402 0.000916 -0.001462 0.000428 0.003536 -0.003966 + 0.000800 -0.002637 + + 3.1 1.98037 -0.833190 -0.006118 0.374859 -0.003976 -0.156457 -0.037454 0.641639 -0.009650 -0.198435 -0.023323 -0.009737 + -0.003481 -0.058728 -0.014287 -0.015550 0.011864 -0.003911 -0.015069 0.005426 -0.000965 0.001276 + -0.001961 -0.000246 0.008768 -0.003825 0.002485 -0.013355 -0.004514 0.004722 0.007375 -0.000303 + -0.003202 -0.009761 -0.001032 0.000674 0.003959 0.001904 0.002887 -0.002764 -0.000080 -0.001344 + -0.001476 0.002213 -0.001777 -0.001319 0.001674 0.000794 0.614008 -0.095080 -0.218731 -0.005161 + -0.011273 -0.007623 -0.008188 -0.009572 -0.012259 -0.016446 0.021376 0.002784 0.000131 0.001741 + 0.001748 0.000409 0.003268 0.003275 -0.005584 -0.000867 -0.000435 -0.002422 -0.001458 0.171789 + -0.024792 -0.004617 0.007389 0.006616 -0.001375 0.001114 0.017974 -0.000064 -0.005621 0.013907 + -0.001748 -0.003397 0.001053 0.000251 0.000576 -0.001323 0.001897 0.004409 0.002324 0.004327 + -0.001685 0.001047 + + 4.1 1.97716 -0.600301 0.002787 -0.140733 0.001045 0.089676 0.036678 0.206398 -0.048602 0.695855 -0.019829 0.008642 + -0.032777 -0.063086 0.010547 -0.041235 -0.007778 0.002848 0.022313 0.010838 0.010880 0.005740 + 0.002629 0.000672 0.018756 0.019178 0.010945 0.002286 0.002603 0.002090 0.002073 0.002466 + 0.002627 0.005221 -0.001980 0.000357 -0.001192 -0.000617 0.000061 0.002159 -0.000596 0.002410 + 0.001838 -0.000552 0.003402 -0.001582 0.002636 -0.002497 0.362608 -0.040883 -0.096848 -0.000604 + -0.008655 -0.004060 0.002875 -0.013733 -0.006423 0.013578 -0.003108 0.004783 0.010676 0.003582 + 0.000087 0.001109 0.002651 0.000064 0.002966 -0.000737 0.002195 -0.001008 -0.003200 -0.796472 + 0.105296 0.203002 -0.002382 -0.005154 0.009005 -0.013962 -0.006204 0.010111 -0.013611 -0.006080 + -0.006938 0.015928 0.002688 0.004704 0.003036 0.001310 -0.002685 -0.001863 -0.002615 -0.001294 + -0.000350 0.003226 + + 5.1 1.97064 -0.684053 0.002076 -0.280023 0.005667 0.109606 0.014276 0.044058 0.855193 0.046351 -0.006466 -0.026507 + 0.003607 -0.003392 -0.101419 -0.001330 -0.000125 0.006486 0.007778 0.009506 -0.008455 -0.014727 + 0.005110 0.002159 0.023812 -0.017275 -0.037697 0.008354 0.007679 0.015135 -0.000853 -0.022144 + 0.005083 0.007098 -0.000444 0.001198 0.000113 -0.005788 -0.000697 0.007115 0.002118 0.004257 + -0.002715 -0.000505 -0.002279 0.002138 0.001113 0.005920 0.268755 -0.044398 -0.095995 -0.001936 + -0.007382 0.004194 -0.002101 -0.010270 0.021911 -0.001573 0.003896 0.011235 0.003481 0.004373 + -0.000828 -0.002127 -0.001539 0.001992 0.002608 -0.003490 -0.001131 -0.007314 -0.000472 0.245423 + -0.036136 -0.056248 0.000710 0.002238 0.003894 0.007289 0.002597 0.022609 0.013029 0.001279 + 0.008662 0.006072 -0.000223 0.000868 -0.005287 0.000386 0.002058 -0.000336 0.008126 -0.003996 + 0.002135 -0.000329 + + 6.1 0.02279 0.756926 -0.033150 -0.451715 -0.051692 -0.316320 -0.152207 0.241467 -0.360043 1.320243 0.046711 -0.007336 + -0.074161 0.057920 -0.008756 -0.178293 0.025789 -0.000569 -0.000316 0.021240 0.004886 0.035839 + -0.002954 0.010001 0.043725 -0.006765 0.060922 0.012810 -0.012729 0.013492 -0.038494 0.079915 + 0.003210 -0.036122 -0.001109 -0.000422 -0.005667 0.007256 -0.003800 0.010442 -0.006604 -0.011790 + -0.006632 -0.002961 -0.005837 -0.010132 -0.003216 0.027804 -0.249102 -0.073037 -0.062036 -0.017264 + -0.002456 -0.003227 -0.003811 0.050086 0.026959 -0.032195 0.051518 0.003095 0.002657 -0.002668 + -0.000341 -0.002570 -0.001093 0.001731 -0.024293 -0.001843 -0.014776 -0.004300 0.000540 1.175268 + 0.383207 0.094747 0.035474 0.002667 0.011252 -0.022959 0.082311 -0.081370 0.127110 0.053432 + -0.066748 0.068089 0.004332 0.007963 0.007847 0.001126 -0.001629 -0.001106 -0.019906 -0.015770 + -0.013512 0.013661 + + 7.1 0.02166 0.714200 -0.054399 -0.777112 -0.100052 -0.261354 -0.134809 -1.153913 -0.433183 -0.051521 0.060912 0.003693 + -0.045200 0.260213 0.053453 -0.050756 -0.010334 -0.015403 -0.023382 -0.040261 0.005744 0.013461 + -0.003094 0.004798 -0.073364 -0.015492 0.017712 -0.039403 -0.029622 -0.026598 0.004060 0.010400 + -0.027005 -0.040328 -0.010507 -0.000270 0.002294 -0.007315 -0.007744 -0.003838 -0.002219 -0.013094 + -0.003578 0.002463 -0.008327 -0.018672 0.004444 0.010131 1.251350 0.332566 -0.072548 0.020640 + 0.023829 0.009999 -0.001698 -0.130503 -0.083613 -0.099704 -0.072119 -0.035323 -0.041265 -0.010981 + -0.002338 -0.003035 -0.008294 -0.002773 0.006260 0.011398 -0.001357 0.021804 0.021626 0.196954 + 0.026126 -0.063168 -0.001206 0.003682 0.001544 -0.005519 0.054516 0.015135 -0.009360 0.017717 + 0.006477 -0.014338 0.005114 0.005256 0.004363 0.000142 0.001658 0.018034 0.010337 0.010726 + -0.005282 0.008700 + + 1 1s 1 1s 1 1s 1 1s 1 1s 1 2px 1 2py 1 2pz 1 2px 1 2py + 1 2pz 1 2px 1 2py 1 2pz 1 2px 1 2py 1 2pz 1 3d1+ 1 3d1- 1 3d0 + 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 + 1 3d2- 1 3d2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 1 4f0 1 4f2- 1 4f2+ 1 4f1+ + 1 4f1- 1 4f3+ 1 4f3- 1 4f0 1 4f2- 1 4f2+ 2 1s 2 1s 2 1s 2 1s + 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 3d1+ + 2 3d1- 2 3d0 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 2 3d0 2 3d2- 2 3d2+ 3 1s + 3 1s 3 1s 3 1s 3 2px 3 2py 3 2pz 3 2px 3 2py 3 2pz 3 2px + 3 2py 3 2pz 3 3d1+ 3 3d1- 3 3d0 3 3d2- 3 3d2+ 3 3d1+ 3 3d1- 3 3d0 + 3 3d2- 3 3d2+ + + 1.2 2.00000 -15.519225 0.998154 -0.035978 0.002301 -0.019546 -0.013875 -0.011390 -0.020857 0.019231 0.004898 0.003286 + -0.002871 0.008092 0.003039 -0.002226 0.002765 -0.000338 0.001541 0.000146 -0.000006 0.000051 + 0.000142 -0.000060 0.000258 -0.000873 0.000963 0.000522 -0.001643 0.000987 -0.000413 0.000596 + 0.000237 -0.000919 0.000081 0.000236 -0.000079 -0.000046 0.000199 0.000113 0.000072 -0.000671 + -0.000399 0.000854 -0.000147 -0.000326 -0.000520 -0.000569 -0.004654 0.005641 0.005379 -0.000093 + 0.000147 -0.000031 0.000631 -0.000260 -0.000998 0.000098 -0.000273 -0.000668 0.000393 -0.000268 + -0.000092 -0.000477 0.000015 0.000046 -0.000066 0.000229 -0.000063 0.000021 -0.000220 -0.008043 + 0.004951 0.004045 -0.000386 0.000087 -0.000630 0.000035 -0.000615 -0.000291 0.000537 -0.000077 + -0.000190 0.000119 0.000032 -0.000111 0.000242 0.000302 0.000421 -0.000080 0.000035 0.000121 + -0.000016 0.000052 + + 2.2 1.99755 -0.714512 -0.042589 -0.750671 0.005849 -0.223209 -0.216768 -0.185343 -0.404578 0.367437 0.007161 0.014753 + -0.010461 0.056665 0.009051 0.032816 0.030559 -0.013126 0.029164 0.001878 -0.004651 -0.000742 + 0.006543 0.001705 0.004531 -0.012651 0.002344 0.020413 -0.000615 -0.003336 -0.006897 0.009775 + 0.004038 -0.008186 -0.000032 0.000794 0.001589 -0.002369 0.000543 -0.002308 -0.000031 -0.000077 + -0.001676 0.003982 -0.002524 -0.001018 -0.002771 -0.001189 -0.103503 0.087529 0.151011 0.007170 + 0.001039 -0.002974 0.008241 -0.004846 -0.014376 0.004531 -0.006518 -0.013666 -0.002356 -0.000349 + 0.001430 -0.001789 0.000734 -0.000652 0.000654 0.002392 -0.002718 0.000945 0.000430 -0.185348 + 0.093907 0.096311 -0.005215 -0.000369 -0.008183 0.003228 -0.010710 -0.001360 0.015769 -0.004168 + -0.001128 0.008046 -0.001014 0.001414 0.001177 0.000086 0.002071 0.000189 0.003023 0.000877 + -0.000869 0.001449 + + 3.2 1.97980 -0.780075 0.003923 -0.336311 0.002239 0.146419 0.088681 -0.176228 0.644778 -0.052257 0.012394 -0.028024 + -0.007988 0.013445 -0.079105 -0.021064 -0.018408 0.006436 -0.013847 -0.000162 -0.000577 0.003051 + 0.001237 0.009712 -0.004227 0.002140 0.004768 -0.007683 0.016940 0.000650 0.008781 -0.003707 + -0.002718 0.005749 -0.000603 -0.002099 0.000258 0.003574 -0.001727 -0.000174 -0.001715 -0.000425 + -0.000758 -0.000453 0.001158 0.000945 -0.000753 0.001020 -0.062242 0.020572 -0.001110 -0.000325 + -0.000876 0.005594 -0.000088 -0.001257 0.015844 -0.008124 0.002661 0.011041 -0.004077 0.000869 + -0.001397 0.001484 -0.000661 0.000723 0.001945 -0.002057 0.005138 -0.001036 0.001782 -0.722313 + 0.109528 0.246764 0.006493 0.009715 -0.014208 -0.006985 0.013646 -0.013854 -0.012846 -0.007133 + 0.017567 0.003381 0.001658 -0.002977 0.002338 0.004531 0.001753 -0.001967 0.001644 -0.002800 + -0.003072 -0.002900 + + 4.2 1.97674 -0.617096 -0.003526 0.220084 -0.001692 -0.116646 -0.148595 0.057073 0.116528 0.699764 -0.004869 -0.016226 + -0.031661 -0.010290 -0.050285 -0.034708 0.026172 -0.006062 0.023185 0.010033 0.001770 0.012381 + 0.002344 0.001049 0.019266 0.001530 0.022218 0.002686 0.002455 -0.003255 -0.004709 0.005484 + 0.002685 -0.002948 0.001698 0.002659 -0.000831 0.000210 0.001107 -0.000522 -0.000436 0.002864 + -0.000468 0.001840 -0.001982 0.003308 -0.001341 -0.000921 0.843482 -0.117107 -0.198349 -0.001226 + -0.007407 -0.006871 -0.015181 -0.008398 -0.008915 -0.011930 0.004124 -0.006438 0.018554 0.003957 + 0.003483 0.004386 0.001171 0.000201 -0.002821 -0.003107 -0.004168 -0.000919 0.000038 -0.200841 + 0.012514 0.047672 -0.003528 0.002433 -0.005117 0.004647 0.002841 -0.012838 0.014714 -0.003324 + -0.007164 0.007398 -0.000404 0.000678 0.002248 0.002223 0.001918 0.000475 0.002529 0.003275 + 0.000829 0.002369 + + 5.2 0.03136 0.642425 -0.052890 -0.987157 -0.074595 -0.597169 -0.429606 1.290001 0.298974 -0.324719 0.070540 -0.021129 + 0.027385 0.124835 -0.029262 0.018259 0.110335 0.006419 0.003459 0.015913 0.008165 0.003273 + -0.011135 -0.008802 0.033591 0.012416 0.071599 -0.028723 -0.129888 0.018268 -0.006545 0.041478 + -0.008671 -0.090122 -0.012299 -0.001508 0.014776 0.004358 0.000055 0.001256 -0.000895 -0.026926 + -0.003838 0.032550 0.009190 0.013201 -0.006548 -0.020968 0.343708 0.067445 -0.077016 -0.015643 + 0.005627 -0.000784 0.001075 0.002888 -0.025330 -0.016511 0.008409 -0.009143 0.014330 -0.005000 + 0.000814 -0.002115 0.000213 0.001670 -0.012054 0.000271 -0.005588 -0.002391 -0.008928 0.186556 + 0.021448 -0.119066 -0.018075 0.004299 0.000662 0.001351 -0.003503 -0.000589 0.017708 0.020031 + -0.022199 -0.006701 -0.000125 0.000715 0.000764 0.003902 0.001531 0.002280 -0.001539 0.011054 + 0.005357 0.003840 + + 6.2 0.02279 0.766781 -0.023336 -0.268374 -0.033121 -0.219593 -0.361000 -0.576502 -0.214718 -1.299604 -0.028842 -0.050158 + 0.073801 -0.014973 -0.065730 0.206885 0.054079 -0.018214 0.011657 -0.003095 0.007544 -0.041080 + 0.003732 0.003262 0.013582 -0.021344 -0.092964 -0.000346 0.029942 0.038794 -0.028269 -0.069668 + -0.004511 0.028209 -0.004964 -0.006774 -0.005550 -0.000042 -0.010028 -0.000021 0.002273 0.012771 + -0.009549 -0.005276 -0.010116 0.006637 -0.008883 -0.022357 1.160582 0.364204 0.148395 0.026880 + 0.008044 -0.000781 0.025770 -0.069933 -0.090053 -0.116572 -0.077949 -0.066788 -0.076691 -0.005852 + -0.002660 -0.010515 -0.000930 0.000224 0.018212 0.019287 0.013994 0.012214 -0.007006 -0.143799 + -0.030532 -0.012609 -0.016678 -0.003186 0.000755 0.003537 0.002249 -0.035901 0.033774 -0.017418 + -0.027241 -0.002720 -0.000148 0.001141 0.003573 0.000350 0.001560 0.003978 0.004454 0.016973 + 0.007935 0.011161 + + 7.2 0.02081 0.756045 0.040224 0.545760 0.072609 0.363329 0.342032 0.649427 -1.179228 -0.113974 0.006056 0.068530 + -0.039969 -0.162003 0.250779 -0.031279 -0.052303 -0.018823 -0.048847 0.005236 -0.007545 -0.015867 + -0.011134 -0.038125 -0.021737 0.018420 -0.033577 -0.062622 -0.076483 -0.031508 0.031008 -0.037269 + -0.050637 -0.028691 -0.006649 0.004738 -0.010008 0.008842 0.003819 0.002616 0.004933 -0.005635 + 0.007837 0.000159 0.017643 0.002710 0.001761 0.016733 -0.049703 0.020667 0.041486 0.012433 + -0.000418 0.004028 -0.002630 -0.009476 0.046717 -0.023918 0.027228 0.017737 -0.021742 0.002165 + -0.001757 0.005195 0.000405 0.001190 0.011127 -0.009433 0.020522 -0.000496 0.009476 -1.294391 + -0.365590 0.036256 -0.018040 -0.009148 0.022224 -0.004088 0.112693 -0.135685 -0.100733 0.046270 + -0.085638 -0.032792 -0.000595 0.001368 -0.008513 -0.008323 -0.006441 0.011592 -0.020405 0.004116 + 0.033747 0.009462 + + + Natural orbital dump at molpro section 2140.2 (Orbital set 2) + + + CI vector + ========= + + 222200 222000 0.9705156 + 222000 222200 -0.0837712 + + TOTAL ENERGIES -111.36172907 + + + + ********************************************************************************************************************************** + DATASETS * FILE NREC LENGTH (MB) RECORD NAMES + 1 20 358.60 500 610 700 900 950 970 1000 129 960 1100 + VAR BASINP GEOM SYMINP ZMAT AOBASIS BASIS P2S ABASIS S + 1400 1410 1200 1210 1080 1600 1650 1300 1700 1380 + T V H0 H01 AOSYM SMH MOLCAS ERIS OPER JKOP + + 2 5 6.44 700 1000 520 2100 2140 + GEOM BASIS MCVARS RHF MCSCF + + PROGRAMS * TOTAL MULTI HF INT + CPU TIMES * 75.29 62.81 4.75 7.47 + REAL TIME * 106.70 SEC + DISK USED * 1.30 GB + ********************************************************************************************************************************** + + + PROGRAM * CI (Multireference internally contracted CI) Authors: H.-J. Werner, P.J. Knowles, 1987 + + + Convergence thresholds: THRVAR = 1.00D-08 THRDEN = 1.00D-06 + + Number of optimized states: 1 Roots: 1 + Number of reference states: 1 Roots: 1 + + Reference symmetry: 1 Singlet + Number of electrons: 18 + Maximum number of shells: 8 + Maximum number of spin couplings: 429 + + Reference space: 29202 conf 85092 CSFs + N elec internal: 58278 conf 169884 CSFs + N-1 el internal: 69576 conf 339768 CSFs + N-2 el internal: 73789 conf 608751 CSFs + + Number of electrons in valence space: 14 + Maximum number of open shell orbitals in reference space: 10 + Maximum number of open shell orbitals in internal spaces: 14 + + + Number of core orbitals: 2 ( 1 1 ) + Number of active orbitals: 12 ( 6 6 ) + Number of external orbitals: 170 ( 85 85 ) + + Molecular orbitals read from record 2140.2 Type=MCSCF/NATURAL (state 1.1) + + Coulomb and exchange operators available. No transformation done. + + Number of p-space configurations: 1 + + Reference wavefunction optimized for reference space (refopt=1) + + State Reference Energy + 1 -111.36172907 + + Number of blocks in overlap matrix: 4 Smallest eigenvalue: 0.20D-02 + Number of N-2 electron functions: 144 + Number of N-1 electron functions: 339768 + + Number of internal configurations: 85092 + Number of singly external configurations: 28880280 + Number of doubly external configurations: 1041420 + Total number of contracted configurations: 30006792 + Total number of uncontracted configurations: 4420599512 + + Diagonal Coupling coefficients finished. Storage:37824290 words, CPU-Time: 182.45 seconds. + Energy denominators for pairs finished in 1 passes. Storage: 4651302 words, CPU-time: 0.04 seconds. + + ITER. STATE ROOT SQ.NORM CORR.ENERGY TOTAL ENERGY ENERGY CHANGE DEN1 VAR(S) VAR(P) TIME + 1 1 1 1.00000000 0.00000000 -111.36172907 0.00000000 -0.29420594 0.32D-01 0.33D-01 229.56 + 2 1 1 1.07049611 -0.30548326 -111.66721233 -0.30548326 -0.01158808 0.15D-02 0.12D-02 1372.57 + 3 1 1 1.07613553 -0.31756184 -111.67929091 -0.01207858 -0.00094616 0.14D-03 0.89D-04 2517.64 + 4 1 1 1.07900883 -0.31860896 -111.68033803 -0.00104712 -0.00011548 0.22D-04 0.91D-05 3693.41 + 5 1 1 1.07980819 -0.31873337 -111.68046243 -0.00012441 -0.00001513 0.31D-05 0.11D-05 4847.23 + 6 1 1 1.07992689 -0.31875018 -111.68047924 -0.00001681 -0.00000245 0.53D-06 0.15D-06 6018.74 + 7 1 1 1.07994376 -0.31875288 -111.68048194 -0.00000270 -0.00000044 0.98D-07 0.25D-07 7162.92 + 8 1 1 1.07996071 -0.31875335 -111.68048242 -0.00000048 -0.00000009 0.19D-07 0.50D-08 8346.49 + 9 1 1 1.07997061 -0.31875345 -111.68048252 -0.00000010 -0.00000002 0.36D-08 0.92D-09 9599.42 + + + ===================================== + Analysis of CPU times by interactions + ===================================== + + I S P + + I 0.5% + S 0.9% 9.1% + P 2.7% 74.5% 9.8% + + Initialization: 2.1% + Other: 0.4% + + Total CPU: 9599.4 seconds + ===================================== + + + + Reference coefficients greater than 0.0500000 + ============================================= + 222200222000 0.9373617 + 222000222200 -0.0755253 + 22/2/02\200\ 0.0545580 + + + + RESULTS FOR STATE 1.1 + ===================== + + Coefficient of reference function: C(0) = 0.96195400 (fixed) 0.96226354 (relaxed) + + Energy contributions of configuration classes + + CLASS SQ.NORM ECORR1 ECORR2 + +++++++++++++++++++++++++++++++++++++++++++++++++++ + Internals 0.00064368 -0.00000001 -0.00018997 + Singles 0.03419495 -0.10821557 -0.11022440 + Pairs 0.04582714 -0.21053776 -0.20833908 + Total 1.08066576 -0.31875334 -0.31875345 + +++++++++++++++++++++++++++++++++++++++++++++++++++ + + + Reference energy -111.36172907 + Nuclear energy 41.78471756 + Kinetic energy 111.62870721 + One electron energy -233.37114277 + Two electron energy 79.90594269 + Virial quotient -1.00046382 + Correlation energy -0.31875345 + !MRCI STATE 1.1 Energy -111.680482516555 + + Properties without orbital relaxation: + + !MRCI STATE 1.1 Dipole moment 0.00000000 0.00000000 0.73462279 + Dipole moment /Debye 0.00000000 0.00000000 1.86710260 + + Cluster corrected energies -111.70619501 (Davidson, fixed reference) + Cluster corrected energies -111.70597342 (Davidson, relaxed reference) + + Cluster corrected energies -111.70384836 (Pople, fixed reference) + Cluster corrected energies -111.70363518 (Pople, relaxed reference) + + + + ********************************************************************************************************************************** + DATASETS * FILE NREC LENGTH (MB) RECORD NAMES + 1 20 358.60 500 610 700 900 950 970 1000 129 960 1100 + VAR BASINP GEOM SYMINP ZMAT AOBASIS BASIS P2S ABASIS S + 1400 1410 1200 1210 1080 1600 1650 1300 1700 1380 + T V H0 H01 AOSYM SMH MOLCAS ERIS OPER JKOP + + 2 5 6.44 700 1000 520 2100 2140 + GEOM BASIS MCVARS RHF MCSCF + + PROGRAMS * TOTAL MRCI MULTI HF INT + CPU TIMES * 9759.63 9684.34 62.81 4.75 7.47 + REAL TIME * 10219.52 SEC + DISK USED * 5.19 GB + ********************************************************************************************************************************** + SETTING E_MRCI = -111.68048252 AU + SETTING E_MRCI_DAVIDSON= -111.70597342 AU + + + E_MRCI E_MRCI_DAVIDSON + -111.6804825 -111.7059734 + + + MRCI/aug-cc-pVTZ energy= -111.680482516555 + + MRCI MULTI HF-SCF + -111.68048252 -111.36172907 -111.22812175 + ********************************************************************************************************************************** + Molpro calculation terminated + Variable memory released diff --git a/arkane/data/molpro_mrci.out b/arkane/data/molpro_mrci.out new file mode 100644 index 0000000000..24c125bfc3 --- /dev/null +++ b/arkane/data/molpro_mrci.out @@ -0,0 +1,792 @@ + + Primary working directories : /tmp + Secondary working directories : /tmp + Wavefunction directory : /home/alongd/wfu/ + Main file repository : /tmp/ + + SHA1 : 5e3d8ac6839c721e2824de82269b4736200146bd + NAME : 2015.1.37 + ARCHNAME : linux/x86_64 + FC : /opt/intel/composer_xe_2015.1.133/bin/intel64/ifort + BLASLIB : -Wl,-_start-group /opt/intel/mkl/lib/intel64/libmkl_intel_ilp64.a /opt/intel/mkl/lib/intel64/libmkl_intel_thread.a /opt/intel/mkl/lib/intel64/libmkl_core.a -Wl,-_end-group + id : phalgunlolur + + Nodes nprocs + node07 1 + + Using customized tuning parameters: mindgm=1; mindgv=20; mindgc=4; mindgr=1; noblas=0; minvec=7 + default implementation of scratch files=df + + ***,name + memory,500,m; + + geometry={angstrom; + N 0.7033634988 0.0974820728 -0.0730473920 + N -0.7033634988 -0.0974820728 -0.0730473920 + H 1.0539960456 0.3871635195 0.8315583036 + H -1.0539960456 -0.3871635195 0.8315583036 + H 1.1434808787 -0.7765990298 -0.3202265599 + H -1.1434808787 0.7765990298 -0.3202265599 + } + + gprint,orbitals; + + basis=aug-cc-pVTZ + + {hf; + maxit,1000; + wf,spin=0,charge=0} + + put,molden,orbitals_1_hf.mol + + {multi; + noextra,failsafe,config,csf; + wf,spin=0,charge=0; + natorb,print,ci;} + + {mrci; + wf,spin=0,charge=0} + + + Variables initialized (889), CPU time= 0.01 sec + Commands initialized (702), CPU time= 0.01 sec, 572 directives. + Default parameters read. Elapsed time= 0.07 sec + + Checking input... + Passed +1 + + + *** PROGRAM SYSTEM MOLPRO *** + Copyright, TTI GmbH Stuttgart, 2015 + Version 2015.1 linked Aug 10 2018 15:00:15 + + + ********************************************************************************************************************************** + LABEL * name + 64 bit serial version DATE: 31-Oct-18 TIME: 06:23:05 + ********************************************************************************************************************************** + + SHA1: 5e3d8ac6839c721e2824de82269b4736200146bd + ********************************************************************************************************************************** + +Geometry recognized as XYZ + + + + Variable memory set to 500000000 words, buffer space 230000 words + + SETTING BASIS = AUG-CC-PVTZ + + + Recomputing integrals since basis changed + + + Using spherical harmonics + + Library entry N S aug-cc-pVTZ selected for orbital group 1 + Library entry N P aug-cc-pVTZ selected for orbital group 1 + Library entry N D aug-cc-pVTZ selected for orbital group 1 + Library entry N F aug-cc-pVTZ selected for orbital group 1 + Library entry H S aug-cc-pVTZ selected for orbital group 2 + Library entry H P aug-cc-pVTZ selected for orbital group 2 + Library entry H D aug-cc-pVTZ selected for orbital group 2 + + + PROGRAM * SEWARD (Integral evaluation for generally contracted gaussian basis sets) Author: Roland Lindh, 1990 + + Geometry written to block 1 of record 700 + + + Point group C2 + + + + ATOMIC COORDINATES + + NR ATOM CHARGE X Y Z + + 1 N 7.00 1.329164379 0.184214420 -0.138039565 + 2 N 7.00 -1.329164379 -0.184214420 -0.138039565 + 3 H 1.00 1.991763863 0.731633017 1.571417450 + 4 H 1.00 -1.991763863 -0.731633017 1.571417450 + 5 H 1.00 2.160865689 -1.467559475 -0.605140496 + 6 H 1.00 -2.160865689 1.467559475 -0.605140496 + + Bond lengths in Bohr (Angstrom) + + 1-2 2.683738361 1-3 1.913360521 1-5 1.907424271 2-4 1.913360521 2-6 1.907424271 + ( 1.420173181) ( 1.012506784) ( 1.009365456) ( 1.012506784) ( 1.009365456) + + Bond angles + + 1-2-4 112.47618938 1-2-6 108.24151671 2-1-3 112.47618938 2-1-5 108.24151671 + + 3-1-5 108.39381540 4-2-6 108.39381540 + + NUCLEAR CHARGE: 18 + NUMBER OF PRIMITIVE AOS: 242 + NUMBER OF SYMMETRY AOS: 216 + NUMBER OF CONTRACTIONS: 184 ( 92A + 92B ) + NUMBER OF CORE ORBITALS: 2 ( 1A + 1B ) + NUMBER OF VALENCE ORBITALS: 12 ( 6A + 6B ) + + + NUCLEAR REPULSION ENERGY 41.78471756 + + Eigenvalues of metric + + 1 0.189E-03 0.324E-03 0.107E-02 0.168E-02 0.262E-02 0.292E-02 0.299E-02 0.382E-02 + 2 0.745E-04 0.179E-03 0.324E-03 0.433E-03 0.138E-02 0.196E-02 0.245E-02 0.301E-02 + + + Contracted 2-electron integrals neglected if value below 1.0D-11 + AO integral compression algorithm 1 Integral accuracy 1.0D-11 + + 419.430 MB (compressed) written to integral file ( 51.9%) + + + NUMBER OF SORTED TWO-ELECTRON INTEGRALS: 73209414. BUFFER LENGTH: 32768 + NUMBER OF SEGMENTS: 5 SEGMENT LENGTH: 15999809 RECORD LENGTH: 524288 + + Memory used in sort: 16.56 MW + + SORT1 READ 101111688. AND WROTE 70607682. INTEGRALS IN 204 RECORDS. CPU TIME: 1.31 SEC, REAL TIME: 2.12 SEC + SORT2 READ 70607682. AND WROTE 73209414. INTEGRALS IN 1600 RECORDS. CPU TIME: 1.60 SEC, REAL TIME: 2.05 SEC + + FILE SIZES: FILE 1: 440.3 MBYTE, FILE 4: 855.7 MBYTE, TOTAL: 1295.9 MBYTE + + OPERATOR DM FOR CENTER 0 COORDINATES: 0.000000 0.000000 0.000000 + + + ********************************************************************************************************************************** + DATASETS * FILE NREC LENGTH (MB) RECORD NAMES + 1 19 336.96 500 610 700 900 950 970 1000 129 960 1100 + VAR BASINP GEOM SYMINP ZMAT AOBASIS BASIS P2S ABASIS S + 1400 1410 1200 1210 1080 1600 1650 1300 1700 + T V H0 H01 AOSYM SMH MOLCAS ERIS OPER + + PROGRAMS * TOTAL INT + CPU TIMES * 7.60 7.47 + REAL TIME * 34.76 SEC + DISK USED * 1.30 GB + ********************************************************************************************************************************** + + + PROGRAM * RHF-SCF (CLOSED SHELL) Authors: W. Meyer, H.-J. Werner + + + NUMBER OF ELECTRONS: 9+ 9- + CONVERGENCE THRESHOLDS: 1.00E-05 (Density) 1.00E-07 (Energy) + MAX. NUMBER OF ITERATIONS: 1000 + INTERPOLATION TYPE: DIIS + INTERPOLATION STEPS: 2 (START) 1 (STEP) + LEVEL SHIFTS: 0.00 (CLOSED) 0.00 (OPEN) + + + + Orbital guess generated from atomic densities. Full valence occupancy: 7 7 + + Molecular orbital dump at record 2100.2 + + Initial occupancy: 5 4 + + ITERATION DDIFF GRAD ENERGY 2-EL.EN. DIPOLE MOMENTS DIIS ORB. + 1 0.000D+00 0.000D+00 -111.20146194 162.183852 0.00000 0.00000 1.05870 0 start + 2 0.000D+00 0.571D-02 -111.22566575 160.629648 0.00000 0.00000 0.68797 1 diag + 3 0.614D-02 0.180D-02 -111.22778162 161.505282 0.00000 0.00000 0.78591 2 diag + 4 0.147D-02 0.604D-03 -111.22809585 161.219331 0.00000 0.00000 0.77644 3 diag + 5 0.519D-03 0.142D-03 -111.22812007 161.265894 0.00000 0.00000 0.77787 4 diag + 6 0.959D-04 0.265D-04 -111.22812161 161.261433 0.00000 0.00000 0.77945 5 diag + 7 0.286D-04 0.643D-05 -111.22812174 161.261637 0.00000 0.00000 0.77971 6 diag + 8 0.118D-04 0.184D-05 -111.22812175 161.261629 0.00000 0.00000 0.77981 7 diag + 9 0.406D-05 0.416D-06 -111.22812175 161.261592 0.00000 0.00000 0.77981 0 orth + + Final occupancy: 5 4 + + !RHF STATE 1.1 Energy -111.228121747966 + Nuclear energy 41.78471756 + One-electron energy -233.64363506 + Two-electron energy 80.63079575 + Virial quotient -1.00155086 + !RHF STATE 1.1 Dipole moment 0.00000000 0.00000000 0.77980560 + Dipole moment /Debye 0.00000000 0.00000000 1.98193833 + + ELECTRON ORBITALS + ================= + + + Orb Occ Energy Couls-En Coefficients + + 1 1s 1 1s 1 1s 1 1s 1 1s 1 2pz 1 2px 1 2py 1 2pz 1 2px + 1 2py 1 2pz 1 2px 1 2py 1 2pz 1 2px 1 2py 1 3d0 1 3d2- 1 3d2+ + 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ + 1 3d1+ 1 3d1- 1 4f0 1 4f2- 1 4f2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 1 4f0 + 1 4f2- 1 4f2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 2 1s 2 1s 2 1s 2 1s + 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 3d0 + 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 2 3d0 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 3 1s + 3 1s 3 1s 3 1s 3 2pz 3 2px 3 2py 3 2pz 3 2px 3 2py 3 2pz + 3 2px 3 2py 3 3d0 3 3d2- 3 3d2+ 3 3d1+ 3 3d1- 3 3d0 3 3d2- 3 3d2+ + 3 3d1+ 3 3d1- + + 1.1 2 -15.5688 -44.1782 0.999650 0.001134 0.000986 -0.000950 0.001382 0.003546 -0.002517 -0.003563 -0.002373 0.001172 + 0.002280 -0.001682 -0.000546 0.002362 0.000063 -0.000354 -0.000050 -0.000039 -0.000039 0.000058 + 0.000095 0.000119 0.000292 0.000041 -0.000331 -0.000237 0.000124 -0.000256 -0.000851 0.000643 + -0.000492 -0.000050 0.000202 0.000187 0.000031 0.000084 0.000200 -0.000173 0.000080 -0.000100 + -0.000409 0.000225 -0.000330 -0.000423 0.000490 0.000344 0.001662 -0.000206 -0.000790 -0.000065 + 0.000192 0.000077 0.000054 -0.000060 0.000407 0.000141 -0.000166 0.000290 -0.000154 -0.000256 + -0.000120 -0.000128 -0.000285 -0.000143 0.000128 0.000193 -0.000237 0.000136 0.000008 0.001212 + 0.000393 -0.002908 -0.000089 -0.000025 0.000135 -0.000213 0.000424 0.000455 0.000294 -0.000068 + 0.000469 -0.000421 0.000195 0.000342 0.000137 0.000011 -0.000049 0.000151 -0.000095 -0.000369 + -0.000011 0.000200 + + 2.1 2 -1.2593 -10.8982 -0.011849 0.848436 -0.012605 -0.116716 0.010403 0.058998 -0.147408 -0.068617 0.004013 -0.001166 + -0.004130 -0.018708 0.033885 0.034793 -0.001771 0.002511 0.001022 -0.003536 0.000492 0.005900 + 0.000281 0.002697 -0.007854 0.001972 0.014655 0.000935 0.002733 -0.001455 -0.004369 0.007321 + -0.000628 -0.007011 0.001268 0.001094 0.001110 0.004354 0.002328 -0.005534 -0.001492 -0.001371 + -0.000744 0.001360 0.000954 -0.000914 0.000193 -0.001152 0.310785 -0.082321 -0.123747 -0.000114 + -0.007656 -0.004324 -0.002942 -0.003014 -0.008936 -0.002225 0.007832 0.000037 0.003134 0.000303 + 0.000751 0.000802 0.001565 0.000298 -0.003906 0.001236 -0.000216 0.000502 -0.002294 0.309379 + -0.076651 -0.130009 -0.002267 0.002581 -0.005279 0.007582 0.003401 -0.007594 0.002654 0.000174 + 0.003329 -0.010047 -0.000863 -0.001429 0.000407 -0.000701 0.000211 0.003263 0.001247 0.001709 + -0.001195 -0.001646 + + 3.1 2 -0.6802 -8.9801 -0.001099 -0.075065 0.001594 -0.019639 -0.009278 0.627882 0.288389 0.218962 -0.028169 -0.010266 + -0.016313 -0.069322 -0.044578 -0.039463 0.007030 -0.000078 0.001824 0.013511 0.002078 -0.002631 + 0.001366 0.000291 0.026743 0.000233 -0.009553 -0.007994 -0.001194 0.010671 0.008695 -0.009225 + 0.000836 -0.000888 -0.002567 0.000829 0.002546 -0.002000 0.001490 0.002644 0.000762 0.001747 + -0.001093 0.001016 -0.000930 -0.001110 0.003329 0.001668 0.699297 -0.088457 -0.233063 -0.005406 + -0.015764 -0.006439 -0.005601 -0.025258 -0.006607 -0.007891 0.013562 0.008160 0.006152 0.005036 + 0.001158 0.000015 0.003493 0.003648 -0.000388 -0.002393 0.000633 -0.004649 -0.001842 -0.262810 + 0.040661 0.116153 0.006014 0.002991 0.006356 -0.005954 0.012084 0.015721 -0.009011 0.009105 + -0.002478 0.010602 0.002454 0.003368 0.000147 -0.000117 0.000879 0.001837 0.003276 0.001240 + -0.000605 0.002892 + + 4.1 2 -0.6131 -9.2487 -0.000935 0.005851 0.003991 0.045543 0.008822 -0.165790 0.752552 -0.231357 0.008349 -0.020873 + 0.015405 0.027554 -0.069476 0.030094 0.000071 0.007254 0.001669 0.002089 -0.012169 -0.014266 + 0.003648 0.002833 0.011205 -0.023815 -0.037677 0.009679 0.007357 0.013142 -0.006502 -0.021211 + 0.004082 0.004235 0.001067 0.001105 0.000055 -0.004307 -0.000656 0.004853 0.001861 0.002776 + -0.003882 -0.000385 -0.003637 0.002370 0.000346 0.006732 0.067149 -0.027476 -0.038632 -0.000533 + -0.003203 0.006194 -0.002390 -0.003371 0.024407 -0.004703 0.001607 0.009371 -0.000579 0.002392 + -0.001003 -0.002361 -0.002903 0.001257 0.001220 -0.002470 -0.002025 -0.006292 0.000463 0.638301 + -0.093293 -0.182553 -0.000181 0.003861 -0.001920 0.016050 0.002779 0.013284 0.025682 0.000113 + 0.013959 -0.002003 -0.002069 -0.001915 -0.006548 -0.000180 0.002926 0.000265 0.008866 -0.004306 + 0.002152 -0.002284 + + 5.1 2 -0.4073 -8.5581 0.001992 0.205454 0.001466 0.161014 0.082435 -0.397480 0.233009 0.727686 0.005251 0.005337 + -0.020700 -0.015386 0.012510 0.024389 -0.020514 0.012122 0.040328 0.004674 0.006494 0.001245 + 0.006738 0.004254 0.011950 0.013533 -0.000448 0.020082 0.014017 0.003801 -0.011391 -0.003530 + 0.007581 0.010783 0.000573 0.001371 -0.003913 -0.001273 -0.000865 0.002776 -0.000603 0.004572 + 0.000340 -0.001617 0.003978 0.000359 0.001976 -0.001074 0.118432 -0.039833 -0.023900 0.003957 + -0.006290 0.002547 0.007080 -0.007714 0.011364 0.026345 -0.013765 0.007928 0.013978 0.003688 + -0.001516 0.000207 -0.000558 -0.002202 0.005626 -0.000566 0.001378 -0.002296 -0.004338 -0.399053 + 0.018451 0.022312 -0.010715 -0.007693 0.006501 -0.003087 -0.019605 0.016646 -0.002772 -0.017471 + 0.006402 0.006830 0.000439 0.003155 -0.000226 0.002146 -0.003218 -0.002298 0.001883 -0.005861 + 0.001633 -0.000820 + + 1 1s 1 1s 1 1s 1 1s 1 1s 1 2px 1 2py 1 2pz 1 2px 1 2py + 1 2pz 1 2px 1 2py 1 2pz 1 2px 1 2py 1 2pz 1 3d1+ 1 3d1- 1 3d0 + 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 + 1 3d2- 1 3d2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 1 4f0 1 4f2- 1 4f2+ 1 4f1+ + 1 4f1- 1 4f3+ 1 4f3- 1 4f0 1 4f2- 1 4f2+ 2 1s 2 1s 2 1s 2 1s + 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 3d1+ + 2 3d1- 2 3d0 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 2 3d0 2 3d2- 2 3d2+ 3 1s + 3 1s 3 1s 3 1s 3 2px 3 2py 3 2pz 3 2px 3 2py 3 2pz 3 2px + 3 2py 3 2pz 3 3d1+ 3 3d1- 3 3d0 3 3d2- 3 3d2+ 3 3d1+ 3 3d1- 3 3d0 + 3 3d2- 3 3d2+ + + 1.2 2 -15.5684 -44.1781 0.999333 -0.000306 0.001609 -0.010679 -0.004683 -0.002751 -0.003626 0.003590 0.004802 0.002699 + -0.002473 0.005930 0.002803 -0.003788 0.001519 0.000248 0.000261 0.000065 0.000192 0.000098 + -0.000148 -0.000162 0.000104 -0.000277 0.000921 -0.000419 -0.001722 0.001115 -0.000127 0.000205 + 0.000043 -0.000635 0.000082 0.000208 -0.000149 0.000058 0.000181 0.000221 0.000076 -0.000676 + -0.000323 0.000689 -0.000038 -0.000269 -0.000389 -0.000530 0.001300 0.001474 -0.001717 -0.000430 + 0.000092 0.000085 0.000234 -0.000045 -0.000394 -0.000097 0.000034 -0.000080 0.000534 -0.000245 + -0.000145 -0.000391 -0.000013 0.000076 -0.000116 0.000118 0.000032 -0.000020 -0.000241 0.001511 + 0.000459 -0.000805 -0.000177 0.000088 -0.000234 -0.000092 -0.000151 -0.000248 -0.000132 0.000140 + -0.000207 -0.000250 0.000071 -0.000165 0.000186 0.000288 0.000325 -0.000080 -0.000103 0.000102 + 0.000039 0.000005 + + 2.2 2 -1.0098 -9.6395 -0.008232 0.787505 -0.007976 -0.004692 0.022089 0.254919 -0.089988 0.089736 -0.014027 -0.002064 + 0.001436 -0.045221 0.019539 -0.019945 0.003154 0.001245 0.000248 0.003134 0.004185 0.003795 + -0.003887 -0.006627 0.008315 0.006854 0.005289 -0.007077 -0.009574 0.000582 -0.002969 -0.001195 + 0.000078 -0.000190 0.001164 0.001899 -0.001529 -0.000734 0.001132 0.001333 0.000911 0.001424 + 0.001198 -0.001273 -0.000125 0.001528 0.001595 -0.000555 0.466413 -0.116589 -0.181609 -0.004641 + -0.003580 -0.004750 -0.012509 -0.001019 -0.005248 -0.006531 0.003778 -0.000591 0.010737 0.001533 + 0.001631 0.002252 0.000527 0.000082 -0.002637 -0.001269 -0.002990 -0.000187 -0.001296 0.485311 + -0.121446 -0.198097 -0.002529 -0.005227 0.012821 0.004482 -0.002303 0.007639 0.004803 0.005627 + -0.012295 -0.004382 -0.000659 0.001417 -0.001372 -0.002169 -0.001725 0.001159 -0.001557 0.002369 + 0.002447 0.001725 + + 3.2 2 -0.6699 -8.8210 0.000283 0.112462 -0.000627 0.098458 0.034117 -0.036137 0.650136 0.279474 0.003116 -0.031169 + -0.019870 -0.013730 -0.084102 -0.039802 -0.005883 0.005670 -0.003089 0.005870 0.001977 0.009574 + 0.000515 0.006709 0.007836 0.006448 0.016203 -0.010562 0.013771 -0.000305 0.005472 -0.002309 + -0.001788 0.004302 0.000548 -0.000101 -0.001011 0.003582 -0.000742 0.000286 -0.001463 0.001430 + -0.000344 -0.000617 0.000277 0.003203 -0.000588 0.000363 0.509245 -0.081031 -0.168796 -0.003570 + -0.005893 0.000568 -0.012702 -0.006171 0.009983 -0.018565 0.006324 0.008253 0.008225 0.003367 + 0.000811 0.004514 0.000065 0.000892 -0.000212 -0.003945 0.002387 -0.001551 0.001310 -0.587856 + 0.055899 0.181449 0.004500 0.009283 -0.012185 -0.003298 0.017514 -0.023475 -0.005386 -0.005550 + 0.006808 0.005036 0.001360 -0.002354 0.002935 0.004964 0.002057 -0.000983 0.001472 0.000222 + -0.000792 -0.000568 + + 4.2 2 -0.4141 -8.5110 -0.002842 -0.289065 0.000034 -0.268178 -0.268859 -0.051823 -0.388259 0.731925 -0.000128 0.007007 + -0.023721 0.030318 -0.004190 0.011090 0.042844 -0.014801 0.040234 0.008149 -0.001676 0.006288 + 0.005883 -0.000612 0.017671 -0.009072 0.014547 0.018441 -0.003308 -0.004766 -0.010404 0.011037 + 0.005677 -0.008876 0.001119 0.002796 0.000613 -0.002569 0.001459 -0.002072 0.000156 0.001726 + -0.001448 0.004337 -0.003471 0.001353 -0.002808 -0.002231 0.487635 -0.018547 -0.027897 0.003833 + -0.004426 -0.008472 -0.005298 -0.010999 -0.021630 -0.008669 -0.003937 -0.016325 0.008094 0.002396 + 0.003983 0.001495 0.001613 -0.000486 -0.001424 0.000726 -0.005536 0.000585 -0.000009 -0.066865 + 0.045166 0.029537 -0.007943 -0.001461 -0.005003 0.007412 -0.010241 -0.004210 0.025011 -0.003515 + -0.009169 0.009579 -0.001515 0.002380 0.001659 0.000200 0.002216 0.000935 0.003609 0.003433 + 0.000580 0.003314 + + HOMO 5.1 -0.407323 = -11.0838eV + LUMO 6.1 0.029650 = 0.8068eV + LUMO-HOMO 0.436973 = 11.8906eV + + + ********************************************************************************************************************************** + DATASETS * FILE NREC LENGTH (MB) RECORD NAMES + 1 19 336.96 500 610 700 900 950 970 1000 129 960 1100 + VAR BASINP GEOM SYMINP ZMAT AOBASIS BASIS P2S ABASIS S + 1400 1410 1200 1210 1080 1600 1650 1300 1700 + T V H0 H01 AOSYM SMH MOLCAS ERIS OPER + + 2 4 3.20 700 1000 520 2100 + GEOM BASIS MCVARS RHF + + PROGRAMS * TOTAL HF INT + CPU TIMES * 12.35 4.75 7.47 + REAL TIME * 40.34 SEC + DISK USED * 1.30 GB + ********************************************************************************************************************************** + + Dump information in style MOLDEN to orbitals_1_hf.mol + + Molecular orbitals read from record 2100.2 Type=RHF/CANONICAL (state 1.1) + Occupation numbers read from record 2100.2 Type=RHF/RHF (state 1.1) + Orbital energies read from record 2100.2 Type=RHF/CANONICAL (state 1.1) + Redundancy group numbers read from rec 2100.2 Type=RHF/RHF (state 1.1) + + DUMP ORBITAL 1.1 AS ORBITAL 1 occ= 2.0000 eig= -15.5688 GROUP= 2 + DUMP ORBITAL 1.2 AS ORBITAL 2 occ= 2.0000 eig= -15.5684 GROUP= 2 + DUMP ORBITAL 2.1 AS ORBITAL 3 occ= 2.0000 eig= -1.2593 GROUP= 2 + DUMP ORBITAL 2.2 AS ORBITAL 4 occ= 2.0000 eig= -1.0098 GROUP= 2 + DUMP ORBITAL 3.1 AS ORBITAL 5 occ= 2.0000 eig= -0.6802 GROUP= 2 + DUMP ORBITAL 3.2 AS ORBITAL 6 occ= 2.0000 eig= -0.6699 GROUP= 2 + DUMP ORBITAL 4.1 AS ORBITAL 7 occ= 2.0000 eig= -0.6131 GROUP= 2 + DUMP ORBITAL 4.2 AS ORBITAL 8 occ= 2.0000 eig= -0.4141 GROUP= 2 + DUMP ORBITAL 5.1 AS ORBITAL 9 occ= 2.0000 eig= -0.4073 GROUP= 2 + + Total charge: 18.000000 + + ********************************************************************************************************************************** + + + PROGRAM * MULTI (Direct Multiconfiguration SCF) Authors: P.J. Knowles, H.-J. Werner (1984) S.T. Elbert (1988) + + + Number of closed-shell orbitals: 2 ( 1 1 ) + Number of active orbitals: 12 ( 6 6 ) + Number of external orbitals: 170 ( 85 85 ) + + State symmetry 1 + + Number of electrons: 14 Spin symmetry=Singlet Space symmetry=1 + Number of states: 1 + Number of CSFs: 85092 (313632 determinants, 627264 intermediate states) + + Molecular orbitals read from record 2100.2 Type=RHF/CANONICAL (state 1.1) + + Wavefunction dump at record 2140.2 + + Convergence thresholds 0.10E-01 (gradient) 0.10E-05 (energy) 0.10E-02 (step length) + + Number of orbital rotations: 1202 ( 12 Core/Active 170 Core/Virtual 0 Active/Active 1020 Active/Virtual) + Total number of variables: 314834 + + + ITER. MIC NCI NEG ENERGY(VAR) ENERGY(PROJ) ENERGY CHANGE GRAD(0) GRAD(ORB) GRAD(CI) STEP TIME + + 1 80 22 0 -111.22824300 -111.37280951 -0.14456652 0.00072114 0.00529068 0.06570182 0.19D+01 15.18 + 2 37 30 0 -111.35750945 -111.36172482 -0.00421537 0.07436063 0.00000354 0.00013192 0.29D+00 36.16 + 3 40 19 0 -111.36172900 -111.36172907 -0.00000006 0.00030586 0.00000169 0.00002137 0.80D-03 49.85 + + ** WVFN **** CONVERGENCE REACHED, FINAL GRADIENT: 0.28D-05 + + + First order charge density matrix for state 1.1 saved on record 2140.2 (density set 1) + + Results for state 1.1 + ===================== + + !MCSCF STATE 1.1 Energy -111.361729066869 + Nuclear energy 41.78471756 + Kinetic energy 111.41243376 + One electron energy -233.60673323 + Two electron energy 80.46028660 + Virial ratio 1.99954489 + + !MCSCF STATE 1.1 Dipole moment 0.00000000 0.00000000 0.72629767 + Dipole moment /Debye 0.00000000 0.00000000 1.84594363 + + + NATURAL ORBITALS + ================ + + Orb Occ Energy Coefficients + + 1 1s 1 1s 1 1s 1 1s 1 1s 1 2pz 1 2px 1 2py 1 2pz 1 2px + 1 2py 1 2pz 1 2px 1 2py 1 2pz 1 2px 1 2py 1 3d0 1 3d2- 1 3d2+ + 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ + 1 3d1+ 1 3d1- 1 4f0 1 4f2- 1 4f2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 1 4f0 + 1 4f2- 1 4f2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 2 1s 2 1s 2 1s 2 1s + 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 3d0 + 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 2 3d0 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 3 1s + 3 1s 3 1s 3 1s 3 2pz 3 2px 3 2py 3 2pz 3 2px 3 2py 3 2pz + 3 2px 3 2py 3 3d0 3 3d2- 3 3d2+ 3 3d1+ 3 3d1- 3 3d0 3 3d2- 3 3d2+ + 3 3d1+ 3 3d1- + + 1.1 2.00000 -15.483138 0.997552 -0.049885 0.001966 -0.003550 -0.002987 0.027748 -0.014130 -0.025776 -0.003134 0.000945 + 0.002854 -0.001273 -0.002196 -0.001279 0.001150 -0.001121 -0.001853 0.000040 -0.000136 -0.000084 + -0.000258 -0.000233 0.000282 -0.000222 -0.000554 -0.001410 -0.000781 -0.000440 -0.000004 0.000645 + -0.000844 -0.000257 0.000072 0.000066 0.000175 -0.000022 0.000154 -0.000077 0.000156 -0.000252 + -0.000363 0.000246 -0.000508 -0.000440 0.000445 0.000346 -0.011553 0.004999 0.004274 -0.000289 + 0.000703 0.000003 -0.000139 0.000138 -0.000106 -0.000896 0.000167 -0.000072 -0.000829 -0.000409 + -0.000065 -0.000137 -0.000254 -0.000044 0.000065 0.000173 -0.000247 0.000258 0.000272 -0.008767 + 0.005363 0.006639 0.000601 0.000161 0.000208 -0.000758 0.001199 0.000069 -0.000177 0.000784 + -0.000142 -0.000136 0.000277 0.000346 0.000228 -0.000044 0.000041 0.000109 -0.000346 -0.000139 + -0.000063 0.000379 + + 2.1 1.99834 -0.890681 0.060890 0.731252 -0.007757 0.045544 0.066217 -0.375078 0.177195 0.342885 0.012487 0.000958 + -0.009043 -0.004670 0.022913 0.053962 -0.016445 0.011389 0.027196 -0.001237 0.001401 0.002200 + 0.005430 0.005491 0.000375 0.004693 0.003114 0.017642 0.013139 0.002675 -0.013381 -0.000045 + 0.005390 0.003291 0.001910 0.001734 -0.002240 0.001433 0.000576 -0.001190 -0.001088 0.002414 + -0.001010 -0.000433 0.002619 0.000225 0.000939 -0.000121 0.182473 -0.073620 -0.068993 0.003470 + -0.007264 0.001335 0.003129 -0.003424 0.008143 0.016135 -0.006049 0.005377 0.010097 0.002271 + -0.000932 0.000123 -0.000624 -0.001621 0.001427 0.000338 0.000177 -0.001845 -0.003988 0.133911 + -0.069879 -0.139530 -0.010424 -0.002990 -0.000878 0.007883 -0.012038 0.005854 0.007857 -0.013171 + 0.009238 -0.003821 -0.001203 0.000093 -0.001402 0.000916 -0.001462 0.000428 0.003536 -0.003966 + 0.000800 -0.002637 + + 3.1 1.98037 -0.833190 -0.006118 0.374859 -0.003976 -0.156457 -0.037454 0.641639 -0.009650 -0.198435 -0.023323 -0.009737 + -0.003481 -0.058728 -0.014287 -0.015550 0.011864 -0.003911 -0.015069 0.005426 -0.000965 0.001276 + -0.001961 -0.000246 0.008768 -0.003825 0.002485 -0.013355 -0.004514 0.004722 0.007375 -0.000303 + -0.003202 -0.009761 -0.001032 0.000674 0.003959 0.001904 0.002887 -0.002764 -0.000080 -0.001344 + -0.001476 0.002213 -0.001777 -0.001319 0.001674 0.000794 0.614008 -0.095080 -0.218731 -0.005161 + -0.011273 -0.007623 -0.008188 -0.009572 -0.012259 -0.016446 0.021376 0.002784 0.000131 0.001741 + 0.001748 0.000409 0.003268 0.003275 -0.005584 -0.000867 -0.000435 -0.002422 -0.001458 0.171789 + -0.024792 -0.004617 0.007389 0.006616 -0.001375 0.001114 0.017974 -0.000064 -0.005621 0.013907 + -0.001748 -0.003397 0.001053 0.000251 0.000576 -0.001323 0.001897 0.004409 0.002324 0.004327 + -0.001685 0.001047 + + 4.1 1.97716 -0.600301 0.002787 -0.140733 0.001045 0.089676 0.036678 0.206398 -0.048602 0.695855 -0.019829 0.008642 + -0.032777 -0.063086 0.010547 -0.041235 -0.007778 0.002848 0.022313 0.010838 0.010880 0.005740 + 0.002629 0.000672 0.018756 0.019178 0.010945 0.002286 0.002603 0.002090 0.002073 0.002466 + 0.002627 0.005221 -0.001980 0.000357 -0.001192 -0.000617 0.000061 0.002159 -0.000596 0.002410 + 0.001838 -0.000552 0.003402 -0.001582 0.002636 -0.002497 0.362608 -0.040883 -0.096848 -0.000604 + -0.008655 -0.004060 0.002875 -0.013733 -0.006423 0.013578 -0.003108 0.004783 0.010676 0.003582 + 0.000087 0.001109 0.002651 0.000064 0.002966 -0.000737 0.002195 -0.001008 -0.003200 -0.796472 + 0.105296 0.203002 -0.002382 -0.005154 0.009005 -0.013962 -0.006204 0.010111 -0.013611 -0.006080 + -0.006938 0.015928 0.002688 0.004704 0.003036 0.001310 -0.002685 -0.001863 -0.002615 -0.001294 + -0.000350 0.003226 + + 5.1 1.97064 -0.684053 0.002076 -0.280023 0.005667 0.109606 0.014276 0.044058 0.855193 0.046351 -0.006466 -0.026507 + 0.003607 -0.003392 -0.101419 -0.001330 -0.000125 0.006486 0.007778 0.009506 -0.008455 -0.014727 + 0.005110 0.002159 0.023812 -0.017275 -0.037697 0.008354 0.007679 0.015135 -0.000853 -0.022144 + 0.005083 0.007098 -0.000444 0.001198 0.000113 -0.005788 -0.000697 0.007115 0.002118 0.004257 + -0.002715 -0.000505 -0.002279 0.002138 0.001113 0.005920 0.268755 -0.044398 -0.095995 -0.001936 + -0.007382 0.004194 -0.002101 -0.010270 0.021911 -0.001573 0.003896 0.011235 0.003481 0.004373 + -0.000828 -0.002127 -0.001539 0.001992 0.002608 -0.003490 -0.001131 -0.007314 -0.000472 0.245423 + -0.036136 -0.056248 0.000710 0.002238 0.003894 0.007289 0.002597 0.022609 0.013029 0.001279 + 0.008662 0.006072 -0.000223 0.000868 -0.005287 0.000386 0.002058 -0.000336 0.008126 -0.003996 + 0.002135 -0.000329 + + 6.1 0.02279 0.756926 -0.033150 -0.451715 -0.051692 -0.316320 -0.152207 0.241467 -0.360043 1.320243 0.046711 -0.007336 + -0.074161 0.057920 -0.008756 -0.178293 0.025789 -0.000569 -0.000316 0.021240 0.004886 0.035839 + -0.002954 0.010001 0.043725 -0.006765 0.060922 0.012810 -0.012729 0.013492 -0.038494 0.079915 + 0.003210 -0.036122 -0.001109 -0.000422 -0.005667 0.007256 -0.003800 0.010442 -0.006604 -0.011790 + -0.006632 -0.002961 -0.005837 -0.010132 -0.003216 0.027804 -0.249102 -0.073037 -0.062036 -0.017264 + -0.002456 -0.003227 -0.003811 0.050086 0.026959 -0.032195 0.051518 0.003095 0.002657 -0.002668 + -0.000341 -0.002570 -0.001093 0.001731 -0.024293 -0.001843 -0.014776 -0.004300 0.000540 1.175268 + 0.383207 0.094747 0.035474 0.002667 0.011252 -0.022959 0.082311 -0.081370 0.127110 0.053432 + -0.066748 0.068089 0.004332 0.007963 0.007847 0.001126 -0.001629 -0.001106 -0.019906 -0.015770 + -0.013512 0.013661 + + 7.1 0.02166 0.714200 -0.054399 -0.777112 -0.100052 -0.261354 -0.134809 -1.153913 -0.433183 -0.051521 0.060912 0.003693 + -0.045200 0.260213 0.053453 -0.050756 -0.010334 -0.015403 -0.023382 -0.040261 0.005744 0.013461 + -0.003094 0.004798 -0.073364 -0.015492 0.017712 -0.039403 -0.029622 -0.026598 0.004060 0.010400 + -0.027005 -0.040328 -0.010507 -0.000270 0.002294 -0.007315 -0.007744 -0.003838 -0.002219 -0.013094 + -0.003578 0.002463 -0.008327 -0.018672 0.004444 0.010131 1.251350 0.332566 -0.072548 0.020640 + 0.023829 0.009999 -0.001698 -0.130503 -0.083613 -0.099704 -0.072119 -0.035323 -0.041265 -0.010981 + -0.002338 -0.003035 -0.008294 -0.002773 0.006260 0.011398 -0.001357 0.021804 0.021626 0.196954 + 0.026126 -0.063168 -0.001206 0.003682 0.001544 -0.005519 0.054516 0.015135 -0.009360 0.017717 + 0.006477 -0.014338 0.005114 0.005256 0.004363 0.000142 0.001658 0.018034 0.010337 0.010726 + -0.005282 0.008700 + + 1 1s 1 1s 1 1s 1 1s 1 1s 1 2px 1 2py 1 2pz 1 2px 1 2py + 1 2pz 1 2px 1 2py 1 2pz 1 2px 1 2py 1 2pz 1 3d1+ 1 3d1- 1 3d0 + 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 1 3d2- 1 3d2+ 1 3d1+ 1 3d1- 1 3d0 + 1 3d2- 1 3d2+ 1 4f1+ 1 4f1- 1 4f3+ 1 4f3- 1 4f0 1 4f2- 1 4f2+ 1 4f1+ + 1 4f1- 1 4f3+ 1 4f3- 1 4f0 1 4f2- 1 4f2+ 2 1s 2 1s 2 1s 2 1s + 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 2px 2 2py 2 2pz 2 3d1+ + 2 3d1- 2 3d0 2 3d2- 2 3d2+ 2 3d1+ 2 3d1- 2 3d0 2 3d2- 2 3d2+ 3 1s + 3 1s 3 1s 3 1s 3 2px 3 2py 3 2pz 3 2px 3 2py 3 2pz 3 2px + 3 2py 3 2pz 3 3d1+ 3 3d1- 3 3d0 3 3d2- 3 3d2+ 3 3d1+ 3 3d1- 3 3d0 + 3 3d2- 3 3d2+ + + 1.2 2.00000 -15.519225 0.998154 -0.035978 0.002301 -0.019546 -0.013875 -0.011390 -0.020857 0.019231 0.004898 0.003286 + -0.002871 0.008092 0.003039 -0.002226 0.002765 -0.000338 0.001541 0.000146 -0.000006 0.000051 + 0.000142 -0.000060 0.000258 -0.000873 0.000963 0.000522 -0.001643 0.000987 -0.000413 0.000596 + 0.000237 -0.000919 0.000081 0.000236 -0.000079 -0.000046 0.000199 0.000113 0.000072 -0.000671 + -0.000399 0.000854 -0.000147 -0.000326 -0.000520 -0.000569 -0.004654 0.005641 0.005379 -0.000093 + 0.000147 -0.000031 0.000631 -0.000260 -0.000998 0.000098 -0.000273 -0.000668 0.000393 -0.000268 + -0.000092 -0.000477 0.000015 0.000046 -0.000066 0.000229 -0.000063 0.000021 -0.000220 -0.008043 + 0.004951 0.004045 -0.000386 0.000087 -0.000630 0.000035 -0.000615 -0.000291 0.000537 -0.000077 + -0.000190 0.000119 0.000032 -0.000111 0.000242 0.000302 0.000421 -0.000080 0.000035 0.000121 + -0.000016 0.000052 + + 2.2 1.99755 -0.714512 -0.042589 -0.750671 0.005849 -0.223209 -0.216768 -0.185343 -0.404578 0.367437 0.007161 0.014753 + -0.010461 0.056665 0.009051 0.032816 0.030559 -0.013126 0.029164 0.001878 -0.004651 -0.000742 + 0.006543 0.001705 0.004531 -0.012651 0.002344 0.020413 -0.000615 -0.003336 -0.006897 0.009775 + 0.004038 -0.008186 -0.000032 0.000794 0.001589 -0.002369 0.000543 -0.002308 -0.000031 -0.000077 + -0.001676 0.003982 -0.002524 -0.001018 -0.002771 -0.001189 -0.103503 0.087529 0.151011 0.007170 + 0.001039 -0.002974 0.008241 -0.004846 -0.014376 0.004531 -0.006518 -0.013666 -0.002356 -0.000349 + 0.001430 -0.001789 0.000734 -0.000652 0.000654 0.002392 -0.002718 0.000945 0.000430 -0.185348 + 0.093907 0.096311 -0.005215 -0.000369 -0.008183 0.003228 -0.010710 -0.001360 0.015769 -0.004168 + -0.001128 0.008046 -0.001014 0.001414 0.001177 0.000086 0.002071 0.000189 0.003023 0.000877 + -0.000869 0.001449 + + 3.2 1.97980 -0.780075 0.003923 -0.336311 0.002239 0.146419 0.088681 -0.176228 0.644778 -0.052257 0.012394 -0.028024 + -0.007988 0.013445 -0.079105 -0.021064 -0.018408 0.006436 -0.013847 -0.000162 -0.000577 0.003051 + 0.001237 0.009712 -0.004227 0.002140 0.004768 -0.007683 0.016940 0.000650 0.008781 -0.003707 + -0.002718 0.005749 -0.000603 -0.002099 0.000258 0.003574 -0.001727 -0.000174 -0.001715 -0.000425 + -0.000758 -0.000453 0.001158 0.000945 -0.000753 0.001020 -0.062242 0.020572 -0.001110 -0.000325 + -0.000876 0.005594 -0.000088 -0.001257 0.015844 -0.008124 0.002661 0.011041 -0.004077 0.000869 + -0.001397 0.001484 -0.000661 0.000723 0.001945 -0.002057 0.005138 -0.001036 0.001782 -0.722313 + 0.109528 0.246764 0.006493 0.009715 -0.014208 -0.006985 0.013646 -0.013854 -0.012846 -0.007133 + 0.017567 0.003381 0.001658 -0.002977 0.002338 0.004531 0.001753 -0.001967 0.001644 -0.002800 + -0.003072 -0.002900 + + 4.2 1.97674 -0.617096 -0.003526 0.220084 -0.001692 -0.116646 -0.148595 0.057073 0.116528 0.699764 -0.004869 -0.016226 + -0.031661 -0.010290 -0.050285 -0.034708 0.026172 -0.006062 0.023185 0.010033 0.001770 0.012381 + 0.002344 0.001049 0.019266 0.001530 0.022218 0.002686 0.002455 -0.003255 -0.004709 0.005484 + 0.002685 -0.002948 0.001698 0.002659 -0.000831 0.000210 0.001107 -0.000522 -0.000436 0.002864 + -0.000468 0.001840 -0.001982 0.003308 -0.001341 -0.000921 0.843482 -0.117107 -0.198349 -0.001226 + -0.007407 -0.006871 -0.015181 -0.008398 -0.008915 -0.011930 0.004124 -0.006438 0.018554 0.003957 + 0.003483 0.004386 0.001171 0.000201 -0.002821 -0.003107 -0.004168 -0.000919 0.000038 -0.200841 + 0.012514 0.047672 -0.003528 0.002433 -0.005117 0.004647 0.002841 -0.012838 0.014714 -0.003324 + -0.007164 0.007398 -0.000404 0.000678 0.002248 0.002223 0.001918 0.000475 0.002529 0.003275 + 0.000829 0.002369 + + 5.2 0.03136 0.642425 -0.052890 -0.987157 -0.074595 -0.597169 -0.429606 1.290001 0.298974 -0.324719 0.070540 -0.021129 + 0.027385 0.124835 -0.029262 0.018259 0.110335 0.006419 0.003459 0.015913 0.008165 0.003273 + -0.011135 -0.008802 0.033591 0.012416 0.071599 -0.028723 -0.129888 0.018268 -0.006545 0.041478 + -0.008671 -0.090122 -0.012299 -0.001508 0.014776 0.004358 0.000055 0.001256 -0.000895 -0.026926 + -0.003838 0.032550 0.009190 0.013201 -0.006548 -0.020968 0.343708 0.067445 -0.077016 -0.015643 + 0.005627 -0.000784 0.001075 0.002888 -0.025330 -0.016511 0.008409 -0.009143 0.014330 -0.005000 + 0.000814 -0.002115 0.000213 0.001670 -0.012054 0.000271 -0.005588 -0.002391 -0.008928 0.186556 + 0.021448 -0.119066 -0.018075 0.004299 0.000662 0.001351 -0.003503 -0.000589 0.017708 0.020031 + -0.022199 -0.006701 -0.000125 0.000715 0.000764 0.003902 0.001531 0.002280 -0.001539 0.011054 + 0.005357 0.003840 + + 6.2 0.02279 0.766781 -0.023336 -0.268374 -0.033121 -0.219593 -0.361000 -0.576502 -0.214718 -1.299604 -0.028842 -0.050158 + 0.073801 -0.014973 -0.065730 0.206885 0.054079 -0.018214 0.011657 -0.003095 0.007544 -0.041080 + 0.003732 0.003262 0.013582 -0.021344 -0.092964 -0.000346 0.029942 0.038794 -0.028269 -0.069668 + -0.004511 0.028209 -0.004964 -0.006774 -0.005550 -0.000042 -0.010028 -0.000021 0.002273 0.012771 + -0.009549 -0.005276 -0.010116 0.006637 -0.008883 -0.022357 1.160582 0.364204 0.148395 0.026880 + 0.008044 -0.000781 0.025770 -0.069933 -0.090053 -0.116572 -0.077949 -0.066788 -0.076691 -0.005852 + -0.002660 -0.010515 -0.000930 0.000224 0.018212 0.019287 0.013994 0.012214 -0.007006 -0.143799 + -0.030532 -0.012609 -0.016678 -0.003186 0.000755 0.003537 0.002249 -0.035901 0.033774 -0.017418 + -0.027241 -0.002720 -0.000148 0.001141 0.003573 0.000350 0.001560 0.003978 0.004454 0.016973 + 0.007935 0.011161 + + 7.2 0.02081 0.756045 0.040224 0.545760 0.072609 0.363329 0.342032 0.649427 -1.179228 -0.113974 0.006056 0.068530 + -0.039969 -0.162003 0.250779 -0.031279 -0.052303 -0.018823 -0.048847 0.005236 -0.007545 -0.015867 + -0.011134 -0.038125 -0.021737 0.018420 -0.033577 -0.062622 -0.076483 -0.031508 0.031008 -0.037269 + -0.050637 -0.028691 -0.006649 0.004738 -0.010008 0.008842 0.003819 0.002616 0.004933 -0.005635 + 0.007837 0.000159 0.017643 0.002710 0.001761 0.016733 -0.049703 0.020667 0.041486 0.012433 + -0.000418 0.004028 -0.002630 -0.009476 0.046717 -0.023918 0.027228 0.017737 -0.021742 0.002165 + -0.001757 0.005195 0.000405 0.001190 0.011127 -0.009433 0.020522 -0.000496 0.009476 -1.294391 + -0.365590 0.036256 -0.018040 -0.009148 0.022224 -0.004088 0.112693 -0.135685 -0.100733 0.046270 + -0.085638 -0.032792 -0.000595 0.001368 -0.008513 -0.008323 -0.006441 0.011592 -0.020405 0.004116 + 0.033747 0.009462 + + + Natural orbital dump at molpro section 2140.2 (Orbital set 2) + + + CI vector + ========= + + 222200 222000 0.9705156 + 222000 222200 -0.0837712 + + TOTAL ENERGIES -111.36172907 + + + + ********************************************************************************************************************************** + DATASETS * FILE NREC LENGTH (MB) RECORD NAMES + 1 20 358.60 500 610 700 900 950 970 1000 129 960 1100 + VAR BASINP GEOM SYMINP ZMAT AOBASIS BASIS P2S ABASIS S + 1400 1410 1200 1210 1080 1600 1650 1300 1700 1380 + T V H0 H01 AOSYM SMH MOLCAS ERIS OPER JKOP + + 2 5 6.44 700 1000 520 2100 2140 + GEOM BASIS MCVARS RHF MCSCF + + PROGRAMS * TOTAL MULTI HF INT + CPU TIMES * 75.29 62.81 4.75 7.47 + REAL TIME * 106.70 SEC + DISK USED * 1.30 GB + ********************************************************************************************************************************** + + + PROGRAM * CI (Multireference internally contracted CI) Authors: H.-J. Werner, P.J. Knowles, 1987 + + + Convergence thresholds: THRVAR = 1.00D-08 THRDEN = 1.00D-06 + + Number of optimized states: 1 Roots: 1 + Number of reference states: 1 Roots: 1 + + Reference symmetry: 1 Singlet + Number of electrons: 18 + Maximum number of shells: 8 + Maximum number of spin couplings: 429 + + Reference space: 29202 conf 85092 CSFs + N elec internal: 58278 conf 169884 CSFs + N-1 el internal: 69576 conf 339768 CSFs + N-2 el internal: 73789 conf 608751 CSFs + + Number of electrons in valence space: 14 + Maximum number of open shell orbitals in reference space: 10 + Maximum number of open shell orbitals in internal spaces: 14 + + + Number of core orbitals: 2 ( 1 1 ) + Number of active orbitals: 12 ( 6 6 ) + Number of external orbitals: 170 ( 85 85 ) + + Molecular orbitals read from record 2140.2 Type=MCSCF/NATURAL (state 1.1) + + Coulomb and exchange operators available. No transformation done. + + Number of p-space configurations: 1 + + Reference wavefunction optimized for reference space (refopt=1) + + State Reference Energy + 1 -111.36172907 + + Number of blocks in overlap matrix: 4 Smallest eigenvalue: 0.20D-02 + Number of N-2 electron functions: 144 + Number of N-1 electron functions: 339768 + + Number of internal configurations: 85092 + Number of singly external configurations: 28880280 + Number of doubly external configurations: 1041420 + Total number of contracted configurations: 30006792 + Total number of uncontracted configurations: 4420599512 + + Diagonal Coupling coefficients finished. Storage:37824290 words, CPU-Time: 182.45 seconds. + Energy denominators for pairs finished in 1 passes. Storage: 4651302 words, CPU-time: 0.04 seconds. + + ITER. STATE ROOT SQ.NORM CORR.ENERGY TOTAL ENERGY ENERGY CHANGE DEN1 VAR(S) VAR(P) TIME + 1 1 1 1.00000000 0.00000000 -111.36172907 0.00000000 -0.29420594 0.32D-01 0.33D-01 229.56 + 2 1 1 1.07049611 -0.30548326 -111.66721233 -0.30548326 -0.01158808 0.15D-02 0.12D-02 1372.57 + 3 1 1 1.07613553 -0.31756184 -111.67929091 -0.01207858 -0.00094616 0.14D-03 0.89D-04 2517.64 + 4 1 1 1.07900883 -0.31860896 -111.68033803 -0.00104712 -0.00011548 0.22D-04 0.91D-05 3693.41 + 5 1 1 1.07980819 -0.31873337 -111.68046243 -0.00012441 -0.00001513 0.31D-05 0.11D-05 4847.23 + 6 1 1 1.07992689 -0.31875018 -111.68047924 -0.00001681 -0.00000245 0.53D-06 0.15D-06 6018.74 + 7 1 1 1.07994376 -0.31875288 -111.68048194 -0.00000270 -0.00000044 0.98D-07 0.25D-07 7162.92 + 8 1 1 1.07996071 -0.31875335 -111.68048242 -0.00000048 -0.00000009 0.19D-07 0.50D-08 8346.49 + 9 1 1 1.07997061 -0.31875345 -111.68048252 -0.00000010 -0.00000002 0.36D-08 0.92D-09 9599.42 + + + ===================================== + Analysis of CPU times by interactions + ===================================== + + I S P + + I 0.5% + S 0.9% 9.1% + P 2.7% 74.5% 9.8% + + Initialization: 2.1% + Other: 0.4% + + Total CPU: 9599.4 seconds + ===================================== + + + + Reference coefficients greater than 0.0500000 + ============================================= + 222200222000 0.9373617 + 222000222200 -0.0755253 + 22/2/02\200\ 0.0545580 + + + + RESULTS FOR STATE 1.1 + ===================== + + Coefficient of reference function: C(0) = 0.96195400 (fixed) 0.96226354 (relaxed) + + Energy contributions of configuration classes + + CLASS SQ.NORM ECORR1 ECORR2 + +++++++++++++++++++++++++++++++++++++++++++++++++++ + Internals 0.00064368 -0.00000001 -0.00018997 + Singles 0.03419495 -0.10821557 -0.11022440 + Pairs 0.04582714 -0.21053776 -0.20833908 + Total 1.08066576 -0.31875334 -0.31875345 + +++++++++++++++++++++++++++++++++++++++++++++++++++ + + + Reference energy -111.36172907 + Nuclear energy 41.78471756 + Kinetic energy 111.62870721 + One electron energy -233.37114277 + Two electron energy 79.90594269 + Virial quotient -1.00046382 + Correlation energy -0.31875345 + !MRCI STATE 1.1 Energy -111.680482516555 + + Properties without orbital relaxation: + + !MRCI STATE 1.1 Dipole moment 0.00000000 0.00000000 0.73462279 + Dipole moment /Debye 0.00000000 0.00000000 1.86710260 + + Cluster corrected energies -111.70384836 (Pople, fixed reference) + Cluster corrected energies -111.70363518 (Pople, relaxed reference) + + + + ********************************************************************************************************************************** + DATASETS * FILE NREC LENGTH (MB) RECORD NAMES + 1 20 358.60 500 610 700 900 950 970 1000 129 960 1100 + VAR BASINP GEOM SYMINP ZMAT AOBASIS BASIS P2S ABASIS S + 1400 1410 1200 1210 1080 1600 1650 1300 1700 1380 + T V H0 H01 AOSYM SMH MOLCAS ERIS OPER JKOP + + 2 5 6.44 700 1000 520 2100 2140 + GEOM BASIS MCVARS RHF MCSCF + + PROGRAMS * TOTAL MRCI MULTI HF INT + CPU TIMES * 9759.63 9684.34 62.81 4.75 7.47 + REAL TIME * 10219.52 SEC + DISK USED * 5.19 GB + ********************************************************************************************************************************** + + + MRCI/aug-cc-pVTZ energy= -111.680482516555 + + MRCI MULTI HF-SCF + -111.68048252 -111.36172907 -111.22812175 + ********************************************************************************************************************************** + Molpro calculation terminated + Variable memory released diff --git a/rmgpy/cantherm/data/npropyl.out b/arkane/data/npropyl.out similarity index 100% rename from rmgpy/cantherm/data/npropyl.out rename to arkane/data/npropyl.out diff --git a/rmgpy/cantherm/data/oxygen.log b/arkane/data/oxygen.log similarity index 100% rename from rmgpy/cantherm/data/oxygen.log rename to arkane/data/oxygen.log diff --git a/arkane/explorer.py b/arkane/explorer.py new file mode 100644 index 0000000000..1a3ab13d6c --- /dev/null +++ b/arkane/explorer.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2018 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +import os +import numpy as np +import logging +import shutil +from copy import deepcopy + +import rmgpy +from rmgpy.rmg.main import RMG +from rmgpy.rmg.model import CoreEdgeReactionModel +from rmgpy.data.rmg import getDB +from rmgpy.exceptions import InputError + +################################################################################ + + +class ExplorerJob(object): + def __init__(self, source, pdepjob, explore_tol, energy_tol=np.inf, flux_tol=0.0, + bathGas=None, maximumRadicalElectrons=np.inf): + self.source = source + self.explore_tol = explore_tol + self.energy_tol = energy_tol + self.flux_tol = flux_tol + self.maximumRadicalElectrons = maximumRadicalElectrons + + self.pdepjob = pdepjob + + if not hasattr(self.pdepjob,'outputFile'): + self.pdepjob.outputFile = None + + if bathGas: + self.bathGas = bathGas + elif self.pdepjob.network and self.pdepjob.network.bathGas: + self.bathGas = self.pdepjob.network.bathGas + else: + raise InputError('bathGas not specified in explorer block') + + def copy(self): + """ + Return a copy of the explorer job. + """ + return ExplorerJob( + source=deepcopy(self.source), + pdepjob=self.pdepjob, + explore_tol=self.explore_tol, + energy_tol=self.energy_tol, + flux_tol=self.flux_tol + ) + + def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesList=None, thermoLibrary=None, kineticsLibrary=None): + + logging.info('Exploring network...') + + rmg = RMG() + + rmg.speciesConstraints = {'allowed' : ['input species', 'seed mechanisms', 'reaction libraries'], 'maximumRadicalElectrons' : self.maximumRadicalElectrons, 'explicitlyAllowedMolecules': []} + + rmgpy.rmg.input.rmg = rmg + + reaction_model = CoreEdgeReactionModel() + + reaction_model.pressureDependence = self.pdepjob + + reaction_model.pressureDependence.rmgmode = True + + if outputFile: + reaction_model.pressureDependence.outputFile = os.path.dirname(outputFile) + + kineticsDatabase = getDB('kinetics') + thermoDatabase = getDB('thermo') + + thermoDatabase.libraries['thermojobs'] = thermoLibrary + thermoDatabase.libraryOrder.insert(0,'thermojobs') + + kineticsDatabase.libraries['kineticsjobs'] = kineticsLibrary + kineticsDatabase.libraryOrder.insert(0,('kineticsjobs','Reaction Library')) + + jobRxns = [rxn for rxn in reaction_model.core.reactions] + + self.jobRxns = jobRxns + + if outputFile is not None: + if not os.path.exists(os.path.join(reaction_model.pressureDependence.outputFile,'pdep')): + os.mkdir(os.path.join(reaction_model.pressureDependence.outputFile,'pdep')) + else: + shutil.rmtree(os.path.join(reaction_model.pressureDependence.outputFile,'pdep')) + os.mkdir(os.path.join(reaction_model.pressureDependence.outputFile,'pdep')) + + # get the molecular formula for the network + mmol = None + for spc in self.source: + if mmol: + mmol.merge(spc.molecule[0]) + else: + mmol = spc.molecule[0] + + form = mmol.getFormula() + + for spec in self.bathGas.keys()+self.source: + nspec,isNew = reaction_model.makeNewSpecies(spec,reactive=False) + flags = np.array([s.molecule[0].getFormula()==form for s in reaction_model.core.species]) + reaction_model.enlarge(nspec,reactEdge=False,unimolecularReact=flags, + bimolecularReact=np.zeros((len(reaction_model.core.species),len(reaction_model.core.species)))) + + reaction_model.addSeedMechanismToCore('kineticsjobs') + + for lib in kineticsDatabase.libraryOrder: + if lib[0] != 'kineticsjobs': + reaction_model.addReactionLibraryToEdge(lib[0]) + + for spc in reaction_model.core.species: + for i,item in enumerate(self.source): + if spc.isIsomorphic(item): + self.source[i] = spc + + # react initial species + flags = np.array([s.molecule[0].getFormula()==form for s in reaction_model.core.species]) + reaction_model.enlarge(reactEdge=True,unimolecularReact=flags, + bimolecularReact=np.zeros((len(reaction_model.core.species),len(reaction_model.core.species)))) + + # find the network we're interested in + for nwk in reaction_model.networkList: + if set(nwk.source) == set(self.source): + self.source = nwk.source + network = nwk + break + else: + raise ValueError('Did not generate a network with the requested source. This usually means no unimolecular' + 'reactions were generated for the source. Note that library reactions that are not' + ' properly flagged as elementary_high_p can replace RMG generated reactions that would' + ' otherwise be part of networks.') + + network.bathGas = self.bathGas + + self.network = network + + # determine T and P combinations + + if self.pdepjob.Tlist: + Tlist = self.pdepjob.Tlist.value_si + else: + Tlist = np.linspace(self.pdepjob.Tmin.value_si,self.pdepjob.Tmax.value_si,self.pdepjob.Tcount) + + if self.pdepjob.Plist: + Plist = self.pdepjob.Plist.value_si + else: + Plist = np.linspace(self.pdepjob.Pmin.value_si,self.pdepjob.Pmax.value_si,self.pdepjob.Pcount) + + # generate the network + + forbiddenStructures = getDB('forbidden') + incomplete = True + + while incomplete: + incomplete = False + for T in Tlist: + for P in Plist: + if network.getLeakCoefficient(T=T,P=P) > self.explore_tol: + incomplete = True + spc = network.getMaximumLeakSpecies(T=T,P=P) + if forbiddenStructures.isMoleculeForbidden(spc.molecule[0]): + reaction_model.removeSpeciesFromEdge(reaction_model.reactionSystems,spc) + reaction_model.removeEmptyPdepNetworks() + logging.error(spc.label) + else: + logging.info('adding new isomer {0} to network'.format(spc)) + flags = np.array([s.molecule[0].getFormula()==form for s in reaction_model.core.species]) + reaction_model.enlarge((network,spc),reactEdge=False,unimolecularReact=flags, + bimolecularReact=np.zeros((len(reaction_model.core.species),len(reaction_model.core.species)))) + + flags = np.array([s.molecule[0].getFormula()==form for s in reaction_model.core.species]) + reaction_model.enlarge(reactEdge=True,unimolecularReact=flags, + bimolecularReact=np.zeros((len(reaction_model.core.species),len(reaction_model.core.species)))) + + rmRxns = [] + for rxn in network.pathReactions: # remove reactions with forbidden species + for r in rxn.reactants+rxn.products: + if forbiddenStructures.isMoleculeForbidden(r.molecule[0]): + rmRxns.append(rxn) + + for rxn in rmRxns: + logging.info('Removing forbidden reaction: {0}'.format(rxn)) + network.pathReactions.remove(rxn) + + # clean up output files + if outputFile is not None: + path = os.path.join(reaction_model.pressureDependence.outputFile,'pdep') + for name in os.listdir(path): + if name.endswith('.py') and '_' in name: + if name.split('_')[-1].split('.')[0] != str(len(network.isomers)): + os.remove(os.path.join(path,name)) + else: + os.rename(os.path.join(path,name),os.path.join(path,'network_full.py')) + + warns = [] + + for rxn in jobRxns: + if rxn not in network.pathReactions: + warns.append('Reaction {0} in the input file was not explored during network expansion and was not included in the full network. This is likely because your explore_tol value is too high.'.format(rxn)) + + # reduction process + + if self.energy_tol != np.inf or self.flux_tol != 0.0: + + rxnSet = None + + for T in Tlist: + if self.energy_tol != np.inf: + rxns = network.get_energy_filtered_reactions(T,self.energy_tol) + if rxnSet is not None: + rxnSet &= set(rxns) + else: + rxnSet = set(rxns) + + for P in Plist: + if self.flux_tol != 0.0: + rxns = network.get_rate_filtered_reactions(T,P,self.flux_tol) + if rxnSet is not None: + rxnSet &= set(rxns) + else: + rxnSet = set(rxns) + + logging.info('removing reactions during reduction:') + for rxn in rxnSet: + logging.info(rxn) + + network.remove_reactions(reaction_model,list(rxnSet)) + + for rxn in jobRxns: + if rxn not in network.pathReactions: + warns.append('Reaction {0} in the input file was not included in the reduced model.'.format(rxn)) + + self.network = network + + self.pdepjob.network = network + + self.pdepjob.execute(outputFile, plot, format='pdf', print_summary=True) + + if warns != []: + logging.info('\nOUTPUT WARNINGS:\n') + for w in warns: + logging.warning(w) diff --git a/arkane/explorerTest.py b/arkane/explorerTest.py new file mode 100644 index 0000000000..ca722566bb --- /dev/null +++ b/arkane/explorerTest.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2018 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +import unittest +import os +from nose.plugins.attrib import attr + +from arkane import Arkane +from arkane.explorer import ExplorerJob + +################################################################################ + + +@attr('functional') +class testExplorerJob(unittest.TestCase): + """ + Contains tests for ExplorerJob class execute method + """ + @classmethod + def setUpClass(cls): + + arkane = Arkane() + + cls.jobList = arkane.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)),'data','methoxy_explore.py')) + for job in cls.jobList: + if not isinstance(job,ExplorerJob): + job.execute(outputFile=None, plot=None) + else: + thermoLibrary,kineticsLibrary,speciesList = arkane.getLibraries() + job.execute(outputFile=None, plot=None, speciesList=speciesList, thermoLibrary=thermoLibrary, kineticsLibrary=kineticsLibrary) + + cls.thermoLibrary = thermoLibrary + cls.kineticsLibrary = kineticsLibrary + cls.explorerjob = cls.jobList[-1] + cls.pdepjob = cls.jobList[-2] + + @classmethod + def tearDownClass(cls): + """A function that is run ONCE after all unit tests in this class.""" + # Reset module level database + import rmgpy.data.rmg + rmgpy.data.rmg.database.kinetics = None + + def test_reactions(self): + """ + test that the right number of reactions are in output network + """ + self.assertEqual(len(self.explorerjob.network.pathReactions),6) + + def test_isomers(self): + """ + test that the right number of isomers are in the output network + """ + self.assertEqual(len(self.explorerjob.network.isomers),2) + + def test_job_rxns(self): + """ + test that in this case all the reactions in the job + ended up in the final network + """ + for rxn in self.explorerjob.jobRxns: + self.assertIn(rxn,self.explorerjob.network.pathReactions) + + +if __name__ == '__main__': + unittest.main(testRunner=unittest.TextTestRunner(verbosity=2)) diff --git a/rmgpy/cantherm/gaussian.py b/arkane/gaussian.py similarity index 93% rename from rmgpy/cantherm/gaussian.py rename to arkane/gaussian.py index 1956aed3a5..113a015085 100644 --- a/rmgpy/cantherm/gaussian.py +++ b/arkane/gaussian.py @@ -32,17 +32,21 @@ import numpy import logging import os.path -from rmgpy.cantherm.common import checkConformerEnergy + import rmgpy.constants as constants from rmgpy.statmech import IdealGasTranslation, NonlinearRotor, LinearRotor, HarmonicOscillator, Conformer +from rmgpy.exceptions import InputError + +from arkane.common import check_conformer_energy, get_element_mass ################################################################################ + class GaussianLog: """ Represent a log file from Gaussian. The attribute `path` refers to the location on disk of the Gaussian log file of interest. Methods are provided - to extract a variety of information into CanTherm classes and/or NumPy + to extract a variety of information into Arkane classes and/or NumPy arrays. """ @@ -118,14 +122,14 @@ def loadGeometry(self): last is returned. """ - number = []; coord = [] + number, coord, mass = [], [], [] f = open(self.path, 'r') line = f.readline() while line != '': # Automatically determine the number of atoms if 'Input orientation:' in line: - number = []; coord = [] + number, coord = [], [] for i in range(5): line = f.readline() while '---------------------------------------------------------------------' not in line: data = line.split() @@ -136,31 +140,16 @@ def loadGeometry(self): # Close file when finished f.close() + # Assign appropriate mass to each atom in the molecule + mass = [] + for num in number: + mass1, _ = get_element_mass(num) + mass.append(mass1) coord = numpy.array(coord, numpy.float64) number = numpy.array(number, numpy.int) - mass = numpy.zeros(len(number), numpy.float64) - # Use the atomic mass of the most common isotope rather than the - # average atomic mass - # These values were taken from "Atomic Weights and Isotopic Compositions" v3.0 (July 2010) from NIST - for i in range(len(number)): - if number[i] == 1: - mass[i] = 1.00782503207 - elif number[i] == 6: - mass[i] = 12.0 - elif number[i] == 7: - mass[i] = 14.0030740048 - elif number[i] == 8: - mass[i] = 15.99491461956 - elif number[i] == 15: - mass[i] = 30.97376163 - elif number[i] == 16: - mass[i] = 31.97207100 - elif number[i] == 17: - mass[i] = 35.4527 - elif number[i] == 53: - mass[i] = 126.90447 - else: - raise NotImplementedError('Atomic number {0:d} not yet supported in loadGeometry().'.format(number[i])) + mass = numpy.array(mass, numpy.float64) + if len(number) == 0 or len(coord) == 0 or len(mass) == 0: + raise InputError('Unable to read atoms from Gaussian geometry output file {0}'.format(self.path)) return coord, number, mass @@ -176,6 +165,7 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym """ modes = [] + unscaled_frequencies = [] E0 = 0.0 f = open(self.path, 'r') @@ -235,6 +225,7 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym # Convert from K to cm^-1 if len(frequencies) > 0: frequencies = [freq * 0.695039 for freq in frequencies] # kB = 0.695039 cm^-1/K + unscaled_frequencies = frequencies vibration = HarmonicOscillator(frequencies=(frequencies,"cm^-1")) modes.append(vibration) @@ -258,7 +249,8 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym # Close file when finished f.close() - return Conformer(E0=(E0*0.001,"kJ/mol"), modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers) + return Conformer(E0=(E0*0.001,"kJ/mol"), modes=modes, spinMultiplicity=spinMultiplicity, + opticalIsomers=opticalIsomers), unscaled_frequencies def loadEnergy(self,frequencyScaleFactor=1.): """ @@ -387,7 +379,7 @@ def loadScanEnergies(self): Vlist = numpy.array(Vlist, numpy.float64) # check to see if the scanlog indicates that a one of your reacting species may not be the lowest energy conformer - checkConformerEnergy(Vlist, self.path) + check_conformer_energy(Vlist, self.path) # Adjust energies to be relative to minimum energy conformer # Also convert units from Hartree/particle to kJ/mol diff --git a/rmgpy/cantherm/gaussianTest.py b/arkane/gaussianTest.py similarity index 96% rename from rmgpy/cantherm/gaussianTest.py rename to arkane/gaussianTest.py index 7ae218f456..cf33f07dcb 100644 --- a/rmgpy/cantherm/gaussianTest.py +++ b/arkane/gaussianTest.py @@ -32,12 +32,15 @@ import unittest import os -from rmgpy.cantherm.gaussian import GaussianLog from rmgpy.statmech import IdealGasTranslation, LinearRotor, NonlinearRotor, HarmonicOscillator, HinderedRotor import rmgpy.constants as constants from external.wip import work_in_progress + +from arkane.gaussian import GaussianLog + ################################################################################ + class GaussianTest(unittest.TestCase): """ Contains unit tests for the chempy.io.gaussian module, used for reading @@ -51,7 +54,7 @@ def testLoadEthyleneFromGaussianLog_CBSQB3(self): """ log = GaussianLog(os.path.join(os.path.dirname(__file__),'data','ethylene.log')) - conformer = log.loadConformer(symfromlog=True) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) E0 = log.loadEnergy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,IdealGasTranslation)]) == 1) @@ -78,7 +81,7 @@ def testLoadOxygenFromGaussianLog(self): """ log = GaussianLog(os.path.join(os.path.dirname(__file__),'data','oxygen.log')) - conformer = log.loadConformer(symfromlog=True) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) E0 = log.loadEnergy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,IdealGasTranslation)]) == 1) @@ -106,7 +109,7 @@ def testLoadEthyleneFromGaussianLog_G3(self): """ log = GaussianLog(os.path.join(os.path.dirname(__file__),'data','ethylene_G3.log')) - conformer = log.loadConformer(symfromlog=True) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) E0 = log.loadEnergy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,IdealGasTranslation)]) == 1) diff --git a/rmgpy/cantherm/input.py b/arkane/input.py similarity index 61% rename from rmgpy/cantherm/input.py rename to arkane/input.py index 9b94d995f0..3ffb802369 100644 --- a/rmgpy/cantherm/input.py +++ b/arkane/input.py @@ -29,13 +29,22 @@ ############################################################################### """ -This module contains functionality for parsing CanTherm input files. +This module contains functionality for parsing Arkane input files. """ import os.path import logging +import numpy as np + +from rmgpy import settings +from rmgpy.exceptions import InputError, DatabaseError +from rmgpy.data.rmg import RMGDatabase +from rmgpy.data.rmg import getDB + +from rmgpy.rmg.model import CoreEdgeReactionModel from rmgpy.species import Species, TransitionState +from rmgpy.quantity import Quantity from rmgpy.statmech.translation import Translation, IdealGasTranslation from rmgpy.statmech.rotation import Rotation, LinearRotor, NonlinearRotor, KRotor, SphericalTopRotor @@ -52,6 +61,7 @@ from rmgpy.kinetics.falloff import ThirdBody, Lindemann, Troe from rmgpy.kinetics.kineticsdata import KineticsData, PDepKineticsData from rmgpy.kinetics.tunneling import Wigner, Eckart +from rmgpy.kinetics.model import PDepKineticsModel, TunnelingModel from rmgpy.pdep.configuration import Configuration from rmgpy.pdep.network import Network @@ -61,10 +71,11 @@ from rmgpy.reaction import Reaction from rmgpy.transport import TransportData -from rmgpy.cantherm.kinetics import KineticsJob -from rmgpy.cantherm.statmech import StatMechJob, assign_frequency_scale_factor -from rmgpy.cantherm.thermo import ThermoJob -from rmgpy.cantherm.pdep import PressureDependenceJob +from arkane.kinetics import KineticsJob +from arkane.statmech import StatMechJob, assign_frequency_scale_factor +from arkane.thermo import ThermoJob +from arkane.pdep import PressureDependenceJob +from arkane.explorer import ExplorerJob ################################################################################ @@ -76,6 +87,67 @@ ################################################################################ + +def database( + thermoLibraries = None, + transportLibraries = None, + reactionLibraries = None, + frequenciesLibraries = None, + kineticsFamilies = 'default', + kineticsDepositories = 'default', + kineticsEstimator = 'rate rules', + ): + if isinstance(thermoLibraries, str): + thermoLibraries = [thermoLibraries] + if isinstance(transportLibraries, str): + transportLibraries = [transportLibraries] + if isinstance(reactionLibraries, str): + reactionLibraries = [reactionLibraries] + if isinstance(frequenciesLibraries, str): + frequenciesLibraries = [frequenciesLibraries] + + databaseDirectory = settings['database.directory'] + thermoLibraries = thermoLibraries or [] + transportLibraries = transportLibraries + reactionLibraries = reactionLibraries or [] + kineticsEstimator = kineticsEstimator + + if kineticsDepositories == 'default': + kineticsDepositories = ['training'] + elif kineticsDepositories == 'all': + kineticsDepositories = None + else: + if not isinstance(kineticsDepositories,list): + raise InputError("kineticsDepositories should be either 'default', 'all', or a list of names eg. ['training','PrIMe'].") + kineticsDepositories = kineticsDepositories + + if kineticsFamilies in ('default', 'all', 'none'): + kineticsFamilies = kineticsFamilies + else: + if not isinstance(kineticsFamilies,list): + raise InputError("kineticsFamilies should be either 'default', 'all', 'none', or a list of names eg. ['H_Abstraction','R_Recombination'] or ['!Intra_Disproportionation'].") + kineticsFamilies = kineticsFamilies + + database = getDB() or RMGDatabase() + + database.load( + path = databaseDirectory, + thermoLibraries = thermoLibraries, + transportLibraries = transportLibraries, + reactionLibraries = reactionLibraries, + seedMechanisms = [], + kineticsFamilies = kineticsFamilies, + kineticsDepositories = kineticsDepositories, + depository = False, # Don't bother loading the depository information, as we don't use it + ) + + for family in database.kinetics.families.values(): #load training + family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) + + for family in database.kinetics.families.values(): + family.fillKineticsRulesByAveragingUp(verbose=True) + + def species(label, *args, **kwargs): global speciesDict, jobList if label in speciesDict: @@ -84,12 +156,18 @@ def species(label, *args, **kwargs): spec = Species(label=label) speciesDict[label] = spec - + + path = None if len(args) == 1: # The argument is a path to a conformer input file path = args[0] job = StatMechJob(species=spec, path=path) + logging.debug('Added species {0} to a stat mech job.'.format(label)) jobList.append(job) + elif len(args) > 1: + raise InputError('species {0} can only have two non-keyword argument ' + 'which should be the species label and the ' + 'path to a quantum file.'.format(spec.label)) if len(kwargs) > 0: # The species parameters are given explicitly @@ -102,6 +180,7 @@ def species(label, *args, **kwargs): collisionModel = None energyTransferModel = None thermo = None + reactive = True for key, value in kwargs.items(): if key == 'structure': structure = value @@ -121,18 +200,53 @@ def species(label, *args, **kwargs): energyTransferModel = value elif key == 'thermo': thermo = value + elif key == 'reactive': + reactive = value else: raise TypeError('species() got an unexpected keyword argument {0!r}.'.format(key)) - if structure: spec.molecule = [structure] + if structure: + spec.molecule = [structure] spec.conformer = Conformer(E0=E0, modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers) spec.molecularWeight = molecularWeight spec.transportData = collisionModel spec.energyTransferModel = energyTransferModel spec.thermo = thermo + spec.reactive = reactive + if spec.reactive and path is None and spec.thermo is None and spec.conformer.E0 is None: + if not spec.molecule: + raise InputError('Neither thermo, E0, species file path, nor structure specified, cannot estimate' + ' thermo properties of species {0}'.format(spec.label)) + try: + db = getDB('thermo') + if db is None: + raise DatabaseError('Thermo database is None.') + except DatabaseError: + logging.warn("The database isn't loaded, cannot estimate thermo for {0}. " + "If it is a bath gas, set reactive = False to avoid generating thermo.".format(spec.label)) + else: + logging.info('No E0 or thermo found, estimating thermo and E0 of species {0} using' + ' RMG-Database...'.format(spec.label)) + spec.thermo = db.getThermoData(spec) + if spec.thermo.E0 is None: + th = spec.thermo.toWilhoit() + spec.conformer.E0 = th.E0 + spec.thermo.E0 = th.E0 + else: + spec.conformer.E0 = spec.thermo.E0 + + if spec.reactive and spec.thermo and not spec.hasStatMech() and structure is not None: + # generate stat mech info if it wasn't provided before + spec.generateStatMech() + + if not energyTransferModel: + # default to RMG's method of generating energyTransferModel + spec.generateEnergyTransferModel() + return spec + def transitionState(label, *args, **kwargs): global transitionStateDict if label in transitionStateDict: @@ -147,7 +261,7 @@ def transitionState(label, *args, **kwargs): job = StatMechJob(species=ts, path=path) jobList.append(job) - elif len(args) == 0 and len(kwargs) > 0: + elif len(args) == 0: # The species parameters are given explicitly E0 = None modes = [] @@ -170,10 +284,15 @@ def transitionState(label, *args, **kwargs): ts.conformer = Conformer(E0=E0, modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers) ts.frequency = frequency - + else: + if len(args) == 0 and len(kwargs) == 0: + raise InputError('The transitionState needs to reference a quantum job file or contain kinetic information.') + raise InputError('The transitionState can only link a quantum job or directly input information, not both.') + return ts -def reaction(label, reactants, products, transitionState, kinetics=None, tunneling=''): + +def reaction(label, reactants, products, transitionState=None, kinetics=None, tunneling=''): global reactionDict, speciesDict, transitionStateDict #label = 'reaction'+transitionState if label in reactionDict: @@ -183,20 +302,54 @@ def reaction(label, reactants, products, transitionState, kinetics=None, tunneli logging.info('Loading reaction {0}...'.format(label)) reactants = sorted([speciesDict[spec] for spec in reactants]) products = sorted([speciesDict[spec] for spec in products]) - transitionState = transitionStateDict[transitionState] + if transitionState: + transitionState = transitionStateDict[transitionState] if tunneling.lower() == 'wigner': transitionState.tunneling = Wigner(frequency=None) elif tunneling.lower() == 'eckart': transitionState.tunneling = Eckart(frequency=None, E0_reac=None, E0_TS=None, E0_prod=None) - elif tunneling == '' or tunneling is None: + elif transitionState and (tunneling == '' or tunneling is None): transitionState.tunneling = None - elif not isinstance(tunneling, TunnelingModel): + elif transitionState and not isinstance(tunneling, TunnelingModel): raise ValueError('Unknown tunneling model {0!r}.'.format(tunneling)) rxn = Reaction(label=label, reactants=reactants, products=products, transitionState=transitionState, kinetics=kinetics) - reactionDict[label] = rxn + + if rxn.transitionState is None and rxn.kinetics is None: + logging.info('estimating rate of reaction {0} using RMG-database') + if not all([m.molecule != [] for m in rxn.reactants+rxn.products]): + raise ValueError('chemical structures of reactants and products not available for RMG estimation of reaction {0}'.format(label)) + for spc in rxn.reactants+rxn.products: + print spc.label + print spc.molecule + db = getDB('kinetics') + rxns = db.generate_reactions_from_libraries(reactants=rxn.reactants,products=rxn.products) + rxns = [r for r in rxns if r.elementary_high_p] + + if rxns != []: + for r in rxns: + if isinstance(rxn.kinetics, PDepKineticsModel): + boo = rxn.generate_high_p_limit_kinetics() + if boo: + rxn = r + break + + if rxns == [] or not boo: + logging.info('No library reactions tagged with elementary_high_p found for reaction {0}, generating reactions from RMG families'.format(label)) + rxn = list(db.generate_reactions_from_families(reactants=rxn.reactants,products=rxn.products)) + model = CoreEdgeReactionModel() + model.verboseComments = True + for r in rxn: + model.applyKineticsToReaction(r) + + if isinstance(rxn,Reaction): + reactionDict[label] = rxn + else: + for i in xrange(len(rxn)): + reactionDict[label+str(i)] = rxn[i] return rxn + def network(label, isomers=None, reactants=None, products=None, pathReactions=None, bathGas=None): global networkDict, speciesDict, reactionDict logging.info('Loading network {0}...'.format(label)) @@ -213,8 +366,19 @@ def network(label, isomers=None, reactants=None, products=None, pathReactions=No reactants.append(sorted([speciesDict[spec] for spec in reactant])) if pathReactions is None: - # If not explicitly given, use all reactions in input file - pathReactions = reactionDict.values() + # Only add reactions that match reactants and/or isomers + pathReactions = [] + for rxn in reactionDict.values(): + if not rxn.isUnimolecular(): + # this reaction is not pressure dependent + continue + reactant_is_isomer = len(rxn.reactants) == 1 and rxn.reactants[0] in isomers + product_is_isomer = len(rxn.products) == 1 and rxn.products[0] in isomers + reactant_is_reactant = any([frozenset(rxn.reactants) == frozenset(reactant_pair) for reactant_pair in reactants]) + product_is_reactant = any([frozenset(rxn.products ) == frozenset(reactant_pair) for reactant_pair in reactants]) + if reactant_is_isomer or reactant_is_reactant or product_is_isomer or product_is_reactant: + pathReactions.append(rxn) + logging.debug('Path reactions {} were found for network {}'.format([rxn.label for rxn in pathReactions], label)) else: pathReactions0 = pathReactions; pathReactions = [] for rxn in pathReactions0: @@ -266,6 +430,7 @@ def network(label, isomers=None, reactants=None, products=None, pathReactions=No ) networkDict[label] = network + def kinetics(label, Tmin=None, Tmax=None, Tlist=None, Tcount=0, sensitivity_conditions=None): global jobList, reactionDict try: @@ -276,6 +441,7 @@ def kinetics(label, Tmin=None, Tmax=None, Tlist=None, Tcount=0, sensitivity_cond sensitivity_conditions=sensitivity_conditions) jobList.append(job) + def statmech(label): global jobList, speciesDict, transitionStateDict if label in speciesDict or label in transitionStateDict: @@ -287,6 +453,7 @@ def statmech(label): else: raise ValueError('Unknown species or transition state label {0!r} for statmech() job.'.format(label)) + def thermo(label, thermoClass): global jobList, speciesDict try: @@ -296,6 +463,7 @@ def thermo(label, thermoClass): job = ThermoJob(species=spec, thermoClass=thermoClass) jobList.append(job) + def pressureDependence(label, Tmin=None, Tmax=None, Tcount=0, Tlist=None, Pmin=None, Pmax=None, Pcount=0, Plist=None, @@ -304,9 +472,15 @@ def pressureDependence(label, activeKRotor=True, activeJRotor=True, rmgmode=False, sensitivity_conditions=None): global jobList, networkDict + if isinstance(interpolationModel, str): interpolationModel = (interpolationModel,) - job = PressureDependenceJob(network = networkDict[label], + + nwk = None + if label in networkDict.keys(): + nwk = networkDict[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, @@ -315,20 +489,68 @@ def pressureDependence(label, rmgmode=rmgmode, sensitivity_conditions=sensitivity_conditions) jobList.append(job) + +def explorer(source, explore_tol=(0.01,'s^-1'), energy_tol=np.inf, flux_tol=0.0, bathGas=None, maximumRadicalElectrons=np.inf): + global jobList,speciesDict + for job in jobList: + if isinstance(job, PressureDependenceJob): + pdepjob = job + break + else: + raise InputError('the explorer block must occur after the pressureDependence block') + + source = [speciesDict[name] for name in source] + + explore_tol = Quantity(explore_tol) + + if bathGas: + bathGas0 = bathGas or {}; bathGas = {} + for spec, fraction in bathGas0.items(): + bathGas[speciesDict[spec]] = fraction + + job = ExplorerJob(source=source,pdepjob=pdepjob,explore_tol=explore_tol.value_si, + energy_tol=energy_tol,flux_tol=flux_tol,bathGas=bathGas, maximumRadicalElectrons=maximumRadicalElectrons) + jobList.append(job) + + def SMILES(smiles): return Molecule().fromSMILES(smiles) + def adjacencyList(adj): return Molecule().fromAdjacencyList(adj) + def InChI(inchi): return Molecule().fromInChI(inchi) + +def loadNecessaryDatabases(): + """ + loads transport and statmech databases + """ + from rmgpy.data.statmech import StatmechDatabase + from rmgpy.data.transport import TransportDatabase + + #only load if they are not there already. + try: + getDB('transport') + getDB('statmech') + except DatabaseError: + logging.info("Databases not found. Making databases") + db = RMGDatabase() + db.statmech = StatmechDatabase() + db.statmech.load(os.path.join(settings['database.directory'],'statmech')) + + db.transport = TransportDatabase() + db.transport.load(os.path.join(settings['database.directory'],'transport')) + ################################################################################ + def loadInputFile(path): """ - Load the CanTherm input file located at `path` on disk, and return a list of + Load the Arkane input file located at `path` on disk, and return a list of the jobs defined in that file. """ global speciesDict, transitionStateDict, reactionDict, networkDict, jobList @@ -370,17 +592,21 @@ def loadInputFile(path): 'species': species, 'transitionState': transitionState, 'network': network, + 'database': database, # Jobs 'kinetics': kinetics, 'statmech': statmech, 'thermo': thermo, 'pressureDependence': pressureDependence, + 'explorer':explorer, # Miscellaneous 'SMILES': SMILES, 'adjacencyList': adjacencyList, 'InChI': InChI, } + loadNecessaryDatabases() + with open(path, 'r') as f: try: exec f in global_context, local_context @@ -401,6 +627,9 @@ def loadInputFile(path): directory = os.path.dirname(path) + for rxn in reactionDict.values(): + rxn.elementary_high_p = True + for job in jobList: if isinstance(job, StatMechJob): job.path = os.path.join(directory, job.path) @@ -411,4 +640,4 @@ def loadInputFile(path): job.applyBondEnergyCorrections = useBondCorrections job.atomEnergies = atomEnergies - return jobList + return jobList, reactionDict, speciesDict, transitionStateDict, networkDict diff --git a/rmgpy/cantherm/kinetics.py b/arkane/kinetics.py similarity index 85% rename from rmgpy/cantherm/kinetics.py rename to arkane/kinetics.py index 6560181a90..2ce3d43a8a 100644 --- a/rmgpy/cantherm/kinetics.py +++ b/arkane/kinetics.py @@ -32,26 +32,29 @@ import numpy import string import logging -from sensitivity import KineticsSensitivity as sa - -from rmgpy.cantherm.output import prettify from rmgpy.kinetics.arrhenius import Arrhenius, ArrheniusEP, PDepArrhenius, MultiArrhenius, MultiPDepArrhenius from rmgpy.kinetics.chebyshev import Chebyshev from rmgpy.kinetics.falloff import ThirdBody, Lindemann, Troe from rmgpy.kinetics.kineticsdata import KineticsData, PDepKineticsData from rmgpy.kinetics.tunneling import Wigner, Eckart - import rmgpy.quantity as quantity -import rmgpy.constants as constants from rmgpy.molecule.draw import MoleculeDrawer, createNewSurface +from rmgpy.exceptions import SpeciesError + +from arkane.sensitivity import KineticsSensitivity as sa +from arkane.output import prettify ################################################################################ + class KineticsJob(object): """ - A representation of a CanTherm kinetics job. This job is used to compute + A representation of an Arkane kinetics job. This job is used to compute and save the high-pressure-limit kinetics information for a single reaction. + + `usedTST` - a boolean representing if TST was used to calculate the kinetics + if kinetics is already given in the input, then it is False. """ def __init__(self, reaction, @@ -60,7 +63,7 @@ def __init__(self, reaction, Tlist=None, Tcount=0, sensitivity_conditions=None): - + self.usedTST = False if Tmin is not None: self.Tmin = quantity.Quantity(Tmin) else: @@ -145,6 +148,10 @@ def generateKinetics(self,Tlist=None): """ Generate the kinetics data for the reaction and fit it to a modified Arrhenius model. """ + + if isinstance(self.reaction.kinetics, Arrhenius): + return None + self.usedTST=True kineticsClass = 'Arrhenius' tunneling = self.reaction.transitionState.tunneling @@ -174,7 +181,8 @@ def generateKinetics(self,Tlist=None): self.Kequnits = {2:'mol^2/cm^6', 1:'mol/cm^3', 0:' ', -1:'cm^3/mol', -2:'cm^6/mol^2'}[len(self.reaction.products)-len(self.reaction.reactants)] self.krunits = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[len(self.reaction.products)] self.reaction.kinetics = Arrhenius().fitToData(Tlist, klist, kunits=self.kunits) - + self.reaction.elementary_high_p = True + def save(self, outputFile): """ Save the results of the kinetics job to the file located @@ -193,54 +201,71 @@ def save(self, outputFile): factor = 1e6 ** (order-1) f = open(outputFile, 'a') - - f.write('# ======= =========== =========== =========== ===============\n') - f.write('# Temp. k (TST) Tunneling k (TST+T) Units\n') - f.write('# ======= =========== =========== =========== ===============\n') - - if self.Tlist is None: - Tlist = numpy.array([300,400,500,600,800,1000,1500,2000]) - else: - Tlist =self.Tlist.value_si - - for T in Tlist: - tunneling = reaction.transitionState.tunneling - reaction.transitionState.tunneling = None - k0 = reaction.calculateTSTRateCoefficient(T) * factor - reaction.transitionState.tunneling = tunneling - k = reaction.calculateTSTRateCoefficient(T) * factor - tunneling = reaction.transitionState.tunneling - kappa = k / k0 - ks.append(k) - k0s.append(k0) - f.write('# {0:4g} K {1:11.3e} {2:11g} {3:11.3e} {4}\n'.format(T, k0, kappa, k, self.kunits)) - f.write('# ======= =========== =========== =========== ===============\n') - f.write('\n\n') - - f.write('# ======= ============ =========== ============ ============= =========\n') - f.write('# Temp. Kc (eq) Units krev (TST) krev (TST+T) Units\n') - f.write('# ======= ============ =========== ============ ============= =========\n') - - for n,T in enumerate(Tlist): - k = ks[n] - k0 = k0s[n] - Keq = reaction.getEquilibriumConstant(T) - k0rev = k0/Keq - krev = k/Keq - k0revs.append(k0rev) - krevs.append(krev) - f.write('# {0:4g} K {1:11.3e} {2} {3:11.3e} {4:11.3e} {5}\n'.format(T, Keq, self.Kequnits, k0rev, krev, self.krunits)) + if self.usedTST: + #If TST is not used, eg. it was given in 'reaction', then this will + #throw an error. + f.write('# ======= =========== =========== =========== ===============\n') + f.write('# Temp. k (TST) Tunneling k (TST+T) Units\n') + f.write('# ======= =========== =========== =========== ===============\n') - f.write('# ======= ============ =========== ============ ============= =========\n') - f.write('\n\n') - - kinetics0rev = Arrhenius().fitToData(Tlist, numpy.array(k0revs), kunits=self.krunits) - kineticsrev = Arrhenius().fitToData(Tlist, numpy.array(krevs), kunits=self.krunits) - - f.write('# krev (TST) = {0} \n'.format(kinetics0rev)) - f.write('# krev (TST+T) = {0} \n\n'.format(kineticsrev)) - + if self.Tlist is None: + Tlist = numpy.array([300,400,500,600,800,1000,1500,2000]) + else: + Tlist =self.Tlist.value_si + + for T in Tlist: + tunneling = reaction.transitionState.tunneling + reaction.transitionState.tunneling = None + try: + k0 = reaction.calculateTSTRateCoefficient(T) * factor + except SpeciesError: + k0 = 0 + reaction.transitionState.tunneling = tunneling + try: + k = reaction.calculateTSTRateCoefficient(T) * factor + kappa = k / k0 + except (SpeciesError,ZeroDivisionError): + k = reaction.getRateCoefficient(T) + kappa = 0 + logging.info("The species in reaction {} do not have adequate information for TST, using default kinetics values.".format(reaction)) + tunneling = reaction.transitionState.tunneling + ks.append(k) + k0s.append(k0) + + f.write('# {0:4g} K {1:11.3e} {2:11g} {3:11.3e} {4}\n'.format(T, k0, kappa, k, self.kunits)) + f.write('# ======= =========== =========== =========== ===============\n') + f.write('\n\n') + + f.write('# ======= ============ =========== ============ ============= =========\n') + f.write('# Temp. Kc (eq) Units krev (TST) krev (TST+T) Units\n') + f.write('# ======= ============ =========== ============ ============= =========\n') + + # Initialize Object for Converting Units + if self.Kequnits != ' ': + keq_unit_converter = quantity.Units(self.Kequnits).getConversionFactorFromSI() + else: + keq_unit_converter = 1 + + for n,T in enumerate(Tlist): + k = ks[n] + k0 = k0s[n] + Keq = keq_unit_converter * reaction.getEquilibriumConstant(T) # getEquilibriumConstant returns SI units + k0rev = k0/Keq + krev = k/Keq + k0revs.append(k0rev) + krevs.append(krev) + f.write('# {0:4g} K {1:11.3e} {2} {3:11.3e} {4:11.3e} {5}\n'.format(T, Keq, self.Kequnits, k0rev, krev, self.krunits)) + + f.write('# ======= ============ =========== ============ ============= =========\n') + f.write('\n\n') + + kinetics0rev = Arrhenius().fitToData(Tlist, numpy.array(k0revs), kunits=self.krunits) + kineticsrev = Arrhenius().fitToData(Tlist, numpy.array(krevs), kunits=self.krunits) + + f.write('# krev (TST) = {0} \n'.format(kinetics0rev)) + f.write('# krev (TST+T) = {0} \n\n'.format(kineticsrev)) + # Reaction path degeneracy is INCLUDED in the kinetics itself! string = 'kinetics(label={0!r}, kinetics={1!r})'.format(reaction.label, reaction.kinetics) f.write('{0}\n\n'.format(prettify(string))) @@ -252,8 +277,12 @@ def save(self, outputFile): reaction = self.reaction kinetics = reaction.kinetics - - string = '{0!s:51} {1:9.3e} {2:9.3f} {3:9.3f}\n'.format( + + string = '' + if reaction.kinetics.comment: + for line in reaction.kinetics.comment.split("\n"): + string += "! {0}\n".format(line) + string += '{0!s:51} {1:9.3e} {2:9.3f} {3:9.3f}\n'.format( reaction, kinetics.A.value_si * factor, kinetics.n.value_si, @@ -299,11 +328,14 @@ def plot(self, outputDirectory): plt.title(reaction_str) plt.xlabel('1000 / Temperature (1000/K)') plt.ylabel('Rate coefficient ({0})'.format(self.kunits)) - if not os.path.exists('plots'): - os.mkdir('plots') + + plot_path = os.path.join(outputDirectory, 'plots') + + if not os.path.exists(plot_path): + os.mkdir(plot_path) valid_chars = "-_.()<=> %s%s" % (string.ascii_letters, string.digits) - filename = os.path.join('plots', ''.join(c for c in reaction_str if c in valid_chars) + '.pdf') - plt.savefig(os.path.join(outputDirectory, filename)) + filename = ''.join(c for c in reaction_str if c in valid_chars) + '.pdf' + plt.savefig(os.path.join(plot_path, filename)) plt.close() def draw(self, outputDirectory, format='pdf'): @@ -316,14 +348,16 @@ def draw(self, outputDirectory, format='pdf'): one of the following: `pdf`, `svg`, `png`. """ - if not os.path.exists('paths'): - os.mkdir('paths') + drawing_path = os.path.join(outputDirectory, 'paths') + + if not os.path.exists(drawing_path): + os.mkdir(drawing_path) valid_chars = "-_.()<=> %s%s" % (string.ascii_letters, string.digits) reaction_str = '{0} {1} {2}'.format( ' + '.join([reactant.label for reactant in self.reaction.reactants]), '<=>', ' + '.join([product.label for product in self.reaction.products])) - filename = os.path.join('paths', ''.join(c for c in reaction_str if c in valid_chars) + '.pdf') - path = os.path.join(outputDirectory, filename) + filename = ''.join(c for c in reaction_str if c in valid_chars) + '.pdf' + path = os.path.join(drawing_path, filename) KineticsDrawer().draw(self.reaction, format=format, path=path) diff --git a/rmgpy/cantherm/main.py b/arkane/main.py similarity index 62% rename from rmgpy/cantherm/main.py rename to arkane/main.py index e0fd20d90a..d16f1463fb 100644 --- a/rmgpy/cantherm/main.py +++ b/arkane/main.py @@ -29,8 +29,7 @@ ############################################################################### """ -This module contains the :class:`CanTherm` class, the main class used to run -CanTherm. +This module contains the :class:`Arkane` class, the main class used to run Arkane. """ import os @@ -39,26 +38,32 @@ import logging import argparse import time +import csv try: import matplotlib matplotlib.rc('mathtext', default='regular') except ImportError: pass -from rmgpy.chemkin import writeElementsSection, writeThermoEntry, writeKineticsEntry +from rmgpy.chemkin import writeElementsSection +from rmgpy.data.thermo import ThermoLibrary +from rmgpy.data.base import Entry +from rmgpy.data.kinetics.library import KineticsLibrary +from rmgpy.exceptions import InputError -from rmgpy.cantherm.input import loadInputFile - -from rmgpy.cantherm.kinetics import KineticsJob -from rmgpy.cantherm.statmech import StatMechJob -from rmgpy.cantherm.thermo import ThermoJob -from rmgpy.cantherm.pdep import PressureDependenceJob +from arkane.input import loadInputFile +from arkane.kinetics import KineticsJob +from arkane.statmech import StatMechJob +from arkane.thermo import ThermoJob +from arkane.pdep import PressureDependenceJob +from arkane.explorer import ExplorerJob ################################################################################ -class CanTherm: + +class Arkane: """ - The :class:`CanTherm` class represents an instance of CanTherm, a tool for + The :class:`Arkane` class represents an instance of Arkane, a tool for computing properties of chemical species and reactions. The attributes are: =================== ======================================================== @@ -88,14 +93,14 @@ def __init__(self, inputFile=None, outputDirectory=None, verbose=logging.INFO): def parseCommandLineArguments(self): """ - Parse the command-line arguments being passed to CanTherm. This uses the + Parse the command-line arguments being passed to Arkane. This uses the :mod:`argparse` module, which ensures that the command-line arguments are sensible, parses them, and returns them. """ parser = argparse.ArgumentParser(description= """ - CanTherm is a Python toolkit for computing chemical reaction rates and other + Arkane is a Python toolkit for computing chemical reaction rates and other properties used in detailed kinetics models using various methodologies and theories. """) @@ -138,7 +143,7 @@ def parseCommandLineArguments(self): def initializeLog(self, verbose=logging.INFO, logFile=None): """ - Set up a logger for CanTherm to use to print output to stdout. The + Set up a logger for Arkane to use to print output to stdout. The `verbose` parameter is an integer specifying the amount of log text seen at the console; the levels correspond to those of the :data:`logging` module. """ @@ -176,23 +181,23 @@ def initializeLog(self, verbose=logging.INFO, logFile=None): def logHeader(self, level=logging.INFO): """ - Output a header containing identifying information about CanTherm to the log. + Output a header containing identifying information about Arkane to the log. """ from rmgpy import __version__ - logging.log(level, 'CanTherm execution initiated at {0}'.format(time.asctime())) + logging.log(level, 'Arkane execution initiated at {0}'.format(time.asctime())) logging.log(level, '') - logging.log(level, '###############################################################') - logging.log(level, '# #') - logging.log(level, '# CanTherm #') - logging.log(level, '# #') - logging.log(level, '# Version: {0:48s} #'.format(__version__)) - logging.log(level, '# Authors: RMG Developers (rmg_dev@mit.edu) #') - logging.log(level, '# P.I.s: William H. Green (whgreen@mit.edu) #') - logging.log(level, '# Richard H. West (r.west@neu.edu) #') - logging.log(level, '# Website: http://reactionmechanismgenerator.github.io/ #') - logging.log(level, '# #') - logging.log(level, '###############################################################') + logging.log(level, '################################################################') + logging.log(level, '# #') + logging.log(level, '# Automated Reaction Kinetics and Network Exploration (Arkane) #') + logging.log(level, '# #') + logging.log(level, '# Version: {0:49s} #'.format(__version__)) + logging.log(level, '# Authors: RMG Developers (rmg_dev@mit.edu) #') + logging.log(level, '# P.I.s: William H. Green (whgreen@mit.edu) #') + logging.log(level, '# Richard H. West (r.west@neu.edu) #') + logging.log(level, '# Website: http://reactionmechanismgenerator.github.io/ #') + logging.log(level, '# #') + logging.log(level, '################################################################') logging.log(level, '') def logFooter(self, level=logging.INFO): @@ -200,7 +205,7 @@ def logFooter(self, level=logging.INFO): Output a footer to the log. """ logging.log(level, '') - logging.log(level, 'CanTherm execution terminated at {0}'.format(time.asctime())) + logging.log(level, 'Arkane execution terminated at {0}'.format(time.asctime())) def loadInputFile(self, inputFile): """ @@ -208,7 +213,7 @@ def loadInputFile(self, inputFile): loaded set of jobs as a list. """ self.inputFile = inputFile - self.jobList = loadInputFile(self.inputFile) + self.jobList, self.reactionDict, self.speciesDict, self.transitionStateDict, self.networkDict = loadInputFile(self.inputFile) logging.info('') return self.jobList @@ -220,7 +225,7 @@ def execute(self): # Initialize the logging system (both to the console and to a file in the # output directory) - self.initializeLog(self.verbose, os.path.join(self.outputDirectory, 'cantherm.log')) + self.initializeLog(self.verbose, os.path.join(self.outputDirectory, 'arkane.log')) # Print some information to the beginning of the log self.logHeader() @@ -253,23 +258,118 @@ def execute(self): f.write('THERM ALL\n') f.write(' 300.000 1000.000 5000.000\n\n') - # run thermo jobs (printing out thermo stuff) + # run thermo and statmech jobs (also writes thermo blocks to Chemkin file) + supporting_info = [] for job in self.jobList: - if isinstance(job,ThermoJob) or isinstance(job, StatMechJob): + if isinstance(job, ThermoJob): job.execute(outputFile=outputFile, plot=self.plot) + if isinstance(job, StatMechJob): + job.execute(outputFile=outputFile, plot=self.plot) + supporting_info.append(job.supporting_info) with open(chemkinFile, 'a') as f: f.write('\n') f.write('END\n\n\n\n') f.write('REACTIONS KCAL/MOLE MOLES\n\n') - # run kinetics and pdep jobs (and outputing chemkin stuff) + supporting_info_file = os.path.join(self.outputDirectory, 'supporting_information.csv') + with open(supporting_info_file, 'wb') as csvfile: + writer = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) + writer.writerow(['Label','Rotational constant (cm-1)','Unscaled frequencies (cm-1)']) + for row in supporting_info: + label = row[0] + rot = '-' + freq = '-' + if len(row) > 1: # monoatomic species have no frequencies nor rotational constants + if isinstance(row[1].rotationalConstant.value, float): + # diatomic species have a single rotational constant + rot = '{0:.2f}'.format(row[1].rotationalConstant.value) + else: + rot = ', '.join(['{0:.2f}'.format(s) for s in row[1].rotationalConstant.value]) + freq = '' + if len(row) == 4: + freq = '{0:.1f}'.format(abs(row[3])) + 'i, ' + freq += ', '.join(['{0:.1f}'.format(s) for s in row[2]]) + writer.writerow([label, rot, freq]) + + # run kinetics and pdep jobs (also writes reaction blocks to Chemkin file) for job in self.jobList: - if isinstance(job,KineticsJob) or isinstance(job, PressureDependenceJob): + if isinstance(job,KineticsJob): job.execute(outputFile=outputFile, plot=self.plot) + elif isinstance(job, PressureDependenceJob) and not any([isinstance(job,ExplorerJob) for job in self.jobList]): #if there is an explorer job the pdep job will be run in the explorer job + if job.network is None: + raise InputError('No network matched the label of the pressureDependence block and there is no explorer block to generate a network') + job.execute(outputFile=outputFile, plot=self.plot) + elif isinstance(job, ExplorerJob): + thermoLibrary,kineticsLibrary,speciesList = self.getLibraries() + job.execute(outputFile=outputFile, plot=self.plot, speciesList=speciesList, thermoLibrary=thermoLibrary, kineticsLibrary=kineticsLibrary) with open(chemkinFile, 'a') as f: f.write('END\n\n') # Print some information to the end of the log self.logFooter() + + def getLibraries(self): + + name = 'kineticsjobs' + + speciesList = self.speciesDict.values() + reactionList = self.reactionDict.values() + + # remove duplicate species + for rxn in reactionList: + for i,rspc in enumerate(rxn.reactants): + for spc in speciesList: + if spc.isIsomorphic(rspc): + rxn.reactants[i] = spc + break + for i,rspc in enumerate(rxn.products): + for spc in speciesList: + if spc.isIsomorphic(rspc): + rxn.products[i] = spc + break + del_inds = [] + for i,spc1 in enumerate(speciesList): + for j,spc2 in enumerate(speciesList): + if j>i and spc1.isIsomorphic(spc2): + del_inds.append(j) + + for j in sorted(del_inds)[::-1]: + del speciesList[j] + + thermoLibrary = ThermoLibrary(name=name) + for i,species in enumerate(speciesList): + if species.thermo: + thermoLibrary.loadEntry(index = i + 1, + label = species.label, + molecule = species.molecule[0].toAdjacencyList(), + thermo = species.thermo, + shortDesc = species.thermo.comment + ) + else: + logging.warning('Species {0} did not contain any thermo data and was omitted from the thermo library.'.format(str(species))) + + # load kinetics library entries + kineticsLibrary = KineticsLibrary(name=name,autoGenerated=True) + kineticsLibrary.entries = {} + for i,reaction in enumerate(reactionList): + entry = Entry( + index = i+1, + label = reaction.toLabeledStr(), + item = reaction, + data = reaction.kinetics, + ) + + if reaction.kinetics is not None: + if hasattr(reaction,'library') and reaction.library: + entry.longDesc = 'Originally from reaction library: ' +\ + reaction.library + "\n" + reaction.kinetics.comment + else: + entry.longDesc = reaction.kinetics.comment + + kineticsLibrary.entries[i+1] = entry + + kineticsLibrary.label = name + + return thermoLibrary,kineticsLibrary,speciesList diff --git a/arkane/mainTest.py b/arkane/mainTest.py new file mode 100644 index 0000000000..4250fa6a57 --- /dev/null +++ b/arkane/mainTest.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2018 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +""" +This script contains unit tests of the :mod:`arkane.main` module. +""" + +import unittest +import os +import shutil +from nose.plugins.attrib import attr + +import rmgpy +from arkane import Arkane + +################################################################################ + + +@attr('functional') +class TestArkaneExamples(unittest.TestCase): + """ + Run all of Arkane's examples, and report which one failed + """ + @classmethod + def setUpClass(cls): + """A function that is run ONCE before all unit tests in this class.""" + cls.base_path = os.path.join(os.path.dirname(os.path.dirname(rmgpy.__file__)), 'examples', 'arkane') + cls.failed = [] + cls.example_types = ['species', 'reactions', 'networks'] + + def test_arkane_examples(self): + for example_type in self.example_types: + example_type_path = os.path.join(self.base_path, example_type) + for example in os.listdir(example_type_path): + path = os.path.join(example_type_path, example) + arkane = Arkane(inputFile=os.path.join(path, 'input.py'), outputDirectory=path) + arkane.plot = True + arkane.execute() + with open(os.path.join(path, 'arkane.log'), 'r') as f: + log = f.readlines() + for line in log[::-1]: + if 'execution terminated' in line: + break + else: + self.failed.append([example_type, example]) + error_message = 'Arkane example(s) failed: ' + for example_type, example_name in self.failed: + error_message += '{1} in {0}; '.format(example_name, example_type) + self.assertFalse(self.failed, error_message) + + @classmethod + def tearDownClass(cls): + """A function that is run ONCE after all unit tests in this class.""" + cls.extensions_to_delete = ['pdf', 'csv', 'txt', 'inp'] + cls.files_to_delete = ['arkane.log', 'output.py'] + cls.files_to_keep = ['README.txt'] # files to keep that have extentions marked for deletion + cls.base_path = os.path.join(os.path.dirname(os.path.dirname(rmgpy.__file__)), 'examples', 'arkane') + for example_type in cls.example_types: + example_type_path = os.path.join(cls.base_path, example_type) + for example in os.listdir(example_type_path): + # clean working folder from all previous test output + example_path = os.path.join(example_type_path, example) + for name in os.listdir(example_path): + item_path = os.path.join(example_path, name) + if os.path.isfile(item_path): + extension = name.split('.')[-1] + if name in cls.files_to_delete or\ + (extension in cls.extensions_to_delete and name not in cls.files_to_keep): + os.remove(item_path) + else: + # This is a sub-directory. remove. + shutil.rmtree(item_path) + + +if __name__ == '__main__': + unittest.main(testRunner=unittest.TextTestRunner(verbosity=2)) diff --git a/rmgpy/cantherm/molpro.py b/arkane/molpro.py similarity index 72% rename from rmgpy/cantherm/molpro.py rename to arkane/molpro.py index 0f6525649c..347e1f57ab 100644 --- a/rmgpy/cantherm/molpro.py +++ b/arkane/molpro.py @@ -31,15 +31,21 @@ import math import numpy import logging -import rmgpy.constants as constants +import rmgpy.constants as constants +from rmgpy.exceptions import InputError from rmgpy.statmech import IdealGasTranslation, NonlinearRotor, LinearRotor, HarmonicOscillator, Conformer +from arkane.common import get_element_mass + +################################################################################ + + class MolproLog: """ Represents a Molpro log file. The attribute `path` refers to the location on disk of the Molpro log file of interest. Methods are provided - to extract a variety of information into CanTherm classes and/or NumPy + to extract a variety of information into Arkane classes and/or NumPy arrays. """ @@ -110,14 +116,14 @@ def loadGeometry(self): last is returned. """ - symbol = []; coord = [] + symbol, coord, mass, number = [], [], [], [] f = open(self.path, 'r') line = f.readline() while line != '': # Automatically determine the number of atoms if 'Current geometry' in line: - symbol = []; coord = [] + symbol, coord = [], [] while 'ENERGY' not in line: line = f.readline() line = f.readline() @@ -147,39 +153,17 @@ def loadGeometry(self): line = f.readline() line = f.readline() + # Assign appropriate mass to each atom in the molecule + for atom1 in symbol: + mass1, num1 = get_element_mass(atom1) + mass.append(mass1) + number.append(num1) + number = numpy.array(number, numpy.int) + mass = numpy.array(mass, numpy.float64) coord = numpy.array(coord, numpy.float64) - number = numpy.zeros(len(symbol), numpy.int) - mass = numpy.zeros(len(symbol), numpy.float64) - # Use the atomic mass of the most common isotope rather than the - # average atomic mass - # These values were taken from "Atomic Weights and Isotopic Compositions" v3.0 (July 2010) from NIST - for i in range(len(symbol)): - if symbol[i] == 'H': - number[i] = 1 - mass[i] = 1.00782503207 - elif symbol[i] == 'C': - number[i] = 6 - mass[i] = 12.0 - elif symbol[i] == 'N': - number[i] = 7 - mass[i] = 14.0030740048 - elif symbol[i] == 'O': - number[i] = 8 - mass[i] = 15.99491461956 - elif symbol[i] == 'P': - number[i] = 15 - mass[i] = 30.97376163 - elif symbol[i] == 'S': - number[i] = 16 - mass[i] = 31.97207100 - elif symbol[i] == 'Cl': - number[i] = 17 - mass[i] = 35.4527 - elif symbol[i] == 'I': - number[i] = 53 - mass[i] = 126.90447 - else: - print 'Atomic number {0:d} not yet supported in loadGeometry().'.format(number[i]) + if len(number) == 0 or len(coord) == 0 or len(mass) == 0: + raise InputError('Unable to read atoms from Molpro geometry output file {0}'.format(self.path)) + return coord, number, mass def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, symfromlog=None, label=''): @@ -189,6 +173,7 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym """ modes = [] + unscaled_frequencies = [] E0 = 0.0 f = open(self.path, 'r') @@ -268,6 +253,7 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym # Convert from K to cm^-1 if len(frequencies) > 0: frequencies = [freq * 0.695039 for freq in frequencies] # kB = 0.695039 cm^-1/K + unscaled_frequencies = frequencies vibration = HarmonicOscillator(frequencies=(frequencies,"cm^-1")) modes.append(vibration) @@ -279,59 +265,81 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym # Close file when finished f.close() - return Conformer(E0=(E0*0.001,"kJ/mol"), modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers) + return Conformer(E0=(E0*0.001,"kJ/mol"), modes=modes, spinMultiplicity=spinMultiplicity, + opticalIsomers=opticalIsomers), unscaled_frequencies - def loadEnergy(self,frequencyScaleFactor=1.): + def loadEnergy(self, frequencyScaleFactor=1.): """ - Return the f12 energy in J/mol from a Molpro Logfile of a CCSD(T)-f12 job. - This function determines which energy (f12a or f12b) to use based on the basis set, - which it will parse out of the Molpro file. For the vtz and dtz basis sets f12a is - better approximation, but for higher basis sets f12b is a better approximation + Return either the f12 or MRCI energy in J/mol from a Molpro Logfile. + If the MRCI job outputted the MRCI+Davidson energy, the latter is returned. + For CCSD(T)-f12, the function determines which energy (f12a or f12b) to use based on the basis set, + which it will parse out of the Molpro file. For the vdz and vtz basis sets f12a is + a better approximation, but for higher basis sets f12b is a better approximation. """ - f = open(self.path, 'r') - line=f.readline() - - #search for basisSet - while line!='': - if 'basis' in line.lower(): - if 'vtz' in line.lower() or 'vdz' in line.lower(): - f12a=True - else: f12a=False - break - line=f.readline() - else: raise Exception('Could not find basis set in Molpro File') - #search for energy - E0=None - if f12a: - while line!='': - if ('RHF-UCCSD(T)-F12a energy' in line - or 'RHF-RCCSD(T)-F12a energy' in line - or 'CCSD(T)-F12a total energy ' in line): - E0=float(line.split()[-1]) - break - if 'Electronic Energy at 0' in line: - E0=float(line.split()[-2]) - break - line=f.readline() - else: - while line!='': - if ('RHF-UCCSD(T)-F12b energy' in line - or 'RHF-RCCSD(T)-F12b energy' in line - or 'CCSD(T)-F12b total energy ' in line): - E0=float(line.split()[-1]) - break - if 'Electronic Energy at 0' in line: - E0=float(line.split()[-2]) + E0 = None + with open(self.path, 'r') as f: + lines = f.readlines() + # Determine whether this is f12a or f12b according to the basis set, or whether this is MRCI. + f12a, f12b, mrci = False, False, False + for line in lines: + if 'basis' in line.lower(): + if 'vtz' in line.lower() or 'vdz' in line.lower(): + f12a = True # MRCI could also have a vdz/vtz basis, so don't break yet + elif any(high_basis in line.lower() for high_basis in ['vqz', 'v5z', 'v6z', 'v7z', 'v8z']): + f12b = True # MRCI could also have a v(4+)z basis, so don't break yet + elif 'mrci' in line.lower(): + mrci = True + f12a, f12b = False, False break - line=f.readline() - - f.close() - - #multiply E0 by correct constants + elif 'point group' in line.lower(): + # We should know the method by this point, so break if possible, but don't throw an error yet + if any([mrci, f12a, f12b]): + break + else: + raise ValueError('Could not determine type of calculation. Currently, CCSD(T)-F12a, CCSD(T)-F12b,' + ' MRCI, MRCI+Davidson are supported') + # Search for E0 + for line in lines: + if f12a: + if 'CCSD(T)-F12a' in line and 'energy' in line: + E0 = float(line.split()[-1]) + break + if 'Electronic Energy at 0' in line: + E0 = float(line.split()[-2]) + break + elif f12b: + if 'CCSD(T)-F12b' in line and 'energy' in line: + E0 = float(line.split()[-1]) + break + if 'Electronic Energy at 0' in line: + E0 = float(line.split()[-2]) + break + elif mrci: + # First search for MRCI+Davidson energy + if '(Davidson, relaxed reference)' in line: + E0 = float(line.split()[3]) + logging.debug('Found MRCI+Davidson energy in molpro log file {0}, using this value'.format( + self.path)) + break + if E0 is None and mrci: + # No Davidson correction is given, search for MRCI energy + read_e0 = False + for line in lines: + if read_e0: + E0 = float(line.split()[0]) + logging.debug('Found MRCI energy in molpro log file {0}, using this value' + ' (did NOT find MRCI+Davidson)'.format(self.path)) + break + if all(w in line for w in ('MRCI', 'MULTI', 'HF-SCF')): + read_e0 = True + logging.debug('Molpro energy found is {0} Hartree'.format(E0)) + # multiply E0 by correct constants if E0 is not None: E0 = E0 * constants.E_h * constants.Na + logging.debug('Molpro energy found is {0} J/mol'.format(E0)) return E0 - else: raise Exception('Unable to find energy in Molpro log file.') + else: + raise Exception('Unable to find energy in Molpro log file {0}.'.format(self.path)) def loadZeroPointEnergy(self): """ @@ -343,11 +351,9 @@ def loadZeroPointEnergy(self): f = open(self.path, 'r') line = f.readline() while line != '': - # Do NOT read the ZPE from the "E(ZPE)=" line, as this is the scaled version! # We will read in the unscaled ZPE and later multiply the scaling factor # from the input file - if 'Electronic Energy at 0 [K]:' in line: electronic_energy = float(line.split()[5]) line = f.readline() @@ -361,7 +367,8 @@ def loadZeroPointEnergy(self): if ZPE is not None: return ZPE else: - raise Exception('Unable to find zero-point energy in MolPro log file. Make sure that the keyword {frequencies, thermo, print,thermo} is included in the input file') + raise Exception('Unable to find zero-point energy in Molpro log file. Make sure that the' + ' keyword {frequencies, thermo, print,thermo} is included in the input file') def loadNegativeFrequency(self): """ diff --git a/rmgpy/cantherm/molproTest.py b/arkane/molproTest.py similarity index 88% rename from rmgpy/cantherm/molproTest.py rename to arkane/molproTest.py index 0d2bc51331..85b59df3e1 100644 --- a/rmgpy/cantherm/molproTest.py +++ b/arkane/molproTest.py @@ -32,12 +32,14 @@ import unittest import os -from rmgpy.cantherm.molpro import MolproLog from rmgpy.statmech import IdealGasTranslation, LinearRotor, NonlinearRotor, HarmonicOscillator, HinderedRotor import rmgpy.constants as constants +from arkane.molpro import MolproLog + ################################################################################ + class MolproTest(unittest.TestCase): """ Contains unit tests for the chempy.io.gaussian module, used for reading @@ -84,7 +86,7 @@ def testLoadHOSIFromMolpro_log(self): """ log = MolproLog(os.path.join(os.path.dirname(__file__),'data','HOSI_ccsd_t1.out')) - conformer = log.loadConformer(symfromlog=True, spinMultiplicity=1) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True, spinMultiplicity=1) E0 = log.loadEnergy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,IdealGasTranslation)]) == 1) @@ -105,6 +107,16 @@ def testLoadHOSIFromMolpro_log(self): self.assertEqual(conformer.spinMultiplicity, 1) self.assertEqual(conformer.opticalIsomers, 1) + def test_load_mrci_e0(self): + """ + Load the MRCI and MRCI+Davidson energies from a molpro output file + """ + mrci_log = MolproLog(os.path.join(os.path.dirname(__file__),'data','molpro_mrci.out')) + mrciq_log = MolproLog(os.path.join(os.path.dirname(__file__),'data','molpro_mrci+q.out')) + mrci_E0=mrci_log.loadEnergy() + mrciq_E0=mrciq_log.loadEnergy() + self.assertAlmostEqual(mrci_E0, -293217091.0381712, places=7) + self.assertAlmostEqual(mrciq_E0, -293284017.3925107, places=7) + if __name__ == '__main__': unittest.main( testRunner = unittest.TextTestRunner(verbosity=2) ) - diff --git a/rmgpy/cantherm/output.py b/arkane/output.py similarity index 98% rename from rmgpy/cantherm/output.py rename to arkane/output.py index 7b3dedb3eb..f214ea938d 100644 --- a/rmgpy/cantherm/output.py +++ b/arkane/output.py @@ -29,13 +29,14 @@ ############################################################################### """ -This module contains helper functionality for writing CanTherm output files. +This module contains helper functionality for writing Arkane output files. """ import ast ################################################################################ + class PrettifyVisitor(ast.NodeVisitor): """ A class for traversing an abstract syntax tree to assemble a prettier diff --git a/rmgpy/cantherm/pdep.py b/arkane/pdep.py similarity index 94% rename from rmgpy/cantherm/pdep.py rename to arkane/pdep.py index 2dc4f6fd7c..f5e54c505c 100644 --- a/rmgpy/cantherm/pdep.py +++ b/arkane/pdep.py @@ -38,18 +38,21 @@ import math import numpy import logging + import rmgpy.quantity as quantity from rmgpy.kinetics import Chebyshev, PDepArrhenius from rmgpy.reaction import Reaction from rmgpy.kinetics.tunneling import Wigner, Eckart from rmgpy.data.kinetics.library import LibraryReaction -from rmgpy.cantherm.output import prettify from rmgpy.chemkin import writeKineticsEntry -from sensitivity import PDepSensitivity as sa from rmgpy.exceptions import InvalidMicrocanonicalRateError, ModifiedStrongCollisionError +from arkane.output import prettify +from arkane.sensitivity import PDepSensitivity as sa + ################################################################################ + class PressureDependenceJob(object): """ A representation of a pressure dependence job. The attributes are: @@ -150,6 +153,11 @@ def __init__(self, network, else: self.sensitivity_conditions = None + if self.Tlist is None and self.Tmin is not None and self.Tmax is not None and self.Tcount is not None: + self.generateTemperatureList() + if self.Plist is None and self.Pmin is not None and self.Pmax is not None and self.Pcount is not None: + self.generatePressureList() + @property def Tmin(self): """The minimum temperature at which the computed k(T,P) values are valid, or ``None`` if not defined.""" @@ -230,6 +238,19 @@ def copy(self): ) def execute(self, outputFile, plot, format='pdf', print_summary=True): + + for config in self.network.isomers + self.network.reactants + self.network.products: + for spec in config.species: + if spec.conformer.E0 is None: + raise AttributeError('species {0} is missing energy for its conformer'.format(spec.label)) + + # set transition state Energy if not set previously using same method as RMG pdep + for reaction in self.network.pathReactions: + transitionState = reaction.transitionState + if transitionState.conformer and transitionState.conformer.E0 is None: + transitionState.conformer.E0 = (sum([spec.conformer.E0.value_si for spec in reaction.reactants]) + reaction.kinetics.Ea.value_si,"J/mol") + logging.info('Approximated transitions state E0 for reaction {3} from kinetics ' + 'A={0}, n={1}, Ea={2} J/mol'.format(reaction.kinetics.A.value_si,reaction.kinetics.n.value_si,reaction.kinetics.Ea.value_si,reaction.label)) if print_summary: self.network.printSummary() @@ -252,7 +273,7 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True): for i in xrange(3): try: sa(self, os.path.dirname(outputFile), perturbation=perturbation) - except (InvalidMicrocanonicalRateError, ModifiedStrongCollisionError): + except (InvalidMicrocanonicalRateError, ModifiedStrongCollisionError) as exept: logging.warn("Could not complete the sensitivity analysis with a perturbation of {0}" " kcal/mol, trying {1} kcal/mol instead.".format( perturbation, perturbation / 2.0)) @@ -262,7 +283,7 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True): else: logging.error("Could not complete the sensitivity analysis even with a perturbation of {0}" " kcal/mol".format(perturbation)) - raise + raise exept logging.info("Completed the sensitivity analysis using a perturbation of {0} kcal/mol".format( perturbation)) logging.debug('Finished pdep job for reaction {0}.'.format(self.network.label)) @@ -300,6 +321,12 @@ def generateTemperatureList(self): def initialize(self): for reaction in self.network.pathReactions: tunneling = reaction.transitionState.tunneling + # throw descriptive error if tunneling not allowed + if tunneling and reaction.transitionState.frequency is None and reaction.kinetics is not None: + raise ValueError("""Cannot apply tunneling for reaction {0} when inverse laplace is used. + Either remove tunnelling parameter or input transitionState + frequencies/quantum file""".format(reaction.label)) + # add tunneling parameters if isinstance(tunneling, Wigner) and tunneling.frequency is None: tunneling.frequency = (reaction.transitionState.frequency.value_si,"cm^-1") elif isinstance(tunneling, Eckart) and tunneling.frequency is None: @@ -591,8 +618,7 @@ def draw(self, outputDirectory, format='pdf'): def saveInputFile(self, path): """ - Save a CanTherm input file for the pressure dependence job to `path` - on disk. + Save an Arkane input file for the pressure dependence job to `path` on disk. """ speciesList = self.network.getAllSpecies() diff --git a/rmgpy/cantherm/pdepTest.py b/arkane/pdepTest.py similarity index 93% rename from rmgpy/cantherm/pdepTest.py rename to arkane/pdepTest.py index 24e7a93805..8836642a3d 100644 --- a/rmgpy/cantherm/pdepTest.py +++ b/arkane/pdepTest.py @@ -32,42 +32,45 @@ import unittest import shutil import logging + from nose.plugins.attrib import attr -from rmgpy.cantherm.main import CanTherm + from rmgpy import settings from rmgpy.chemkin import readReactionsBlock from rmgpy.species import Species from rmgpy.kinetics.chebyshev import Chebyshev +from arkane.main import Arkane + ################################################################################ @attr('functional') -class CanthermTest(unittest.TestCase): +class ArkaneTest(unittest.TestCase): """ - Contains unit tests for the sensitivity module in Cantherm + Contains unit tests for the sensitivity module in Arkane """ @classmethod def setUp(self): """A function that is run ONCE before all unit tests in this class.""" - self.directory = os.path.join(settings['test_data.directory'], 'Cantherm', 'tst1', '') + self.directory = os.path.join(settings['test_data.directory'], 'arkane', 'tst1', '') self.input_file = os.path.join(self.directory, 'pdep_sa.py') # clean working folder from all previous test output dirs = [d for d in os.listdir(self.directory) if not os.path.isfile(os.path.join(self.directory, d))] for d in dirs: - shutil.rmtree(os.path.join(settings['test_data.directory'], 'Cantherm', 'tst1', d, '')) + shutil.rmtree(os.path.join(settings['test_data.directory'], 'arkane', 'tst1', d, '')) files = [f for f in os.listdir(self.directory) if os.path.isfile(os.path.join(self.directory, f))] for f in files: if not 'pdep_sa' in f: - os.remove(os.path.join(settings['test_data.directory'], 'Cantherm', 'tst1', f)) + os.remove(os.path.join(settings['test_data.directory'], 'arkane', 'tst1', f)) def testPDepJob(self): """ - A general test for a PDep job in Cantherm + A general test for a PDep job in Arkane """ - self.tst1 = CanTherm() + self.tst1 = Arkane() self.tst1.inputFile = self.input_file self.tst1.outputDirectory = self.directory self.tst1.verbose = logging.WARN @@ -115,14 +118,14 @@ def testPDepJob(self): @classmethod def tearDown(self): """A function that is run ONCE after all unit tests in this class.""" - self.directory = os.path.join(settings['test_data.directory'], 'Cantherm', 'tst1', '') + self.directory = os.path.join(settings['test_data.directory'], 'arkane', 'tst1', '') self.input_file = os.path.join(self.directory, 'pdep_sa.py') # clean working folder from all previous test output dirs = [d for d in os.listdir(self.directory) if not os.path.isfile(os.path.join(self.directory, d))] for d in dirs: - shutil.rmtree(os.path.join(settings['test_data.directory'], 'Cantherm', 'tst1', d, '')) + shutil.rmtree(os.path.join(settings['test_data.directory'], 'arkane', 'tst1', d, '')) files = [f for f in os.listdir(self.directory) if os.path.isfile(os.path.join(self.directory, f))] for f in files: if not 'pdep_sa' in f: - os.remove(os.path.join(settings['test_data.directory'], 'Cantherm', 'tst1', f)) + os.remove(os.path.join(settings['test_data.directory'], 'arkane', 'tst1', f)) diff --git a/rmgpy/cantherm/qchem.py b/arkane/qchem.py similarity index 59% rename from rmgpy/cantherm/qchem.py rename to arkane/qchem.py index a975b41bd3..9791dd2022 100644 --- a/rmgpy/cantherm/qchem.py +++ b/arkane/qchem.py @@ -29,21 +29,26 @@ ############################################################################### import math -import numpy import logging import os.path +import numpy + import rmgpy.constants as constants from rmgpy.exceptions import InputError -from rmgpy.cantherm.common import checkConformerEnergy from rmgpy.statmech import IdealGasTranslation, NonlinearRotor, LinearRotor, HarmonicOscillator, Conformer + +from arkane.common import check_conformer_energy, get_element_mass + ################################################################################ -class QchemLog: + + +class QChemLog: """ - Represent an output file from Qchem. The attribute `path` refers to the - location on disk of the Qchem output file of interest. Methods are provided - to extract a variety of information into CanTherm classes and/or NumPy + Represent an output file from QChem. The attribute `path` refers to the + location on disk of the QChem output file of interest. Methods are provided + to extract a variety of information into Arkane classes and/or NumPy arrays. - """ + """ def __init__(self, path): self.path = path @@ -51,11 +56,11 @@ def __init__(self, path): def getNumberOfAtoms(self): """ Return the number of atoms in the molecular configuration used in - the Qchem output file. + the QChem output file. """ Natoms = 0 - # Open Qchem log file for parsing + # Open QChem log file for parsing f = open(self.path, 'r') line = f.readline() while line != '' and Natoms == 0: @@ -73,7 +78,7 @@ def getNumberOfAtoms(self): def loadForceConstantMatrix(self): """ - Return the force constant matrix (in Cartesian coordinates) from the + Return the force constant matrix (in Cartesian coordinates) from the QChem log file. If multiple such matrices are identified, only the last is returned. The units of the returned force constants are J/m^2. If no force constant matrix can be found in the log file, @@ -105,40 +110,38 @@ def loadForceConstantMatrix(self): # Close file when finished f.close() - return F - + return F + def loadGeometry(self): - + """ Return the optimum geometry of the molecular configuration from the - Qchem log file. If multiple such geometries are identified, only the + QChem log file. If multiple such geometries are identified, only the last is returned. """ - atom = []; coord = []; number = []; - + atom, coord, number, mass = [], [], [], [] with open(self.path) as f: log = f.read().splitlines() - #First check that the Qchem job file (not necessarily a geometry optimization) - #has successfully completed, if not an error is thrown + # First check that the QChem job file (not necessarily a geometry optimization) + # has successfully completed, if not an error is thrown completed_job = False for line in reversed(log): if 'Total job time:' in line: - logging.debug('Found a sucessfully completed Qchem Job') + logging.debug('Found a sucessfully completed QChem Job') completed_job = True break if not completed_job: - raise InputError('Could not find a successfully completed Qchem job in Qchem output file {0}'.format(self.path)) + raise InputError('Could not find a successfully completed QChem job in QChem output file {0}'.format(self.path)) - #Now look for the geometry. - #Will return the final geometry in the file under Standard Nuclear Orientation. + # Now look for the geometry. + # Will return the final geometry in the file under Standard Nuclear Orientation. geometry_flag = False for i in reversed(xrange(len(log))): line = log[i] if 'Standard Nuclear Orientation' in line: - atom, coord, number = [], [], [] for line in log[(i+3):]: if '------------' not in line: data = line.split() @@ -150,52 +153,29 @@ def loadGeometry(self): if geometry_flag: break + # Assign appropriate mass to each atom in the molecule + for atom1 in atom: + mass1, num1 = get_element_mass(atom1) + mass.append(mass1) + number.append(num1) coord = numpy.array(coord, numpy.float64) - # Assign appropriate mass to each atom in molecule - # These values were taken from "Atomic Weights and Isotopic Compositions" v3.0 (July 2010) from NIST - - mass = [0]*len(atom) - - for i in range(len(atom)): - if atom[i] == 'H': - mass[i] = 1.00782503207 - number.append('1') - elif atom[i] == 'C': - mass[i] = 12.0 - number.append('6') - elif atom[i] == 'N': - mass[i] = 14.0030740048 - number.append('7') - elif atom[i] == 'O': - mass[i] = 15.99491461956 - number.append('8') - elif atom[i] == 'P': - mass[i] = 30.97376163 - number.append('15') - elif atom[i] == 'S': - mass[i] = 31.97207100 - number.append('16') - elif atom[i] == 'Cl': - mass[i] = 35.4527 - number.append('17') - else: - raise NotImplementedError('Atomic atom {0:d} not yet supported in loadGeometry().'.format(atom[i])) number = numpy.array(number, numpy.int) + mass = numpy.array(mass, numpy.float64) if len(number) == 0 or len(coord) == 0 or len(mass) == 0: - raise InputError('Unable to read the numbers and types of atoms from Qchem output file {0}'.format(self.path)) + raise InputError('Unable to read atoms from QChem geometry output file {0}'.format(self.path)) + return coord, number, mass - + def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, symfromlog=None, label=''): """ - Load the molecular degree of freedom data from a output file created as - the result of a Qchem "Freq" calculation. As - Qchem's guess of the external symmetry number is not always correct, - you can use the `symmetry` parameter to substitute your own value; if - not provided, the value in the Qchem output file will be adopted. + Load the molecular degree of freedom data from an output file created as the result of a + QChem "Freq" calculation. As QChem's guess of the external symmetry number is not always correct, + you can use the `symmetry` parameter to substitute your own value; + if not provided, the value in the QChem output file will be adopted. """ - modes = []; freq = []; mmass = []; rot = [] + modes = []; freq = []; mmass = []; rot = []; inertia = [] + unscaled_frequencies = [] E0 = 0.0 -# symmetry = 1 f = open(self.path, 'r') line = f.readline() while line != '': @@ -208,7 +188,6 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym # The rest of the data we want is in the Thermochemistry section of the output elif 'VIBRATIONAL ANALYSIS' in line: modes = [] - line = f.readline() while line != '': @@ -226,48 +205,32 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym elif len(line.split()) == 3: frequencies.extend([float(d) for d in line.split()[-2:]]) elif len(line.split()) == 2: - frequencies.extend([float(d) for d in line.split()[-1:]]) + frequencies.extend([float(d) for d in line.split()[-1:]]) line = f.readline() line = f.readline() # If there is an imaginary frequency, remove it if frequencies[0] < 0.0: frequencies = frequencies[1:] - + + unscaled_frequencies = frequencies vibration = HarmonicOscillator(frequencies=(frequencies,"cm^-1")) - #modes.append(vibration) + # modes.append(vibration) freq.append(vibration) # Read molecular mass for external translational modes elif 'Molecular Mass:' in line: mass = float(line.split()[2]) translation = IdealGasTranslation(mass=(mass,"amu")) - #modes.append(translation) + # modes.append(translation) mmass.append(translation) # Read moments of inertia for external rotational modes, given in atomic units elif 'Eigenvalues --' in line: inertia = [float(d) for d in line.split()[-3:]] - # If the first eigenvalue is 0, the rotor is linear - symmetry = 1 - if inertia[0] == 0.0: - inertia.remove(0.0) - logging.debug('inertia is {}'.format(str(inertia))) - for i in range(2): - inertia[i] *= (constants.a0/1e-10)**2 - inertia = numpy.sqrt(inertia[0]*inertia[1]) - rotation = LinearRotor(inertia=(inertia,"amu*angstrom^2"), symmetry=symmetry) - rot.append(rotation) - else: - for i in range(3): - inertia[i] *= (constants.a0/1e-10)**2 - rotation = NonlinearRotor(inertia=(inertia,"amu*angstrom^2"), symmetry=symmetry) - #modes.append(rotation) - rot.append(rotation) - - # Read Qchem's estimate of the external rotational symmetry number, which may very well be incorrect - elif 'Rotational Symmetry Number is' in line: # and symmetry is None: - if symfromlog is True: - symmetry = int(float(line.split()[4])) - logging.debug('rot sym is {}'.format(str(symmetry))) + + # Read QChem's estimate of the external rotational symmetry number, which may very well be incorrect + elif 'Rotational Symmetry Number is' in line and symfromlog: + symmetry = int(float(line.split()[-1])) + logging.debug('Rotational Symmetry read from QChem is {}'.format(str(symmetry))) # Read the next line in the file line = f.readline() @@ -275,111 +238,101 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=1, sym # Read the next line in the file line = f.readline() + if len(inertia): + if symmetry is None: + symmetry = 1 + if inertia[0] == 0.0: + # If the first eigenvalue is 0, the rotor is linear + inertia.remove(0.0) + logging.debug('inertia is {}'.format(str(inertia))) + for i in range(2): + inertia[i] *= (constants.a0 / 1e-10) ** 2 + inertia = numpy.sqrt(inertia[0] * inertia[1]) + rotation = LinearRotor(inertia=(inertia, "amu*angstrom^2"), symmetry=symmetry) + rot.append(rotation) + else: + for i in range(3): + inertia[i] *= (constants.a0 / 1e-10) ** 2 + rotation = NonlinearRotor(inertia=(inertia, "amu*angstrom^2"), symmetry=symmetry) + # modes.append(rotation) + rot.append(rotation) + + inertia = [] + # Close file when finished f.close() modes = mmass + rot + freq - return Conformer(E0=(E0*0.001,"kJ/mol"), modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers) - - def loadEnergy(self,frequencyScaleFactor=1.): + return Conformer(E0=(E0*0.001,"kJ/mol"), modes=modes, spinMultiplicity=spinMultiplicity, + opticalIsomers=opticalIsomers), unscaled_frequencies + + def loadEnergy(self, frequencyScaleFactor=1.): """ - Load the energy in J/mol from a Qchem log file. Only the last energy - in the file is returned. The zero-point energy is *not* included in + Load the energy in J/mol from a QChem log file. Only the last energy + in the file is returned. The zero-point energy is *not* included in the returned value. """ E0 = None - - f = open(self.path, 'r') - line = f.readline() - while line != '': - - if 'Final energy is' in line: - E0 = float(line.split()[3]) * constants.E_h * constants.Na - logging.debug('energy is {}'.format(str(E0))) - -# elif 'Zero point vibrational energy' in line: - #Qchem's ZPE is in kcal/mol -# ZPE = float(line.split()[4]) * 4184 -# scaledZPE = ZPE * frequencyScaleFactor -# print 'ZPE is ' + str(ZPE) - # Read the next line in the file - line = f.readline() - - # Close file when finished - f.close() - - if E0 is not None: - return E0 - else: - raise InputError('Unable to find energy in Qchem output file.') + with open(self.path, 'r') as f: + for line in f: + if 'Final energy is' in line: + E0 = float(line.split()[3]) * constants.E_h * constants.Na + logging.debug('energy is {}'.format(str(E0))) + if E0 is None: + for line in f: + if 'Total energy in the final basis set' in line: + E0 = float(line.split()[8]) * constants.E_h * constants.Na + logging.debug('energy is {}'.format(str(E0))) + if E0 is None: + raise InputError('Unable to find energy in QChem output file.') + return E0 def loadZeroPointEnergy(self,frequencyScaleFactor=1.): """ - Load the unscaled zero-point energy in J/mol from a Qchem output file. + Load the unscaled zero-point energy in J/mol from a QChem output file. """ - ZPE = None - - f = open(self.path, 'r') - line = f.readline() - while line != '': - -# if 'Final energy is' in line: -# E0 = float(line.split()[3]) * constants.E_h * constants.Na -# print 'energy is' + str(E0) - if 'Zero point vibrational energy' in line: - #Qchem's ZPE is in kcal/mol - ZPE = float(line.split()[4]) * 4184 - #scaledZPE = ZPE * frequencyScaleFactor - logging.debug('ZPE is {}'.format(str(ZPE))) - # Read the next line in the file - line = f.readline() - - # Close file when finished - f.close() - + with open(self.path, 'r') as f: + for line in f: + if 'Zero point vibrational energy' in line: + ZPE = float(line.split()[4]) * 4184 # QChem's ZPE is in kcal/mol + # scaledZPE = ZPE * frequencyScaleFactor + logging.debug('ZPE is {}'.format(str(ZPE))) if ZPE is not None: return ZPE else: - raise InputError('Unable to find zero-point energy in Qchem output file.') + raise InputError('Unable to find zero-point energy in QChem output file.') def loadScanEnergies(self): """ - Extract the optimized energies in J/mol from a Qchem log file, e.g. the - result of a Qchem "PES Scan" quantum chemistry calculation. + Extract the optimized energies in J/mol from a QChem log file, e.g. the + result of a QChem "PES Scan" quantum chemistry calculation. """ Vlist = [] angle = [] - f = open(self.path, 'r') - line = f.readline() - while line != '': - if 'Summary of potential scan:' in line: - line = f.readline() - print 'found a sucessfully completed Qchem Job' - while '-----------------' not in line: - # print len(line.split()) - # Vlist.append(float(line.split()[1])) + read = False + with open(self.path, 'r') as f: + for line in f: + if '-----------------' in line: + read = False + if read: values = [float(item) for item in line.split()] angle.append(values[0]) Vlist.append(values[1]) - # Read the next line in the file - line = f.readline() - line = f.readline() - if 'SCF failed to converge' in line: - print 'Qchem Job did not sucessfully complete: SCF failed to converge' - break - # Close file when finished - print ' Assuming', os.path.basename(self.path), 'is the output from a Qchem PES scan...' - f.close() - + if 'Summary of potential scan:' in line: + logging.info('found a sucessfully completed QChem Job') + read = True + elif 'SCF failed to converge' in line: + raise InputError('QChem Job did not sucessfully complete: SCF failed to converge') + logging.info(' Assuming {0} is the output from a QChem PES scan...'.format(os.path.basename(self.path))) Vlist = numpy.array(Vlist, numpy.float64) # check to see if the scanlog indicates that one of your reacting species may not be the lowest energy conformer - checkConformerEnergy(Vlist, self.path) + check_conformer_energy(Vlist, self.path) # Adjust energies to be relative to minimum energy conformer # Also convert units from Hartree/particle to J/mol Vlist -= numpy.min(Vlist) - Vlist *= constants.E_h * constants.Na + Vlist *= constants.E_h * constants.Na angle = numpy.arange(0.0, 2*math.pi+0.00001, 2*math.pi/(len(Vlist)-1), numpy.float64) return Vlist, angle @@ -388,18 +341,14 @@ def loadNegativeFrequency(self): Return the imaginary frequency from a transition state frequency calculation in cm^-1. """ - - f = open(self.path, 'r') - line = f.readline() - while line != '': - # Read imaginary frequency - if ' Frequency:' in line: - frequency = float((line.split()[1])) - break - line = f.readline() - # Close file when finished - f.close() - #Make sure the frequency is imaginary: + frequency = 0 + with open(self.path, 'r') as f: + for line in f: + # Read imaginary frequency + if ' Frequency:' in line: + frequency = float((line.split()[1])) + break + # Make sure the frequency is imaginary: if frequency < 0: return frequency else: diff --git a/rmgpy/cantherm/qchemTest.py b/arkane/qchemTest.py similarity index 72% rename from rmgpy/cantherm/qchemTest.py rename to arkane/qchemTest.py index df6d6e7e86..0c567162b3 100644 --- a/rmgpy/cantherm/qchemTest.py +++ b/arkane/qchemTest.py @@ -32,83 +32,86 @@ import unittest import os -from rmgpy.cantherm.qchem import QchemLog from rmgpy.statmech import Conformer, IdealGasTranslation, LinearRotor, NonlinearRotor, HarmonicOscillator, HinderedRotor import rmgpy.constants as constants from external.wip import work_in_progress + +from arkane.qchem import QChemLog + ################################################################################ + class QChemTest(unittest.TestCase): """ Contains unit tests for the chempy.io.qchem module, used for reading - and writing Qchem files. + and writing QChem files. """ - def testNumberOfAtomsFromQchemLog(self): + def testNumberOfAtomsFromQChemLog(self): """ - Uses a Qchem log files to test that + Uses a QChem log files to test that number of atoms can be properly read. """ - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) self.assertEqual(log.getNumberOfAtoms(), 10) - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) self.assertEqual(log.getNumberOfAtoms(), 2) - def testEnergyFromQchemLog(self): + def testEnergyFromQChemLog(self): """ - Uses a Qchem log files to test that + Uses a QChem log files to test that molecular energies can be properly read. """ - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) self.assertAlmostEqual(log.loadEnergy(), -310896203.5432524, 1e-5) - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) self.assertAlmostEqual(log.loadEnergy(), -297402545.0217114, 1e-5) - def testLoadVibrationsFromQchemLog(self): + def testLoadVibrationsFromQChemLog(self): """ - Uses a Qchem log files to test that + Uses a QChem log files to test that molecular energies can be properly read. - """ - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) - conformer = log.loadConformer(symfromlog=True) + """ + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) self.assertEqual(len(conformer.modes[2]._frequencies.getValue()), 24) self.assertEqual(conformer.modes[2]._frequencies.getValue()[5], 881.79) - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) - conformer = log.loadConformer(symfromlog=True) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) self.assertEqual(len(conformer.modes[2]._frequencies.getValue()), 1) self.assertEqual(conformer.modes[2]._frequencies.getValue(), 2253.16) - def testLoadNpropylModesFromQchemLog(self): + def testLoadNpropylModesFromQChemLog(self): """ - Uses a Qchem log file for npropyl to test that its + Uses a QChem log file for npropyl to test that its molecular modes can be properly read. """ - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) - conformer = log.loadConformer(symfromlog=True) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,IdealGasTranslation)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,NonlinearRotor)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,HarmonicOscillator)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,HinderedRotor)]) == 0) - def testSpinMultiplicityFromQchemLog(self): + def testSpinMultiplicityFromQChemLog(self): """ - Uses a Qchem log file for npropyl to test that its + Uses a QChem log file for npropyl to test that its molecular degrees of freedom can be properly read. """ - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) - conformer = log.loadConformer(symfromlog=True) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','npropyl.out')) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) self.assertEqual(conformer.spinMultiplicity, 2) - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) - conformer = log.loadConformer(symfromlog=True) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) self.assertEqual(conformer.spinMultiplicity, 1) - def testLoadCOModesFromQchemLog(self): + def testLoadCOModesFromQChemLog(self): """ - Uses a Qchem log file for CO to test that its + Uses a QChem log file for CO to test that its molecular degrees of freedom can be properly read. """ - log = QchemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) - conformer = log.loadConformer(symfromlog=True) + log = QChemLog(os.path.join(os.path.dirname(__file__),'data','co.out')) + conformer, unscaled_frequencies = log.loadConformer(symfromlog=True) E0 = log.loadEnergy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode,IdealGasTranslation)]) == 1) diff --git a/rmgpy/cantherm/sensitivity.py b/arkane/sensitivity.py similarity index 96% rename from rmgpy/cantherm/sensitivity.py rename to arkane/sensitivity.py index 049de3b7f7..a3a176ce7a 100644 --- a/rmgpy/cantherm/sensitivity.py +++ b/arkane/sensitivity.py @@ -37,6 +37,7 @@ import logging import string import numpy as np + import rmgpy.quantity as quantity from rmgpy.species import TransitionState from rmgpy.pdep import Configuration @@ -67,6 +68,7 @@ class KineticsSensitivity(object): def __init__(self, job, output_directory): self.job = job self.output_directory = output_directory + self.sensitivity_path = os.path.join(output_directory, 'sensitivity') self.conditions = self.job.sensitivity_conditions self.f_rates = [self.job.reaction.kinetics.getRateCoefficient(condition.value_si) for condition in self.conditions] @@ -110,14 +112,14 @@ def unperturb(self, species): species.conformer.E0.value_si -= self.perturbation.value_si # restore E0 to its original value def save(self): - if not os.path.exists('sensitivity'): - os.mkdir('sensitivity') + if not os.path.exists(self.sensitivity_path): + os.mkdir(self.sensitivity_path) valid_chars = "-_.()<=> %s%s" % (string.ascii_letters, string.digits) reaction_str = '{0} {1} {2}'.format( ' + '.join([reactant.label for reactant in self.job.reaction.reactants]), '<=>', ' + '.join([product.label for product in self.job.reaction.products])) - filename = os.path.join('sensitivity', ''.join(c for c in reaction_str if c in valid_chars) + '.txt') - path = os.path.join(self.output_directory, filename) + filename = ''.join(c for c in reaction_str if c in valid_chars) + '.txt' + path = os.path.join(self.sensitivity_path, filename) with open(path, 'w') as sa_f: sa_f.write("Sensitivity analysis for reaction {0}\n\n" "The semi-normalized sensitivity coefficients are calculated as dln(r)/dE0\n" @@ -199,14 +201,14 @@ def plot(self): ax[i][1].set_xlim([min_sa, max_sa]) plt.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) - if not os.path.exists('sensitivity'): - os.mkdir('sensitivity') + if not os.path.exists(self.sensitivity_path): + os.mkdir(self.sensitivity_path) valid_chars = "-_.()<=> %s%s" % (string.ascii_letters, string.digits) reaction_str = '{0} {1} {2}'.format( ' + '.join([reactant.label for reactant in self.job.reaction.reactants]), '<=>', ' + '.join([product.label for product in self.job.reaction.products])) - filename = os.path.join('sensitivity', ''.join(c for c in reaction_str if c in valid_chars) + '.pdf') - path = os.path.join(self.output_directory, filename) + filename = ''.join(c for c in reaction_str if c in valid_chars) + '.pdf' + path = os.path.join(self.sensitivity_path, filename) plt.savefig(path) plt.close() @@ -235,6 +237,7 @@ class PDepSensitivity(object): def __init__(self, job, output_directory, perturbation): self.job = job self.output_directory = output_directory + self.sensitivity_path = os.path.join(output_directory, 'sensitivity') self.conditions = self.job.sensitivity_conditions self.rates = {} for rxn in self.job.network.netReactions: @@ -371,11 +374,11 @@ def plot(self, wells, transition_states): axis.set_xlim([min_sa, max_sa]) axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) - if not os.path.exists('sensitivity'): - os.mkdir('sensitivity') + if not os.path.exists(self.sensitivity_path): + os.mkdir(self.sensitivity_path) valid_chars = "-_.()<=>+ %s%s" % (string.ascii_letters, string.digits) reaction_str = str(rxn) - filename = os.path.join('sensitivity', ''.join(c for c in reaction_str if c in valid_chars) + '.pdf') - path = os.path.join(self.output_directory, filename) + filename = ''.join(c for c in reaction_str if c in valid_chars) + '.pdf' + path = os.path.join(self.sensitivity_path, filename) plt.savefig(path) plt.close() diff --git a/rmgpy/cantherm/statmech.py b/arkane/statmech.py similarity index 84% rename from rmgpy/cantherm/statmech.py rename to arkane/statmech.py index b3e1fa36f3..e25ac080af 100644 --- a/rmgpy/cantherm/statmech.py +++ b/arkane/statmech.py @@ -42,31 +42,24 @@ from rdkit.Chem import GetPeriodicTable import rmgpy.constants as constants - -from rmgpy.cantherm.output import prettify -from rmgpy.cantherm.gaussian import GaussianLog -from rmgpy.cantherm.molpro import MolproLog -from rmgpy.cantherm.qchem import QchemLog - from rmgpy.species import TransitionState, Species - from rmgpy.statmech.translation import Translation, IdealGasTranslation from rmgpy.statmech.rotation import Rotation, LinearRotor, NonlinearRotor, KRotor, SphericalTopRotor from rmgpy.statmech.vibration import Vibration, HarmonicOscillator from rmgpy.statmech.torsion import Torsion, HinderedRotor, FreeRotor from rmgpy.statmech.conformer import Conformer from rmgpy.exceptions import InputError +from rmgpy.quantity import Quantity -# These are the atoms we currently have enthalpies of formation for -atom_num_dict = {1: 'H', - 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 7: 'N', 8: 'O', 9: 'F', - 11: 'Na', 12: 'Mg', 13: 'Al', 14: 'Si', 15: 'P', 16: 'S', 17: 'Cl', 53: 'I'} - -# Use the RDKit periodic table so we can write symbols for not implemented elements -_rdkit_periodic_table = GetPeriodicTable() +from arkane.output import prettify +from arkane.gaussian import GaussianLog +from arkane.molpro import MolproLog +from arkane.qchem import QChemLog +from arkane.common import symbol_by_number ################################################################################ + class ScanLog(object): """ Represent a text file containing a table of angles and corresponding @@ -167,11 +160,10 @@ def freeRotor(pivots,top,symmetry): class StatMechJob(object): """ - A representation of a CanTherm statistical mechanics job. This job is used + A representation of a Arkane statistical mechanics job. This job is used to compute and save the statistical mechanics information for a single species or transition state. """ - def __init__(self, species, path): self.species = species self.path = path @@ -181,6 +173,8 @@ def __init__(self, species, path): self.applyAtomEnergyCorrections = True self.applyBondEnergyCorrections = True self.atomEnergies = None + self.supporting_info = [self.species.label] + self.bonds = None def execute(self, outputFile=None, plot=False): """ @@ -216,7 +210,7 @@ def load(self): 'FreeRotor': freeRotor, # File formats 'GaussianLog': GaussianLog, - 'QchemLog': QchemLog, + 'QChemLog': QChemLog, 'MolproLog': MolproLog, 'ScanLog': ScanLog, 'Log': Log @@ -230,11 +224,12 @@ def load(self): except (NameError, TypeError, SyntaxError), e: logging.error('The species file {0} was invalid:'.format(path)) raise - - try: - bonds = local_context['bonds'] - except KeyError: - bonds = {} + + if self.bonds is None: + try: + self.bonds = local_context['bonds'] + except KeyError: + self.bonds = {} try: linear = local_context['linear'] @@ -271,15 +266,31 @@ def load(self): except KeyError: raise InputError('Model chemistry {0!r} not found in from dictionary of energy values in species file ' '{1!r}.'.format(self.modelChemistry, path)) + E0_withZPE, E0 = None, None + energyLog = None if isinstance(energy, Log): energy.determine_qm_software(os.path.join(directory, energy.path)) - energy = energy.software_log - if isinstance(energy, (GaussianLog,QchemLog,MolproLog)): - energyLog = energy; E0 = None + energyLog = energy.software_log + elif isinstance(energy, (GaussianLog,QChemLog,MolproLog)): + energyLog = energy energyLog.path = os.path.join(directory, energyLog.path) elif isinstance(energy, float): - energyLog = None; E0 = energy - + E0 = energy + elif isinstance(energy, tuple) and len(energy) == 2: + # this is likely meant to be a quantity object with ZPE already accounted for + energy_temp = Quantity(energy) + E0_withZPE = energy_temp.value_si # in J/mol + elif isinstance(energy, tuple) and len(energy) == 3: + if energy[2] == 'E0': + energy_temp = Quantity(energy[:2]) + E0 = energy_temp.value_si / constants.E_h / constants.Na# convert J/mol to Hartree + elif energy[2] == 'E0-ZPE': + energy_temp = Quantity(energy[:2]) + E0_withZPE = energy_temp.value_si # in J/mol + else: + raise InputError('The third argument for E0 energy value should '\ + 'be E0 (for energy w/o ZPE) or E0-ZPE. Value '\ + 'entered {0}'.format(energy[2])) try: geomLog = local_context['geometry'] except KeyError: @@ -326,14 +337,22 @@ def load(self): ' In order to ensure the geometry and Hessian of {0!r} are defined in consistent coordinate systems' ' for hindered/free rotor projection, either use the frequency log for both geometry and frequency,' ' or remove rotors.'.format(self.species.label,geomLog.path,statmechLog.path)) - elif isinstance(statmechLog, QchemLog): - logging.warning('Qchem log will be used for Hessian of {0!r}. ' + elif isinstance(statmechLog, QChemLog): + logging.warning('QChem log will be used for Hessian of {0!r}. ' 'Please verify that the geometry and Hessian of {0!r} are defined in the same coordinate system'.format(self.species.label)) logging.debug(' Reading molecular degrees of freedom...') - conformer = statmechLog.loadConformer(symmetry=externalSymmetry, spinMultiplicity=spinMultiplicity, - opticalIsomers=opticalIsomers, symfromlog=symfromlog, - label=self.species.label) + conformer, unscaled_frequencies = statmechLog.loadConformer(symmetry=externalSymmetry, + spinMultiplicity=spinMultiplicity, + opticalIsomers=opticalIsomers, + symfromlog=symfromlog, + label=self.species.label) + for mode in conformer.modes: + if isinstance(mode, (LinearRotor, NonlinearRotor)): + self.supporting_info.append(mode) + break + if unscaled_frequencies: + self.supporting_info.append(unscaled_frequencies) if conformer.spinMultiplicity == 0: raise ValueError("Could not read spin multiplicity from log file {0},\n" @@ -346,11 +365,9 @@ def load(self): atoms = {} for atom_num in number: try: - symbol = atom_num_dict[atom_num] + symbol = symbol_by_number[atom_num] except KeyError: - raise Exception( - 'Element {} is not yet supported.'.format(_rdkit_periodic_table.GetElementSymbol(atom_num)) - ) + raise Exception('Could not recognize element number {0}.'.format(atom_num)) atoms[symbol] = atoms.get(symbol, 0) + 1 # Save atoms for use in writing thermo output @@ -362,34 +379,37 @@ def load(self): conformer.mass = (mass,"amu") logging.debug(' Reading energy...') - # The E0 that is read from the log file is without the ZPE and corresponds to E_elec - if E0 is None: - E0 = energyLog.loadEnergy(self.frequencyScaleFactor) - else: - E0 = E0 * constants.E_h * constants.Na # Hartree/particle to J/mol - if not self.applyAtomEnergyCorrections: - logging.warning('Atom corrections are not being used. Do not trust energies and thermo.') - E0 = applyEnergyCorrections(E0, - self.modelChemistry, - atoms, - bonds, - atomEnergies=self.atomEnergies, - applyAtomEnergyCorrections=self.applyAtomEnergyCorrections, - applyBondEnergyCorrections=self.applyBondEnergyCorrections) - ZPE = statmechLog.loadZeroPointEnergy() * self.frequencyScaleFactor - - # The E0_withZPE at this stage contains the ZPE - E0_withZPE = E0 + ZPE - - logging.debug(' Scaling factor used = {0:g}'.format(self.frequencyScaleFactor)) - logging.debug(' ZPE (0 K) = {0:g} kcal/mol'.format(ZPE / 4184.)) - logging.debug(' E0 (0 K) = {0:g} kcal/mol'.format(E0_withZPE / 4184.)) - + if E0_withZPE is None: + # The E0 that is read from the log file is without the ZPE and corresponds to E_elec + if E0 is None: + E0 = energyLog.loadEnergy(self.frequencyScaleFactor) + else: + E0 = E0 * constants.E_h * constants.Na # Hartree/particle to J/mol + if not self.applyAtomEnergyCorrections: + logging.warning('Atom corrections are not being used. Do not trust energies and thermo.') + E0 = applyEnergyCorrections(E0, + self.modelChemistry, + atoms, + self.bonds, + atomEnergies=self.atomEnergies, + applyAtomEnergyCorrections=self.applyAtomEnergyCorrections, + applyBondEnergyCorrections=self.applyBondEnergyCorrections) + ZPE = statmechLog.loadZeroPointEnergy() * self.frequencyScaleFactor + logging.debug('Corrected minimum energy is {0} J/mol'.format(E0)) + # The E0_withZPE at this stage contains the ZPE + E0_withZPE = E0 + ZPE + + logging.debug(' Scaling factor used = {0:g}'.format(self.frequencyScaleFactor)) + logging.debug(' ZPE (0 K) = {0:g} kcal/mol'.format(ZPE / 4184.)) + logging.debug(' E0 (0 K) = {0:g} kcal/mol'.format(E0_withZPE / 4184.)) + conformer.E0 = (E0_withZPE*0.001,"kJ/mol") # If loading a transition state, also read the imaginary frequency if TS: - self.species.frequency = (statmechLog.loadNegativeFrequency() * self.frequencyScaleFactor, "cm^-1") + neg_freq = statmechLog.loadNegativeFrequency() + self.species.frequency = (neg_freq * self.frequencyScaleFactor, "cm^-1") + self.supporting_info.append(neg_freq) # Read and fit the 1D hindered rotors if applicable # If rotors are found, the vibrational frequencies are also @@ -419,7 +439,7 @@ def load(self): Vlist, angle = scanLog.loadScanEnergies() scanLogOutput = ScanLog(os.path.join(directory, '{0}_rotor_{1}.txt'.format(self.species.label, rotorCount+1))) scanLogOutput.save(angle, Vlist) - elif isinstance(scanLog, QchemLog): + elif isinstance(scanLog, QChemLog): scanLog.path = os.path.join(directory, scanLog.path) Vlist, angle = scanLog.loadScanEnergies() scanLogOutput = ScanLog(os.path.join(directory, '{0}_rotor_{1}.txt'.format(self.species.label, rotorCount+1))) @@ -490,7 +510,6 @@ def load(self): self.species.conformer = conformer - def save(self, outputFile): """ Save the results of the statistical mechanics job to the file located @@ -510,7 +529,7 @@ def save(self, outputFile): x = coordinates[i,0] y = coordinates[i,1] z = coordinates[i,2] - f.write('# {0} {1:9.4f} {2:9.4f} {3:9.4f}\n'.format(atom_num_dict[number[i]], x, y, z)) + f.write('# {0} {1:9.4f} {2:9.4f} {3:9.4f}\n'.format(symbol_by_number[number[i]], x, y, z)) string = 'conformer(label={0!r}, E0={1!r}, modes={2!r}, spinMultiplicity={3:d}, opticalIsomers={4:d}'.format( self.species.label, @@ -568,6 +587,7 @@ def plotHinderedRotor(self, angle, Vlist, cosineRotor, fourierRotor, rotor, roto ################################################################################ + def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, atomEnergies=None, applyAtomEnergyCorrections=True, applyBondEnergyCorrections=False): """ @@ -579,7 +599,7 @@ def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, atom calculations using corresponding model chemistries. The assumption for the multiplicity of each atom is: - H singlet, C triplet, O triplet, N quartet, S triplet, P quartet. + H doublet, C triplet, O triplet, N quartet, S triplet, P quartet, I doublet. `bonds` is a dictionary associating bond types with the number of that bond in the molecule. @@ -591,14 +611,14 @@ def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, # Values in millihartree are also available (with fewer significant figures) from table VII of http://dx.doi.org/10.1063/1.473182 # Iodine SOC calculated as a weighted average of the electronic spin splittings of the lowest energy state. The splittings are # obtained from Huber, K.P.; Herzberg, G., Molecular Spectra and Molecular Structure. IV. Constants of Diatomic Molecules, Van Nostrand Reinhold Co., 1979 - SOC = {'H':0.0, 'N':0.0, 'O': -0.000355, 'C': -0.000135, 'S': -0.000893, 'P': 0.0, 'I':-0.011547226,} + SOC = {'H': 0.0, 'N': 0.0, 'O': -0.000355, 'C': -0.000135, 'S': -0.000893, 'P': 0.0, 'I':-0.011547226,} # Step 1: Reference all energies to a model chemistry-independent basis # by subtracting out that model chemistry's atomic energies # All model chemistries here should be lower-case because the user input is changed to lower-case if atomEnergies is None: # Note: If your model chemistry does not include spin orbit coupling, you should add the corrections to the energies here - if modelChemistry == 'cbs-qb3': + if modelChemistry.startswith('cbs-qb3'): # only check start of string to allow different bond corrections (see below) atomEnergies = {'H':-0.499818 + SOC['H'], 'N':-54.520543 + SOC['N'], 'O':-74.987624+ SOC['O'], 'C':-37.785385+ SOC['C'], 'P':-340.817186+ SOC['P'], 'S': -397.657360+ SOC['S']} elif modelChemistry == 'm06-2x/cc-pvtz': atomEnergies = {'H':-0.498135 + SOC['H'], 'N':-54.586780 + SOC['N'], 'O':-75.064242+ SOC['O'], 'C':-37.842468+ SOC['C'], 'P':-341.246985+ SOC['P'], 'S': -398.101240+ SOC['S']} @@ -645,12 +665,12 @@ def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, elif modelChemistry == 'ccsd(t)/aug-cc-pvtz(-pp)': atomEnergies = {'H':-0.499821176024 + SOC['H'], 'O':-74.96738492 + SOC['O'], 'C':-37.77385697 + SOC['C'], 'S':-397.6461604 + SOC['S'], 'I':-294.7958443 + SOC['I']} - elif modelChemistry == 'ccsd(t)-f12/aug-cc-pvdz': - atomEnergies = {'H':-0.499459066131 + SOC['H'], 'N':-54.524279516472 + SOC['N'], 'O':-74.992097308083+ SOC['O'], 'C':-37.786694171716+ SOC['C']} + elif modelChemistry == 'ccsd(t)-f12/aug-cc-pvdz': # note that all atom corrections but S are fitted, the correction for S is calculated + atomEnergies = {'H':-0.499459066131 + SOC['H'], 'N':-54.524279516472 + SOC['N'], 'O':-74.992097308083+ SOC['O'], 'C':-37.786694171716+ SOC['C'], 'S':-397.648733842400 + SOC['S']} elif modelChemistry == 'ccsd(t)-f12/aug-cc-pvtz': - atomEnergies = {'H':-0.499844820798 + SOC['H'], 'N':-54.527419359906 + SOC['N'], 'O':-75.000001429806+ SOC['O'], 'C':-37.788504810868+ SOC['C']} + atomEnergies = {'H':-0.499844820798 + SOC['H'], 'N':-54.527419359906 + SOC['N'], 'O':-75.000001429806 + SOC['O'], 'C':-37.788504810868 + SOC['C'], 'S':-397.666903000231 + SOC['S']} elif modelChemistry == 'ccsd(t)-f12/aug-cc-pvqz': - atomEnergies = {'H':-0.499949526073 + SOC['H'], 'N':-54.529569719016 + SOC['N'], 'O':-75.004026586610+ SOC['O'], 'C':-37.789387892348+ SOC['C']} + atomEnergies = {'H':-0.499949526073 + SOC['H'], 'N':-54.529569719016 + SOC['N'], 'O':-75.004026586610+ SOC['O'], 'C':-37.789387892348+ SOC['C'], 'S':-397.671214204994 + SOC['S']} elif modelChemistry == 'b-ccsd(t)-f12/cc-pvdz-f12': @@ -702,6 +722,11 @@ def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, atomEnergies = {'H':-0.500426155, 'C':-37.850331697831, 'O':-75.0535872748806, 'S':-398.100820107242} elif modelChemistry == 'b3lyp/6-311+g(3df,2p)': # Calculated atomic energies atomEnergies = {'H':-0.502155915123 + SOC['H'], 'C':-37.8574709934 + SOC['C'], 'N':-54.6007233609 + SOC['N'], 'O':-75.0909131284 + SOC['O'], 'P':-341.281730319 + SOC['P'], 'S':-398.134489850 + SOC['S']} + elif modelChemistry == 'wb97x-d/aug-cc-pvtz': + atomEnergies = {'H':-0.502803+ SOC['H'], 'N':-54.585652+ SOC['N'], 'O':-75.068286+ SOC['O'], 'C':-37.842014+ SOC['C']} + + elif modelChemistry == 'MRCI+Davidson/aug-cc-pV(T+d)Z': # Calculated atomic energies (unfitted) + atomEnergies = {'H':-0.49982118 + SOC['H'], 'C':-37.78321274 + SOC['C'], 'N':-54.51729444 + SOC['N'], 'O':-74.97847534 + SOC['O'], 'S':-397.6571654 + SOC['S']} else: raise Exception('Unknown model chemistry "{}".'.format(modelChemistry)) @@ -716,34 +741,45 @@ def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, ) # Step 2: Atom energy corrections to reach gas-phase reference state - # Experimental enthalpy of formation at 0 K + # Experimental enthalpy of formation at 0 K, 1 bar for gas phase # See Gaussian thermo whitepaper at http://www.gaussian.com/g_whitepap/thermo.htm) - # Note: these values are relatively old and some improvement may be possible by using newer values, particularly for carbon + # Note: These values are relatively old and some improvement may be possible by using newer values + # (particularly for carbon). # However, care should be taken to ensure that they are compatible with the BAC values (if BACs are used) - # The enthalpies listed here should correspond to the allowed elements in atom_num_dict - # Iodine value is from Cox, J. D., Wagman, D. D., and Medvedev, V. A., CODATA Key Values for Thermodynamics, Hemisphere Publishing Corp., New York, 1989. - atomHf = {'H': 51.63, - 'Li': 37.69, 'Be': 76.48, 'B': 136.2, 'C': 169.98, 'N': 112.53, 'O': 58.99, 'F': 18.47, - 'Na': 25.69, 'Mg': 34.87, 'Al': 78.23, 'Si': 106.6, 'P': 75.42, 'S': 65.66, 'Cl': 28.59, 'I':24.04} + # He, Ne, K, Ca, Ti, Cu, Zn, Ge, Br, Kr, Rb, Ag, Cd, Sn, I, Xe, Cs, Hg, and Pb are taken from CODATA + # Codata: Cox, J. D., Wagman, D. D., and Medvedev, V. A., CODATA Key Values for Thermodynamics, Hemisphere + # Publishing Corp., New York, 1989. (http://www.science.uwaterloo.ca/~cchieh/cact/tools/thermodata.html) + atom_hf = {'H': 51.63, 'He': -1.481, + 'Li': 37.69, 'Be': 76.48, 'B': 136.2, 'C': 169.98, 'N': 112.53, 'O': 58.99, 'F': 18.47, 'Ne': -1.481, + 'Na': 25.69, 'Mg': 34.87, 'Al': 78.23, 'Si': 106.6, 'P': 75.42, 'S': 65.66, 'Cl': 28.59, + 'K': 36.841, 'Ca': 41.014, 'Ti': 111.2, 'Cu': 79.16, 'Zn': 29.685, 'Ge': 87.1, 'Br': 25.26, 'Kr': -1.481, + 'Rb': 17.86, 'Ag': 66.61, 'Cd': 25.240, 'Sn': 70.50, 'I': 24.04, 'Xe': -1.481, + 'Cs': 16.80, 'Hg': 13.19, 'Pb': 15.17} # Thermal contribution to enthalpy Hss(298 K) - Hss(0 K) reported by Gaussian thermo whitepaper - # This will be subtracted from the corresponding value in atomHf to produce an enthalpy used in calculating the enthalpy of formation at 298 K - atomThermal = {'H': 1.01, - 'Li': 1.1, 'Be': 0.46, 'B': 0.29, 'C': 0.25, 'N': 1.04, 'O': 1.04, 'F': 1.05, - 'Na': 1.54, 'Mg': 1.19, 'Al': 1.08, 'Si': 0.76, 'P': 1.28, 'S': 1.05, 'Cl': 1.1, 'I':1.48} + # This will be subtracted from the corresponding value in atom_hf to produce an enthalpy used in calculating + # the enthalpy of formation at 298 K + atom_thermal = {'H': 1.01, 'He': 1.481, + 'Li': 1.1, 'Be': 0.46, 'B': 0.29, 'C': 0.25, 'N': 1.04, 'O': 1.04, 'F': 1.05, 'Ne': 1.481, + 'Na': 1.54, 'Mg': 1.19, 'Al': 1.08, 'Si': 0.76, 'P': 1.28, 'S': 1.05, 'Cl': 1.1, + 'K': 1.481, 'Ca': 1.481, 'Ti': 1.802, 'Cu': 1.481, 'Zn': 1.481, 'Ge': 1.768, 'Br': 1.481, 'Kr': 1.481, + 'Rb': 1.481, 'Ag': 1.481, 'Cd': 1.481, 'Sn': 1.485, 'I': 1.481, 'Xe': 1.481, + 'Cs': 1.481, 'Hg': 1.481, 'Pb': 1.481} # Total energy correction used to reach gas-phase reference state - # Note: Spin orbit coupling no longer included in these energies, since some model chemistries include it automatically - atomEnthalpyCorrections = {element: atomHf[element] - atomThermal[element] for element in atomHf} + # Note: Spin orbit coupling is no longer included in these energies, since some model chemistries include it + # automatically + atom_enthalpy_corrections = {element: atom_hf[element] - atom_thermal[element] for element in atom_hf} for symbol, count in atoms.items(): - if symbol in atomEnthalpyCorrections: - E0 += count * atomEnthalpyCorrections[symbol] * 4184. + if symbol in atom_enthalpy_corrections: + E0 += count * atom_enthalpy_corrections[symbol] * 4184. else: - raise Exception('Element "{}" is not supported.'.format(symbol)) + raise Exception('Element "{0}" is not yet supported in Arkane.' + ' To include it, add its experimental heat of formation'.format(symbol)) if applyBondEnergyCorrections: # Step 3: Bond energy corrections - #The order of elements in the bond correction label is important and should follow the order specified below: - #'C', 'N', 'O', 'S', 'P', and 'H' - #Use ``-``/``=``/``#`` to denote a single/double/triple bond, respectively. + # The order of elements in the bond correction label is important and should follow the order specified below: + # 'C', 'N', 'O', 'S', 'P', and 'H' + # Use ``-``/``=``/``#`` to denote a single/double/triple bond, respectively. # For example, ``'C=N'`` is correct while ``'N=C'`` is incorrect bondEnergies = {} # 'S-H', 'C-S', 'C=S', 'S-S', 'O-S', 'O=S', 'O=S=O' taken from http://hdl.handle.net/1721.1/98155 (both for @@ -768,6 +804,13 @@ def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, 'C=N': -0.30, 'C#N': -1.33, 'N-O': 1.01, 'N_O': -0.03, 'N=O': -0.26, 'N-H': 0.06, 'N-N': -0.23, 'N=N': -0.37, 'N#N': -0.64,} elif modelChemistry == 'cbs-qb3': + bondEnergies = { + 'C-H': -0.11, 'C-C': -0.30, 'C=C': -0.08, 'C#C': -0.64, 'O-H' : 0.02, 'C-O': 0.33, 'C=O': 0.55, # Table IX: Petersson GA (1998) J. of Chemical Physics, DOI: 10.1063/1.477794 + 'N-H': -0.42, 'C-N': -0.13, 'C#N': -0.89, 'C-F': 0.55, 'C-Cl': 1.29, 'S-H': 0.0, 'C-S': 0.43, 'O=S': -0.78, + 'N=O': 1.11, 'N-N': -1.87, 'N=N': -1.58, 'N-O': 0.35, #Table 2: Ashcraft R (2007) J. Phys. Chem. B; DOI: 10.1021/jp073539t + 'N#N': -2.0, 'O=O': -0.2, 'H-H': 1.1, # Unknown source + } + elif modelChemistry == 'cbs-qb3-paraskevas': # NOTE: The Paraskevas corrections are inaccurate for non-oxygenated hydrocarbons, and may do poorly in combination with the Petersson corrections bondEnergies = { 'C-C': -0.495,'C-H': -0.045,'C=C': -0.825,'C-O': 0.378,'C=O': 0.743,'O-H': -0.423, #Table2: Paraskevas, PD (2013). Chemistry-A European J., DOI: 10.1002/chem.201301381 'C#C': -0.64, 'C#N': -0.89, 'C-S': 0.43, 'O=S': -0.78,'S-H': 0.0, 'C-N': -0.13, 'C-Cl': 1.29, 'C-F': 0.55, # Table IX: Petersson GA (1998) J. of Chemical Physics, DOI: 10.1063/1.477794 @@ -791,13 +834,13 @@ def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, return E0 + class Log(object): """ Represent a general log file. The attribute `path` refers to the location on disk of the log file of interest. A method is provided to determine whether it is a Gaussian, Molpro, or QChem type. """ - def __init__(self, path): self.path = path @@ -815,7 +858,7 @@ def determine_qm_software(self, fullpath): break elif 'qchem' in line.lower(): f.close() - software_log = QchemLog(fullpath) + software_log = QChemLog(fullpath) break elif 'molpro' in line.lower(): f.close() @@ -1047,12 +1090,14 @@ def projectRotors(conformer, F, rotors, linear, TS): return numpy.sqrt(eig[-Nvib:]) / (2 * math.pi * constants.c * 100) + def assign_frequency_scale_factor(model_chemistry): """ Assign the frequency scaling factor according to the model chemistry. Refer to https://comp.chem.umn.edu/freqscale/index.html for future updates of these factors """ freq_dict = {'cbs-qb3': 0.99, # J. Chem. Phys. 1999, 110, 2822–2827 + 'cbs-qb3-paraskevas': 0.99, # 'g3': , 'm08so/mg3s*': 0.983, # DOI: 10.1021/ct100326h, taken as 'M08-SO/MG3S' 'm06-2x/cc-pvtz': 0.955, # http://cccbdb.nist.gov/vibscalejust.asp @@ -1063,7 +1108,7 @@ def assign_frequency_scale_factor(model_chemistry): # 'ccsd(t)-f12/cc-pvdz-f12_h-tz': , # 'ccsd(t)-f12/cc-pvdz-f12_h-qz': , 'ccsd(t)-f12/cc-pvdz-f12': 0.979, # http://cccbdb.nist.gov/vibscalejust.asp, taken as 'ccsd(t)/cc-pvdz' - 'ccsd(t)-f12/cc-pvtz-f12': 0.984, # DOI: 10.1021/ct100326h, taken as 'CCSD(T)-F12a/cc-pVTZ-F12' + 'ccsd(t)-f12/cc-pvtz-f12': 0.984, # Taken from https://comp.chem.umn.edu/freqscale/version3b2.htm as CCSD(T)-F12a/cc-pVTZ-F12 'ccsd(t)-f12/cc-pvqz-f12': 0.970, # http://cccbdb.nist.gov/vibscalejust.asp, taken as 'ccsd(t)/cc-pvqz' 'ccsd(t)-f12/cc-pcvdz-f12': 0.971, # http://cccbdb.nist.gov/vibscalejust.asp, taken as 'ccsd(t)/cc-pcvdz' 'ccsd(t)-f12/cc-pcvtz-f12': 0.966, @@ -1095,6 +1140,7 @@ def assign_frequency_scale_factor(model_chemistry): # 'bmk/6-311g(2d,d,p)': , 'b3lyp/6-31g**': 0.961, # http://cccbdb.nist.gov/vibscalejust.asp 'b3lyp/6-311+g(3df,2p)': 0.967, # http://cccbdb.nist.gov/vibscalejust.asp + 'wb97x-d/aug-cc-pvtz': 0.974, # Taken from https://comp.chem.umn.edu/freqscale/version3b2.htm as ωB97X-D/maug-cc-pVTZ } scale_factor = freq_dict.get(model_chemistry.lower(), 1) if scale_factor == 1: diff --git a/rmgpy/cantherm/thermo.py b/arkane/thermo.py similarity index 85% rename from rmgpy/cantherm/thermo.py rename to arkane/thermo.py index 2d7f468f6e..c605118cbc 100644 --- a/rmgpy/cantherm/thermo.py +++ b/arkane/thermo.py @@ -39,14 +39,11 @@ import string import rmgpy.constants as constants -from rmgpy.cantherm.output import prettify - from rmgpy.statmech.translation import Translation, IdealGasTranslation from rmgpy.statmech.rotation import Rotation, LinearRotor, NonlinearRotor, KRotor, SphericalTopRotor from rmgpy.statmech.vibration import Vibration, HarmonicOscillator from rmgpy.statmech.torsion import Torsion, HinderedRotor from rmgpy.statmech.conformer import Conformer - from rmgpy.thermo.thermodata import ThermoData from rmgpy.thermo.nasa import NASAPolynomial, NASA from rmgpy.thermo.wilhoit import Wilhoit @@ -55,11 +52,14 @@ from rmgpy.molecule import Molecule from rmgpy.molecule.util import retrieveElementCount +from arkane.output import prettify + ################################################################################ + class ThermoJob(object): """ - A representation of a CanTherm thermodynamics job. This job is used to + A representation of an Arkane thermodynamics job. This job is used to compute and save the thermodynamics information for a single species. """ @@ -91,6 +91,10 @@ def generateThermo(self): logging.info('Generating {0} thermo model for {1}...'.format(self.thermoClass, species)) + if species.thermo is not None: + logging.info("Thermo already generated for species {}. Skipping thermo generation.".format(species)) + return None + Tlist = numpy.arange(10.0, 3001.0, 10.0, numpy.float64) Cplist = numpy.zeros_like(Tlist) H298 = 0.0 @@ -153,11 +157,14 @@ def save(self, outputFile): f.write('# (K) (cal/mol*K) (kcal/mol) (cal/mol*K) (kcal/mol)\n') f.write('# =========== =========== =========== =========== ===========\n') for T in [300,400,500,600,800,1000,1500,2000,2400]: - Cp = species.getThermoData().getHeatCapacity(T) / 4.184 - H = species.getThermoData().getEnthalpy(T) / 4184. - S = species.getThermoData().getEntropy(T) / 4.184 - G = species.getThermoData().getFreeEnergy(T) / 4184. - f.write('# {0:11g} {1:11.3f} {2:11.3f} {3:11.3f} {4:11.3f}\n'.format(T, Cp, H, S, G)) + try: + Cp = species.getThermoData().getHeatCapacity(T) / 4.184 + H = species.getThermoData().getEnthalpy(T) / 4184. + S = species.getThermoData().getEntropy(T) / 4.184 + G = species.getThermoData().getFreeEnergy(T) / 4184. + f.write('# {0:11g} {1:11.3f} {2:11.3f} {3:11.3f} {4:11.3f}\n'.format(T, Cp, H, S, G)) + except ValueError: + logging.debug("Valid thermo for {0} is outside range for temperature {1}".format(species,T)) f.write('# =========== =========== =========== =========== ===========\n') string = 'thermo(label={0!r}, thermo={1!r})'.format(species.label, species.getThermoData()) @@ -176,7 +183,7 @@ def save(self, outputFile): elementCounts = {'C': 0, 'H': 0} else: elementCounts = {'C': 0, 'H': 0} - string = writeThermoEntry(species, elementCounts=elementCounts, verbose=False) + string = writeThermoEntry(species, elementCounts=elementCounts, verbose=True) f.write('{0}\n'.format(string)) f.close() @@ -215,14 +222,17 @@ def plot(self, outputDirectory): conformer = self.species.conformer thermo = self.species.getThermoData() for i in range(Tlist.shape[0]): - Cplist[i] = conformer.getHeatCapacity(Tlist[i]) - Slist[i] = conformer.getEntropy(Tlist[i]) - Hlist[i] = (conformer.getEnthalpy(Tlist[i]) + conformer.E0.value_si) * 0.001 - Glist[i] = Hlist[i] - Tlist[i] * Slist[i] * 0.001 - Cplist1[i] = thermo.getHeatCapacity(Tlist[i]) - Slist1[i] = thermo.getEntropy(Tlist[i]) - Hlist1[i] = thermo.getEnthalpy(Tlist[i]) * 0.001 - Glist1[i] = thermo.getFreeEnergy(Tlist[i]) * 0.001 + try: + Cplist[i] = conformer.getHeatCapacity(Tlist[i]) + Slist[i] = conformer.getEntropy(Tlist[i]) + Hlist[i] = (conformer.getEnthalpy(Tlist[i]) + conformer.E0.value_si) * 0.001 + Glist[i] = Hlist[i] - Tlist[i] * Slist[i] * 0.001 + Cplist1[i] = thermo.getHeatCapacity(Tlist[i]) + Slist1[i] = thermo.getEntropy(Tlist[i]) + Hlist1[i] = thermo.getEnthalpy(Tlist[i]) * 0.001 + Glist1[i] = thermo.getFreeEnergy(Tlist[i]) * 0.001 + except (ValueError,AttributeError): + continue fig = plt.figure(figsize=(10,8)) fig.suptitle('{0}'.format(self.species.label)) @@ -249,9 +259,11 @@ def plot(self, outputDirectory): fig.subplots_adjust(left=0.10, bottom=0.08, right=0.95, top=0.95, wspace=0.35, hspace=0.20) - if not os.path.exists('plots'): - os.mkdir('plots') + plot_path = os.path.join(outputDirectory, 'plots') + + if not os.path.exists(plot_path): + os.mkdir(plot_path) valid_chars = "-_.()<=> %s%s" % (string.ascii_letters, string.digits) - filename = os.path.join('plots', ''.join(c for c in self.species.label if c in valid_chars) + '.pdf') - plt.savefig(os.path.join(outputDirectory, filename)) + filename = ''.join(c for c in self.species.label if c in valid_chars) + '.pdf' + plt.savefig(os.path.join(plot_path, filename)) plt.close() diff --git a/deploy.sh b/deploy.sh index d590d4f3d7..bb77a0f9fc 100644 --- a/deploy.sh +++ b/deploy.sh @@ -2,54 +2,30 @@ set -e # exit with nonzero exit code if anything fails -openssl aes-256-cbc -K $encrypted_244ac3091cff_key -iv $encrypted_244ac3091cff_iv -in deploy_key.enc -out deploy_key -d - echo 'Travis Build Dir: '$TRAVIS_BUILD_DIR if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - DEPLOY_BRANCH=$TRAVIS_PULL_REQUEST + DEPLOY_BRANCH=$TRAVIS_PULL_REQUEST else DEPLOY_BRANCH=$TRAVIS_BRANCH fi # Deploy built site to this branch -echo Deploy branch: $DEPLOY_BRANCH +echo "DEPLOY_BRANCH: $DEPLOY_BRANCH" -# SSH URL of the RMG/RMG-tests repo that is pushed to: -REPO=git@github.com:ReactionMechanismGenerator/RMG-tests.git +# URL for the official RMG-tests repository +REPO=https://${GH_TOKEN}@github.com/ReactionMechanismGenerator/RMG-tests.git if [ -n "$TRAVIS_BUILD_ID" ]; then - # - # Set the following environment variables in the travis configuration (.travis.yml) - # - # DEPLOY_BRANCH - The only branch that Travis should deploy from - # GIT_NAME - The Git user name - # GIT_EMAIL - The Git user email - # - GIT_NAME="Travis Deploy" - GIT_EMAIL="travisci@rmg.edu" - echo DEPLOY_BRANCH: $DEPLOY_BRANCH - echo GIT_NAME: $GIT_NAME - echo GIT_EMAIL: $GIT_EMAIL if [ "$TRAVIS_BRANCH" != "$DEPLOY_BRANCH" ]; then echo "Travis should only deploy from the DEPLOY_BRANCH ($DEPLOY_BRANCH) branch" exit 0 - else - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then - echo "Travis should not deploy from pull requests" - exit 0 - else - - # use the decrypted deploy SSH key as - # the credentials to push to the RMG-tests repo: - chmod 600 deploy_key - eval `ssh-agent -s` - ssh-add deploy_key - git config --global user.name "$GIT_NAME" - git config --global user.email "$GIT_EMAIL" - fi + elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then + echo "Travis should not deploy from pull requests" + exit 0 fi + fi # create a temporary folder: @@ -76,6 +52,3 @@ git commit --allow-empty -m rmgpy-$REV # push to the branch to the RMG/RMG-tests repo: git push -f $REPO $RMGTESTSBRANCH > /dev/null - -# kill ssh-agent if neccessary -ssh-agent -k \ No newline at end of file diff --git a/deploy_key.enc b/deploy_key.enc deleted file mode 100644 index bd526028dc..0000000000 Binary files a/deploy_key.enc and /dev/null differ diff --git a/documentation/Makefile b/documentation/Makefile index b241233498..39e259974e 100644 --- a/documentation/Makefile +++ b/documentation/Makefile @@ -12,7 +12,7 @@ PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest setup_github_pages publish +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest setup_github_pages publish travis_setup help: @echo "Please use \`make ' where is one of" @@ -50,6 +50,11 @@ else # Prompt for a commit message cd $(BUILDDIR)/html; git add -A .; git commit; git push official gh-pages endif +travis_setup: +# This target is intended to be used when automatically compiling documentation with Travis + @rm -rf $(BUILDDIR)/html + @git clone --single-branch --branch gh-pages --origin official https://${GH_TOKEN}@github.com/ReactionMechanismGenerator/RMG-Py.git $(BUILDDIR)/html + clean: # set aside the git repository info used to push pages to github mkdir build_temp diff --git a/documentation/RMG-Py_API_Reference.pdf b/documentation/RMG-Py_API_Reference.pdf index c57ed8b1c9..8db2629889 100644 Binary files a/documentation/RMG-Py_API_Reference.pdf and b/documentation/RMG-Py_API_Reference.pdf differ diff --git a/documentation/RMG-Py_and_CanTherm_Documentation.pdf b/documentation/RMG-Py_and_Arkane_Documentation.pdf similarity index 65% rename from documentation/RMG-Py_and_CanTherm_Documentation.pdf rename to documentation/RMG-Py_and_Arkane_Documentation.pdf index 7e24841085..35565dde82 100644 Binary files a/documentation/RMG-Py_and_CanTherm_Documentation.pdf and b/documentation/RMG-Py_and_Arkane_Documentation.pdf differ diff --git a/documentation/source/_templates/index.html b/documentation/source/_templates/index.html index 4b220a9ecb..aea63a5899 100644 --- a/documentation/source/_templates/index.html +++ b/documentation/source/_templates/index.html @@ -16,7 +16,7 @@

Reaction Mechanism Generator Documentation

- CanTherm is developed and distributed as part of RMG-Py, but can be used as a stand-alone + Arkane is developed and distributed as part of RMG-Py, but can be used as a stand-alone application for Thermochemistry, Transition State Theory, and Master Equation chemical kinetics calculations.

@@ -50,12 +50,12 @@

Quick reference guide:

RMG website resources (no download needed) - make transition state theory calculations - Run Cantherm with the Canterm User's Guide + create mechanisms automatically + Download and run RMG, see the RMG User's Guide - create mechanisms automatically - Download RMG with the RMG User's Guide + make transition state theory calculations + Download RMG and run Arkane, see the Arkane User's Guide post an issue with RMG @@ -73,8 +73,8 @@

Parts of the documentation:

- +