├── .gitignore ├── HEADER ├── LICENSE ├── MANIFEST.in ├── README ├── cleancode.sh ├── cleanfiles.sh ├── doc ├── Makefile ├── common.py ├── conf.py ├── ig.rst ├── index.rst ├── papers.rst ├── rg.rst ├── tu.rst ├── ug.rst ├── updatelibdoc.py └── vl.rst ├── quickff ├── __init__.py ├── cost.py ├── data │ ├── __init__.py │ ├── quickffrc │ ├── systems │ │ ├── H2 │ │ │ ├── __init__.py │ │ │ ├── gaussian.fchk │ │ │ └── gaussian_mbis.h5 │ │ ├── __init__.py │ │ ├── amoniak │ │ │ ├── __init__.py │ │ │ ├── gaussian.fchk │ │ │ └── gaussian_mbis.h5 │ │ ├── benzene │ │ │ ├── __init__.py │ │ │ ├── gaussian.fchk │ │ │ └── gaussian_mbis.h5 │ │ ├── clean_h5.py │ │ ├── ethane │ │ │ ├── __init__.py │ │ │ ├── gaussian.fchk │ │ │ └── gaussian_mbis.h5 │ │ ├── ethanol │ │ │ ├── __init__.py │ │ │ ├── gaussian.fchk │ │ │ └── gaussian_mbis.h5 │ │ ├── ethene │ │ │ ├── __init__.py │ │ │ ├── gaussian.fchk │ │ │ └── gaussian_mbis.h5 │ │ ├── methane │ │ │ ├── __init__.py │ │ │ ├── gaussian.fchk │ │ │ └── gaussian_mbis.h5 │ │ ├── uio66-zr-brick │ │ │ ├── __init__.py │ │ │ └── system.chk │ │ └── water │ │ │ ├── __init__.py │ │ │ ├── gaussian.fchk │ │ │ └── gaussian_mbis.h5 │ └── uff.prm ├── io.py ├── log.py ├── paracontext.py ├── perturbation.py ├── program.py ├── reference.py ├── scripts.py ├── settings.py ├── tests │ ├── __init__.py │ ├── common.py │ ├── test_examples.py │ ├── test_reference.py │ └── test_valence.py ├── tools.py └── valence.py ├── scripts ├── qff-input-ei.py └── qff.py ├── setup.py └── updatesite.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | build 3 | doc/_build 4 | doc/system*.chk 5 | doc/pars*.txt 6 | trajectory-* 7 | share/tutorials/water/system*.chk 8 | share/tutorials/water/pars*.txt 9 | updateheaders.py 10 | .gitignore 11 | -------------------------------------------------------------------------------- /HEADER: -------------------------------------------------------------------------------- 1 | QuickFF is a code to quickly derive accurate force fields from ab initio input. 2 | Copyright (C) 2012 - 2019 Louis Vanduyfhuys 3 | Steven Vandenbrande , 4 | Jelle Wieme , 5 | Toon Verstraelen , Center for Molecular Modeling 6 | (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 7 | stated. 8 | 9 | This file is part of QuickFF. 10 | 11 | QuickFF is free software; you can redistribute it and/or 12 | modify it under the terms of the GNU General Public License 13 | as published by the Free Software Foundation; either version 3 14 | of the License, or (at your option) any later version. 15 | 16 | QuickFF is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, see 23 | 24 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README 2 | include LICENSE 3 | include quickff/data/* 4 | include quickff/data/systems/*.* 5 | include quickff/data/systems/*/*.* 6 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | QuickFF is a pythonic code to easily derive fully flexible force fields from ab 2 | initio training data. The intended audience is very broad, one does not require 3 | much force field experience to generate reliable force fields for molecular 4 | systems. 5 | 6 | More information including an installation guide and user manual can be found at 7 | http://molmod.github.io/QuickFF/ 8 | 9 | QuickFF is distributed as open source software under the conditions of the GPL 10 | license version 3. Read the file COPYING for more details, or visit 11 | http://www.gnu.org/licenses/ 12 | -------------------------------------------------------------------------------- /cleancode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo Cleaning python code in \'`pwd`\' and subdirectories 3 | for file in `find quickff scripts *.py | egrep '(\.py$)|(\.c$)|(\.h$)|(\.pxd$)|(\.pyx$)|(\.rst$)|(^scripts/)'`; do 4 | echo "Cleaning $file" 5 | sed -i -e $'s/\t/ /' ${file} 6 | sed -i -e $'s/[ \t]\+$//' ${file} 7 | #sed -i -e $'s/^# --$/#--/' ${file} 8 | #sed -i -e $'s/^\/\/ --$/\/\/--/' ${file} 9 | sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' ${file} 10 | #./updateheaders.py ${file} 11 | done 12 | exit 0 13 | -------------------------------------------------------------------------------- /cleanfiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | for i in $(find quickff | egrep "\.pyc$|\.py~$|\.pyc~$|\.bak$|\.so$") ; do rm -v ${i}; done 3 | for i in $(find quickff/tests | egrep "\.pyc$|\.py~$|\.pyc~$|\.bak$|\.so$") ; do rm -v ${i}; done 4 | for i in $(find doc | egrep "\.pyc$|\.py~$|\.pyc~$|\.bak$|\.so$") ; do rm -v ${i}; done 5 | for i in $(find share/systems | egrep "\.pdf$|\.xyz$|\.txt$|\.chk$|\.pps$|\.zip$|\.log$") ; do rm -v ${i}; done 6 | 7 | (cd doc; make clean) 8 | rm -vr dist 9 | rm -vr build 10 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = a4 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | cd ../share/validation/water; rm pars_*.txt system*.chk *.png; cd ../../../doc 44 | cd ../share/validation/benzene; rm pars_*.txt system*.chk *.png; cd ../../../doc 45 | cd ../share/tutorials/water; rm trajectory-* pars_*.txt system*.chk; cd ../../../doc 46 | cd ../share/tutorials/benzene; rm trajectory-* pars_*.txt system*.chk; cd ../../../doc 47 | 48 | html: 49 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 50 | @echo 51 | mkdir -p _static/water _static/benzene 52 | cp ../share/validation/water/trajectory-*.png _static/water/. 53 | cp ../share/validation/benzene/trajectory-*.png _static/benzene/. 54 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 55 | 56 | dirhtml: 57 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 58 | @echo 59 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 60 | 61 | singlehtml: 62 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 63 | @echo 64 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 65 | 66 | pickle: 67 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 68 | @echo 69 | @echo "Build finished; now you can process the pickle files." 70 | 71 | json: 72 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 73 | @echo 74 | @echo "Build finished; now you can process the JSON files." 75 | 76 | htmlhelp: 77 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 78 | @echo 79 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 80 | ".hhp project file in $(BUILDDIR)/htmlhelp." 81 | 82 | qthelp: 83 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 84 | @echo 85 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 86 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 87 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/QuickFF.qhcp" 88 | @echo "To view the help file:" 89 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/QuickFF.qhc" 90 | 91 | devhelp: 92 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 93 | @echo 94 | @echo "Build finished." 95 | @echo "To view the help file:" 96 | @echo "# mkdir -p $$HOME/.local/share/devhelp/QuickFF" 97 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/QuickFF" 98 | @echo "# devhelp" 99 | 100 | epub: 101 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 102 | @echo 103 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 104 | 105 | latex: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo 108 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 109 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 110 | "(use \`make latexpdf' here to do that automatically)." 111 | 112 | latexpdf: 113 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 114 | @echo "Running LaTeX files through pdflatex..." 115 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 116 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 117 | 118 | text: 119 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 120 | @echo 121 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 122 | 123 | man: 124 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 125 | @echo 126 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 127 | 128 | texinfo: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo 131 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 132 | @echo "Run \`make' in that directory to run these through makeinfo" \ 133 | "(use \`make info' here to do that automatically)." 134 | 135 | info: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo "Running Texinfo files through makeinfo..." 138 | make -C $(BUILDDIR)/texinfo info 139 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 140 | 141 | gettext: 142 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 143 | @echo 144 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 145 | 146 | changes: 147 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 148 | @echo 149 | @echo "The overview file is in $(BUILDDIR)/changes." 150 | 151 | linkcheck: 152 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 153 | @echo 154 | @echo "Link check complete; look for any errors in the above output " \ 155 | "or in $(BUILDDIR)/linkcheck/output.txt." 156 | 157 | doctest: 158 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 159 | @echo "Testing of doctests in the sources finished, look at the " \ 160 | "results in $(BUILDDIR)/doctest/output.txt." 161 | -------------------------------------------------------------------------------- /doc/common.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2015 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Toon Verstraelen , Center for Molecular Modeling 6 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 7 | # stated. 8 | # 9 | # This file is part of QuickFF. 10 | # 11 | # QuickFF is free software; you can redistribute it and/or 12 | # modify it under the terms of the GNU General Public License 13 | # as published by the Free Software Foundation; either version 3 14 | # of the License, or (at your option) any later version. 15 | # 16 | # QuickFF is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, see 23 | # 24 | #-- 25 | 26 | 27 | import os 28 | 29 | 30 | __all__ = ['write_if_changed'] 31 | 32 | 33 | def write_if_changed(fn, s_new): 34 | if os.path.isfile(fn): 35 | # read the entire file 36 | with open(fn) as f: 37 | s_old = f.read() 38 | if s_new == s_old: 39 | print 'File %s needs no update. Skipping.' % fn 40 | return 41 | 42 | # write the new file to dis 43 | print 'Writing new or updated %s' % fn 44 | with open(fn, 'w') as f: 45 | f.write(s_new) 46 | -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Toon Verstraelen , Center for Molecular Modeling 6 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 7 | # stated. 8 | # 9 | # This file is part of QuickFF. 10 | # 11 | # QuickFF is free software; you can redistribute it and/or 12 | # modify it under the terms of the GNU General Public License 13 | # as published by the Free Software Foundation; either version 3 14 | # of the License, or (at your option) any later version. 15 | # 16 | # QuickFF is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, see 23 | # 24 | #-- 25 | 26 | import sys, os 27 | 28 | # If extensions (or modules to document with autodoc) are in another directory, 29 | # add these directories to sys.path here. If the directory is relative to the 30 | # documentation root, use os.path.abspath to make it absolute, like shown here. 31 | #sys.path.insert(0, os.path.abspath('.')) 32 | 33 | # -- General configuration ----------------------------------------------------- 34 | 35 | # If your documentation needs a minimal Sphinx version, state it here. 36 | #needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be extensions 39 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 40 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.imgmath', 'sphinx.ext.viewcode', 'sphinxcontrib.programoutput'] 41 | 42 | # Add any paths that contain templates here, relative to this directory. 43 | templates_path = ['_templates'] 44 | 45 | # The suffix of source filenames. 46 | source_suffix = '.rst' 47 | 48 | # The encoding of source files. 49 | #source_encoding = 'utf-8-sig' 50 | 51 | # The master toctree document. 52 | master_doc = 'index' 53 | 54 | # General information about the project. 55 | project = u'QuickFF' 56 | copyright = u'2019, Louis Vanduyfhuys, Center for Molecular Modeling, Ghent University' 57 | 58 | # The version info for the project you're documenting, acts as replacement for 59 | # |version| and |release|, also used in various other places throughout the 60 | # built documents. 61 | # 62 | # The short X.Y version. 63 | version = '2.2' 64 | # The full version, including alpha/beta/rc tags. 65 | release = '2.2.4' 66 | 67 | # The language for content autogenerated by Sphinx. Refer to documentation 68 | # for a list of supported languages. 69 | #language = None 70 | 71 | # There are two options for replacing |today|: either, you set today to some 72 | # non-false value, then it is used: 73 | #today = '' 74 | # Else, today_fmt is used as the format for a strftime call. 75 | #today_fmt = '%B %d, %Y' 76 | 77 | # List of patterns, relative to source directory, that match files and 78 | # directories to ignore when looking for source files. 79 | exclude_patterns = ['_build'] 80 | 81 | # The reST default role (used for this markup: `text`) to use for all documents. 82 | #default_role = None 83 | 84 | # If true, '()' will be appended to :func: etc. cross-reference text. 85 | #add_function_parentheses = True 86 | 87 | # If true, the current module name will be prepended to all description 88 | # unit titles (such as .. function::). 89 | #add_module_names = True 90 | 91 | # If true, sectionauthor and moduleauthor directives will be shown in the 92 | # output. They are ignored by default. 93 | #show_authors = False 94 | 95 | # The name of the Pygments (syntax highlighting) style to use. 96 | pygments_style = 'sphinx' 97 | 98 | # A list of ignored prefixes for module index sorting. 99 | #modindex_common_prefix = [] 100 | 101 | 102 | # -- Options for HTML output --------------------------------------------------- 103 | 104 | # The theme to use for HTML and HTML Help pages. See the documentation for 105 | # a list of builtin themes. 106 | html_theme = 'sphinx_rtd_theme' #'default' 107 | html_theme_path = ["_themes", ] 108 | 109 | # Theme options are theme-specific and customize the look and feel of a theme 110 | # further. For a list of options available for each theme, see the 111 | # documentation. 112 | #html_theme_options = { 113 | # 'stickysidebar': True, 114 | # 'relbarbgcolor': '#223300', 115 | # 'relbartextcolor': '#f7ffe6', 116 | # 'sidebarbgcolor': '#ebebe0', 117 | # 'sidebartextcolor': '#194d19', 118 | # 'sidebarlinkcolor': '#267326', 119 | # 'headbgcolor': '#f5f5f0', 120 | # 'headtextcolor': '#223300', 121 | # 'bodyfont': , 122 | # 'headfont': , 123 | #} 124 | 125 | html_theme_options = { 126 | 'canonical_url': '', 127 | 'analytics_id': '', 128 | 'logo_only': False, 129 | 'display_version': True, 130 | 'prev_next_buttons_location': 'bottom', 131 | 'style_external_links': False, 132 | # 'vcs_pageview_mode': '', 133 | # Toc options 134 | 'collapse_navigation': False, 135 | 'sticky_navigation': False, 136 | 'navigation_depth': 4, 137 | 'includehidden': True, 138 | 'titles_only': False 139 | } 140 | 141 | html_logo = "quickff_logo_trans_small.png" 142 | 143 | # Add any paths that contain custom themes here, relative to this directory. 144 | #html_theme_path = [] 145 | 146 | # The name for this set of Sphinx documents. If None, it defaults to 147 | # " v documentation". 148 | #html_title = None 149 | 150 | # A shorter title for the navigation bar. Default is the same as html_title. 151 | #html_short_title = None 152 | 153 | # The name of an image file (relative to this directory) to place at the top 154 | # of the sidebar. 155 | #html_logo = None 156 | 157 | # The name of an image file (within the static path) to use as favicon of the 158 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 159 | # pixels large. 160 | #html_favicon = None 161 | 162 | # Add any paths that contain custom static files (such as style sheets) here, 163 | # relative to this directory. They are copied after the builtin static files, 164 | # so a file named "default.css" will overwrite the builtin "default.css". 165 | html_static_path = ['_static'] 166 | 167 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 168 | # using the given strftime format. 169 | #html_last_updated_fmt = '%b %d, %Y' 170 | 171 | # If true, SmartyPants will be used to convert quotes and dashes to 172 | # typographically correct entities. 173 | #html_use_smartypants = True 174 | 175 | # Custom sidebar templates, maps document names to template names. 176 | #html_sidebars = {} 177 | 178 | # Additional templates that should be rendered to pages, maps page names to 179 | # template names. 180 | #html_additional_pages = {} 181 | 182 | # If false, no module index is generated. 183 | #html_domain_indices = True 184 | 185 | # If false, no index is generated. 186 | #html_use_index = True 187 | 188 | # If true, the index is split into individual pages for each letter. 189 | #html_split_index = False 190 | 191 | # If true, links to the reST sources are added to the pages. 192 | #html_show_sourcelink = True 193 | 194 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 195 | #html_show_sphinx = True 196 | 197 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 198 | #html_show_copyright = True 199 | 200 | # If true, an OpenSearch description file will be output, and all pages will 201 | # contain a tag referring to it. The value of this option must be the 202 | # base URL from which the finished HTML is served. 203 | #html_use_opensearch = '' 204 | 205 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 206 | #html_file_suffix = None 207 | 208 | # Output file base name for HTML help builder. 209 | htmlhelp_basename = 'QuickFFdoc' 210 | 211 | 212 | # -- Options for LaTeX output -------------------------------------------------- 213 | 214 | latex_elements = { 215 | # The paper size ('letterpaper' or 'a4paper'). 216 | 'papersize': 'a4paper', 217 | 218 | # The font size ('10pt', '11pt' or '12pt'). 219 | 'pointsize': '11pt', 220 | 221 | # Additional stuff for the LaTeX preamble. 222 | 'preamble': '', 223 | } 224 | 225 | # Grouping the document tree into LaTeX files. List of tuples 226 | # (source start file, target name, title, author, documentclass [howto/manual]). 227 | latex_documents = [ 228 | ('index', 'QuickFF.tex', u'QuickFF Documentation', 229 | u'Louis Vanduyfhuys', 'manual'), 230 | ] 231 | 232 | # The name of an image file (relative to this directory) to place at the top of 233 | # the title page. 234 | latex_logo = 'quickff_logo.png' 235 | 236 | # For "manual" documents, if this is true, then toplevel headings are parts, 237 | # not chapters. 238 | #latex_use_parts = False 239 | 240 | # If true, show page references after internal links. 241 | #latex_show_pagerefs = False 242 | 243 | # If true, show URL addresses after external links. 244 | #latex_show_urls = False 245 | 246 | # Documents to append as an appendix to all manuals. 247 | #latex_appendices = [] 248 | 249 | # If false, no module index is generated. 250 | #latex_domain_indices = True 251 | 252 | 253 | # -- Options for manual page output -------------------------------------------- 254 | 255 | # One entry per manual page. List of tuples 256 | # (source start file, name, description, authors, manual section). 257 | man_pages = [ 258 | ('index', 'quickff', u'QuickFF Documentation', 259 | [u'Louis Vanduyfhuys'], 1) 260 | ] 261 | 262 | # If true, show URL addresses after external links. 263 | #man_show_urls = False 264 | 265 | 266 | # -- Options for Texinfo output ------------------------------------------------ 267 | 268 | # Grouping the document tree into Texinfo files. List of tuples 269 | # (source start file, target name, title, author, 270 | # dir menu entry, description, category) 271 | texinfo_documents = [ 272 | ('index', 'QuickFF', u'QuickFF Documentation', 273 | u'Louis Vanduyfhuys', 'QuickFF', 'One line description of project.', 274 | 'Miscellaneous'), 275 | ] 276 | 277 | # Documents to append as an appendix to all manuals. 278 | #texinfo_appendices = [] 279 | 280 | # If false, no module index is generated. 281 | #texinfo_domain_indices = True 282 | 283 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 284 | #texinfo_show_urls = 'footnote' 285 | 286 | 287 | # -- Options for autodoc ------------------------------------------------------- 288 | 289 | # also print __init__ method documentation for classes 290 | autoclass_content='both' 291 | -------------------------------------------------------------------------------- /doc/ig.rst: -------------------------------------------------------------------------------- 1 | .. _seclab_ig: 2 | 3 | Installation Guide 4 | ################## 5 | 6 | Dependencies 7 | ************ 8 | 9 | MolMod dependency 10 | ================= 11 | 12 | `MolMod `_ is a Python library used by most 13 | Python programs developed at the CMM. It must be installed before QuickFF can 14 | be used or installed. Installation and download instructions can be found in the 15 | `molmod documentation `_. 16 | The instructions below only work if the MolMod package is installed. 17 | 18 | Yaff dependency 19 | =============== 20 | 21 | `Yaff `_ is a pythonic force-field (FF) 22 | code used at the Center for Molecular Modeling (CMM) to test-drive new FF models. 23 | Yaff is required to run QuickFF, the implementation of each force field term is 24 | based on the implementation in Yaff. For this version of QuickFF, it is required 25 | to install the development version in the 26 | `master `_ 27 | branch of Yaff available at github. It can be installed by cloning the git 28 | repository using the git command:: 29 | 30 | git clone https://github.com/molmod/yaff.git 31 | 32 | Alternatively, a zip file can be 33 | downloaded from the online repository for the branch 34 | `master `_. 35 | After extracting the zip file, Yaff can be installed by following the 36 | instructions given in the 37 | `yaff documentation `_. The 38 | instructions below only work if the Yaff package is installed. 39 | 40 | External dependencies 41 | ===================== 42 | 43 | Some software packages should be installed before QuickFF can be installed or 44 | used. It is recommended to use the software package management of your Linux 45 | distribution to install these dependencies. 46 | 47 | The following software must be installed: 48 | 49 | * Python >= 2.7 (including the development files): http://www.python.org/ 50 | * Numpy >= 1.0: http://numpy.scipy.org/ 51 | * Scipy >= 0.14: http://www.scipy.org/ 52 | * h5py >= 2.0.0: http://code.google.com/p/h5py/ 53 | * matplotlib >= 1.0.0: http://matplotlib.sourceforge.net/ 54 | 55 | To run the python tests, it is necessary to install the `Nose 56 | `_ package. Most Linux distributions 57 | can install this software with just a single terminal command. 58 | 59 | * Ubuntu 12.4 and later:: 60 | 61 | sudo apt-get install python-numpy python-scipy python-h5py python-matplotlib python-nose 62 | 63 | * Fedora 17 and later:: 64 | 65 | sudo yum install numpy scipy h5py python-matplotlib python-nose 66 | 67 | Finally, to be able to run QuickFF in parallel on multiple cores, the Python 68 | package `Scoop `_ needs to be installed. To 69 | download and install Scoop (version 0.6.0.final), run the following commands 70 | 71 | * Ubuntu 12.4 and later:: 72 | 73 | wget 'https://scoop.googlecode.com/files/scoop-0.6.0.final.tar.gz' 74 | tar -xvzf scoop-0.6.0.final.tar.gz 75 | cd scoop-0.6.0.final 76 | python setup.py install 77 | 78 | 79 | Downloading QuickFF 80 | ******************* 81 | 82 | Stable release 83 | ============== 84 | 85 | A stable release of the second generation of QuickFF, which includes all 86 | features described on this website, can be downloaded from: 87 | 88 | http://users.ugent.be/~lvduyfhu/QuickFF-2.2.2.tar.gz 89 | 90 | Previous versions available for download can be found below: 91 | 92 | http://users.ugent.be/~lvduyfhu/QuickFF-2.2.0.tar.gz 93 | 94 | http://users.ugent.be/~lvduyfhu/QuickFF-2.1.3.tar.gz 95 | 96 | http://users.ugent.be/~lvduyfhu/QuickFF-2.1.2.tar.gz 97 | 98 | http://users.ugent.be/~lvduyfhu/QuickFF-2.1.0.tar.gz 99 | 100 | 101 | Choose a suitable directory, e.g. ``~/build``, download and unpack the archive:: 102 | 103 | mkdir -p ~/build 104 | cd ~/build 105 | wget http://users.ugent.be/~lvduyfhu/QuickFF-2.2.1.tar.gz 106 | tar -xvzf QuickFF-2.2.1.tar.gz 107 | cd QuickFF-2.2.1 108 | 109 | 110 | Latest development version (experts only) 111 | ========================================= 112 | 113 | The latest development version of QuickFF can only be downloaded using Git. 114 | This also allows you to upload your own changes to QuickFF. Git is free and 115 | open-source distributed revision control system to easily handle programming 116 | projects shared between several people. Further information about git (including 117 | downloads and tutorials) can be found `here `_. The 118 | official git URL for QuickFF is http://github.com/molmod/QuickFF . To `clone` 119 | the QuickFF repository, go to your favorite directory for source code, e.g. 120 | ``~/build``, and execute the following commands:: 121 | 122 | git clone git://github.com/molmod/QuickFF.git quickff 123 | cd quickff 124 | 125 | The source code can be updated with the latest patches with the following 126 | command:: 127 | 128 | git pull 129 | 130 | This will also update the version history so that the progress can easily be 131 | tracked. This version history can be visualized using the `gitk` program. This 132 | program can be downloaded with the following command (Ubuntu):: 133 | 134 | sudo apt-get install gitk 135 | 136 | Once, `gitk` is installed, the version history can be visualized by going to the 137 | directory containing the quickff repository and running the command:: 138 | 139 | gitk 140 | 141 | 142 | Installing QuickFF 143 | ****************** 144 | 145 | Once you downloaded the source code and installed all required packages, QuickFF 146 | can be installed. To install QuickFF, simply go to the directory in which you 147 | downloaded the QuickFF source directory and run the following command:: 148 | 149 | python setup.py install 150 | 151 | After the installation is complete, you can test your installation by running 152 | the following commands:: 153 | 154 | cd test 155 | nosetests 156 | 157 | Once all tests are succesfull, you are ready to use QuickFF. 158 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. QuickFF documentation master file, created by 2 | sphinx-quickstart on Mon Feb 10 17:45:25 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to QuickFF! 7 | ################### 8 | 9 | .. figure:: quickff_logo.png 10 | :scale: 30 % 11 | :alt: QuickFF 12 | :align: left 13 | 14 | QuickFF is a Python package developed at the 15 | `Center for Molecular Modeling `_ (CMM) to quickly 16 | derive accurate force fields from ab initio calculations. This website contains 17 | all information on how to install and use QuickFF. A detailed description of the 18 | methodology used by QuickFF to derive the force fields can be found in the 19 | :ref:`corresponding papers `. 20 | 21 | .. toctree:: 22 | :maxdepth:0 23 | 24 | papers.rst 25 | 26 | How to cite QuickFF 27 | ******************* 28 | 29 | If you used QuickFF in your research, please refer to QuickFF as follows: 30 | 31 | L. Vanduyfhuys, S. Vandenbrande, T. Verstraelen, R. Schmid, M. Waroquier, 32 | V. Van Speybroeck, *J. Comput. Chem.*, 2015, 36, 13, 1015-1027 33 | 34 | If you use version 2.x.x or higher, please also refer to the follow-up paper 35 | 36 | L. Vanduyfhuys, S. Vandenbrande, J. Wieme, M. Waroquier, T. Verstraelen, 37 | V. Van Speybroeck, *J. Comput. Chem.*, 2018, 39, 16, 999-1011 38 | 39 | 40 | Installation Guide 41 | ****************** 42 | 43 | QuickFF is developed and tested on modern Linux environments. The installation 44 | instructions given in :ref:`this guide ` are given for a Linux system only. If you want 45 | to use QuickFF on other operating systems such as Windows or OSX, you should 46 | have a minimal computer geek status to get it working. We are always interested 47 | in hearing from your installation adventures. 48 | 49 | .. toctree:: 50 | :maxdepth: 2 51 | 52 | ig.rst 53 | 54 | 55 | User Guide 56 | ********** 57 | 58 | A manual elaborating on how to configure and use QuickFF to construct a force 59 | field from *ab initio* input. 60 | 61 | .. toctree:: 62 | :maxdepth: 2 63 | 64 | ug.rst 65 | 66 | 67 | .. _seclab_tutorials: 68 | 69 | Tutorials 70 | ********* 71 | 72 | A small list of examples illustrating the basic use of QuickFF as is described 73 | in the User Guide: 74 | 75 | .. toctree:: 76 | :maxdepth: 2 77 | 78 | tu.rst 79 | 80 | 81 | Validation 82 | ********** 83 | 84 | Basic validations to test whether the force fields generated by QuickFF for a 85 | number of systems can reproduce the *ab initio* input. 86 | 87 | .. toctree:: 88 | :maxdepth: 2 89 | 90 | vl.rst 91 | 92 | Reference Guide 93 | *************** 94 | 95 | A reference guide generated from the documentation strings in the source code. 96 | It includes an overview of all modules included in QuickFF. This information is 97 | based on the documentation provided in the source code. The reference guide also 98 | includes an overview of the scripts in QuickFF as well as their basic usage and 99 | options. The information below can also be obtained by running the script with 100 | the :option:`--help` option. 101 | 102 | .. toctree:: 103 | :maxdepth: 2 104 | 105 | rg.rst 106 | 107 | 108 | Contact 109 | ******* 110 | 111 | For support and bug reports, please contact us at `louis.vanduyfhuys@ugent.be 112 | `_. 113 | 114 | Indices and tables 115 | ****************** 116 | 117 | * :ref:`genindex` 118 | * :ref:`modindex` 119 | * :ref:`search` 120 | -------------------------------------------------------------------------------- /doc/papers.rst: -------------------------------------------------------------------------------- 1 | .. _seclab_literature: 2 | 3 | QuickFF literature 4 | ################## 5 | 6 | **QuickFF: A Program for a Quick and Easy Derivation of Force Fields for Metal-Organic Frameworks from Ab Initio Input** 7 | 8 | **Authors**: L. Vanduyfhuys, S. Vandenbrande, T. Verstraelen, R. Schmid, M. Waroquier, V. Van Speybroeck 9 | 10 | **Journal**: *Journal of Computational Chemistry*, 2015 11 | 12 | **Volume** 36, **Issue** 13, **Pages** 1015-1027 13 | 14 | .. figure:: toc1.png 15 | :width: 450 16 | :align: right 17 | 18 | QuickFF is a software package to derive accurate force fields for isolated and complex molecular systems in a quick and easy manner. Apart from its general applicability, the program has been designed to generate force fields for metal-organic frameworks in an automated fashion. The force field parameters for the covalent interaction are derived from ab initio data. The mathematical expression of the covalent energy is kept simple to ensure robustness and to avoid fitting deficiencies as much as possible. The user needs to produce an equilibrium structure and a Hessian matrix for one or more building units. Afterwards, a force field is generated for the system using a three-step method implemented in QuickFF. The first two steps of the methodology are designed to minimize correlations among the force field parameters. In the last step the parameters are refined by imposing the force field parameters to reproduce the ab initio Hessian matrix in Cartesian coordinate space as accurate as possible. The method is applied on a set of 1000 organic molecules to show the easiness of the software protocol. To illustrate its application to MOFs, QuickFF is used to determine force fields for MIL-53(Al) and MOF-5. For both materials accurate force fields were already generated in literature but they requested a lot of manual interventions. QuickFF is a tool that can easily be used by anyone with a basic knowledge of performing ab initio calculations. As a result accurate force fields are generated with minimal effort. 19 | 20 | `Access the paper online here `_ 21 | 22 | | 23 | 24 | **Extension of the QuickFF Force Field Protocol for an Improved Accuracy of Structural, Vibrational, Mechanical and Thermal Properties of Metal-Organic Frameworks** 25 | 26 | **Authors**: L. Vanduyfhuys, S. Vandenbrande, J. Wieme, M. Waroquier, T. Verstraelen, V. Van Speybroeck 27 | 28 | **Journal**: *Journal of Computational Chemistry*, 2018 29 | 30 | **Volume** 39, **Issue** 16, **Pages** 999-1011 31 | 32 | .. figure:: toc2.png 33 | :width: 250 34 | :align: left 35 | 36 | QuickFF was originally launched in 2015 to derive accurate force fields for isolated and complex molecular systems in a quick and easy way. Apart from the general applicability, the functionality was especially tested for metal-organic frameworks (MOFs), a class of hybrid materials consisting of organic and inorganic building blocks. Herein, we launch a new release of the QuickFF protocol which includes new major features to predict structural, vibrational, mechanical and thermal properties with greater accuracy, without compromising its robustness and transparant workflow. First, the *ab initio* data necessary for the fitting procedure may now also be derived from periodic models for the molecular system, as opposed to the earlier cluster-based models. This is essential for an accurate description of MOFs with one dimensional metal-oxide chains. Second, cross terms that couple internal coordinates (ICs) and anharmonic contributions for bond and bend terms are implemented. These features are essential for a proper description of vibrational and thermal properties. Third, the fitting scheme was modified to improve robustness and accuracy. The new features are tested on MIL-53(Al), MOF-5, CAU-13 and NOTT-300. As expected, periodic input data is proven to be essential for a correct description of structural, vibrational and thermodynamic properties of MIL-53(Al). Bulk moduli and thermal expansion coefficients of MOF-5 are very accurately reproduced by static and dynamic simulations using the newly derived force fields which include cross terms and anharmonic corrections. For the flexible materials CAU-13 and NOTT-300, the transition pressure is accurately predicted provided cross terms are taken into account. 37 | 38 | `Access the paper online here `_ 39 | -------------------------------------------------------------------------------- /doc/rg.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file is automatically generated. Do not make 3 | changes as these will be overwritten. Rather edit 4 | the docstrings in the source code. 5 | 6 | Reference Guide 7 | ############### 8 | 9 | .. _seclab_rg_modules: 10 | 11 | Modules 12 | ======= 13 | 14 | An overview is provived of all modules included in QuickFF. The information 15 | below is based on the documentation provided in the source code. 16 | 17 | ``quickff.cost`` -- Least-Square cost function for hessian matching 18 | ------------------------------------------------------------------- 19 | 20 | .. automodule:: quickff.cost 21 | :members: 22 | 23 | 24 | ``quickff.io`` -- Input/Ouput methods 25 | ------------------------------------- 26 | 27 | .. automodule:: quickff.io 28 | :members: 29 | 30 | .. _seclab_rg_modules_settings: 31 | 32 | ``quickff.settings`` -- QuickFF configuration settings 33 | ------------------------------------------------------ 34 | 35 | .. automodule:: quickff.settings 36 | :members: 37 | 38 | ``quickff.perturbation`` -- Perturbation trajectories for internal coordinates 39 | ------------------------------------------------------------------------------ 40 | 41 | .. automodule:: quickff.perturbation 42 | :members: 43 | 44 | .. _seclab_rg_modules_program: 45 | 46 | ``quickff.program`` -- Program classes implementing a sequence of fitting steps 47 | ------------------------------------------------------------------------------- 48 | 49 | .. automodule:: quickff.program 50 | :members: 51 | 52 | 53 | ``quickff.reference`` -- Representation of the ab initio reference data 54 | ----------------------------------------------------------------------- 55 | 56 | .. automodule:: quickff.reference 57 | :members: 58 | 59 | .. _seclab_rg_modules_tools: 60 | 61 | ``quickff.tools`` -- Various convenient tools 62 | --------------------------------------------- 63 | 64 | .. automodule:: quickff.tools 65 | :members: 66 | 67 | ``quickff.valence`` -- ValenceFF class storing all valence ff terms 68 | ------------------------------------------------------------------- 69 | 70 | .. automodule:: quickff.valence 71 | :members: 72 | 73 | 74 | .. _seclab_rg_scripts: 75 | 76 | Scripts 77 | ======= 78 | 79 | An overview is provided of the scripts in QuickFF as well as their basic usage 80 | and options. The information below can also be obtained by running the script 81 | with the :option:`--help` option. 82 | 83 | .. _seclab_rg_scripts_qff: 84 | 85 | ``qff.py`` -- Main script to run QuickFF calculation 86 | **************************************************** 87 | 88 | .. program-output:: qff.py --help 89 | 90 | 91 | .. _seclab_rg_scripts_inputei: 92 | 93 | ``qff-input-ei.py`` -- generate Yaff parameter file for electrostatics 94 | ********************************************************************** 95 | 96 | .. program-output:: qff-input-ei.py --help 97 | -------------------------------------------------------------------------------- /doc/tu.rst: -------------------------------------------------------------------------------- 1 | Tutorials 2 | ######### 3 | 4 | Tutorial 1 - Benzene 5 | ******************** 6 | 7 | This tutorial will describe in detail the use of QuickFF by means of the command 8 | line scripts, to generate a force field for benzene. This tutorial assumes that 9 | the following input files are available (examples of such file are provided with 10 | the source code in the directory `share/systems/benzene`): 11 | 12 | * ``gaussian.fchk`` 13 | A Gaussian Formatted Checkpoint file containing the ab initio equilibrium 14 | geometry and ab initio Hessian in equilibrium. This file can be generated 15 | by performing a freq job in Gaussian using your level of theory and basis 16 | set of choice. The following line should be added prior to the route 17 | section (i.e. the lines starting with #):: 18 | 19 | %chk=gaussian.chk 20 | 21 | When the calculation terminated succesfully, make the fchk file using the 22 | following command:: 23 | 24 | formchk gaussian.chk gaussian.fchk 25 | 26 | * ``gaussian_mbis.h5`` 27 | A HDF5 file containing the atomic charges. Such a file can, for example, be 28 | generated using `HORTON `_. If you have HORTON 2.x 29 | installed, the following command will derive the atomic charges in this example from 30 | the wavefunction in the ``gaussian.fchk`` file:: 31 | 32 | horton-wpart.py gaussian.fchk gaussian_mbis.h5 mbis --grid=ultrafine 33 | 34 | To determine 35 | the path in the HDF5 file to these charges, one can use the `h5dump` 36 | command (part of the Linux package `hdf5-tools`):: 37 | 38 | h5dump -n gaussian_mbis.h5 39 | 40 | The output of this command for the gaussian_mbis.h5 file provided in the 41 | directory ``share/tuturials/benzene`` is: 42 | 43 | .. program-output:: h5dump -n gaussian_mbis.h5 44 | :cwd: ../share/tutorials/benzene 45 | 46 | From this output, we can conclude that, for this example, MBIS charges can 47 | be found in the path ``/charges``. 48 | 49 | 50 | Covalent force field without non-bonding terms 51 | ============================================== 52 | 53 | As a first example, we will derive a force field containing only covalent terms. 54 | No electrostatic nor van der Waals interactions will be included in the force 55 | field. Furthermore, we use the :ref:`built-in feature 56 | ` to automatically determine atom types according to 57 | the level `low` (for benzene it does not make any difference which level is 58 | chosen). This can very easily be done using the :ref:`qff.py 59 | ` script (documentation on the available options can be 60 | accessed by `qff.py` :option:`--help`):: 61 | 62 | qff.py --ffatypes=low --suffix=_noei gaussian.fchk 63 | 64 | The script will dump all relevant information to the screen, for this tutorial, 65 | the output is as follows: 66 | 67 | .. program-output:: qff.py --ffatypes=low --suffix=_noei gaussian.fchk 68 | :cwd: ../share/tutorials/benzene 69 | 70 | The logger will dump to following information to the screen (or a file if the 71 | :option:`--logfile` option was used): 72 | 73 | * Machine environment: 74 | This section contains some general information about the machine environment 75 | on which you ran the quickff job. It contains the user name, machine info, 76 | starting time of job, Python version, Numpy version, Scipy versoin, 77 | Matplotlib version, current directory and the command used 78 | to envoke quickff. 79 | 80 | * Routine sequence: 81 | Every task that is performed will be shown in the log output. For example, 82 | the line ``PTGEN Constructing trajectories`` indicates that QuickFF is 83 | busy constructing the perturbation trajectories. As a second example, the 84 | line ``HCEST Estimating force constants from Hessian cost for tasks 85 | HC_FC_DIAG HC_FC_CROSS`` indicates QuickFF is estimating force constants by 86 | means of a least-square fit of the FF Hessian to the AI Hessian for each 87 | term for which the task `HC_FC_DIAG` and `HC_FC_CROSS` was selected. 88 | 89 | * Final force field parameters: 90 | The final FF parameters are shown at the end of the log output. 91 | 92 | * Timings: 93 | Finally, a summary of the timings for several steps during run of the 94 | program is provided. 95 | 96 | The force field parameters were also written to the Yaff parameters file 97 | `pars_yaff_noei.txt`: 98 | 99 | .. program-output:: cat pars_yaff_noei.txt 100 | :cwd: ../share/tutorials/benzene 101 | 102 | 103 | Force field with electrostatics 104 | =============================== 105 | 106 | * Generating Yaff input 107 | First we need to generate the Yaff input file for the electrostatic 108 | contribution to the force field. This is done using the script 109 | :ref:`qff_input-ei.py `. For this tutorial, 110 | we will convert the charges given in the dataset ``/charges`` of the 111 | file ``gaussian_mbis.h5`` for the atoms in gaussian.fchk with atom types 112 | according to the level `medium` and use Gaussian charge distributions:: 113 | 114 | qff-input-ei.py -v --ffatypes=low --gaussian gaussian.fchk gaussian_mbis.h5:charges pars_ei_mbisgauss.txt 115 | 116 | This command dumped the following output to the screen, indicating wheter or 117 | not the atom types are well chosen from the point of view of electrostatics 118 | (see second remark in :ref:`qff-input-ei.py `): 119 | 120 | .. program-output:: qff-input-ei.py -v --ffatypes=low --gaussian gaussian.fchk gaussian_mbis.h5:charges pars_ei_mbisgauss.txt 121 | :cwd: ../share/tutorials/benzene 122 | 123 | Furthermore, the following Yaff parameter (`pars_ei.txt`) file was written: 124 | 125 | .. program-output:: cat pars_ei_mbisgauss.txt 126 | :cwd: ../share/tutorials/benzene 127 | 128 | * Constructing the covalent contribution 129 | Now, we generate a covalent force field on top of the previously derived 130 | electrostatic contribution using the qff.py script:: 131 | 132 | qff.py --ffatype=low --ei=pars_ei_mbisgauss.txt --suffix=_mbisgauss gaussian.fchk 133 | 134 | The logging output for this job is: 135 | 136 | .. program-output:: qff.py --ffatypes=low --ei=pars_ei_mbisgauss.txt --suffix=_mbisgauss gaussian.fchk 137 | :cwd: ../share/tutorials/benzene 138 | 139 | An extra line appeared in the beginning of the log output, i.e. 140 | ``INIT Initializing Yaff force field reference for EI``. This indicates 141 | that an extra reference instance was created to represent the EI 142 | contribution to the force field. Furthermore, the covalent parameters are 143 | almost identical compared to the FF without electrostatics. This is indeed 144 | what we expect due to the charges being so small. 145 | 146 | The force field parameters were also written to the Yaff parameters file 147 | `pars_yaff_mbisgauss.txt`: 148 | 149 | .. program-output:: cat pars_yaff_mbisgauss.txt 150 | :cwd: ../share/tutorials/benzene 151 | 152 | | 153 | 154 | .. _seclab_tu_water: 155 | 156 | Tutorial 2 - Water 157 | ******************** 158 | 159 | In the current tutorial, we will illustrate the usage of QuickFF as a library 160 | by constructing a basic force field for water. In 161 | :ref:`Tutorial 3 `, we will cover the more advanced features 162 | of QuickFF. 163 | 164 | For this tutorial we again assume to have the input files ``gaussian.fchk`` and 165 | ``gaussian_mbis.h5``. We will construct a script (which we will give the name 166 | ``qff-derive.py``) that will read the input files, convert them to data objects 167 | QuickFF can read and implement a small program using QuickFF modules to derive 168 | the force field. These files, together with the expected output, can be found 169 | in ``share/tutorials/water``. 170 | 171 | First, we define the required :ref:`settings <_seclab_ug_settings>` using the 172 | :ref:`Settings <_seclab_rg_modules_settings>` class: 173 | 174 | .. literalinclude:: ../share/tutorials/water/qff-derive.py 175 | :language: python 176 | :lines: 28-30 177 | 178 | Second, we load the input files and convert them to a Yaff 179 | `system `_ 180 | instance and a QuickFF 181 | `SecondOrderTaylor `_ 182 | instance. Therefore, we use routines implemented in the 183 | `fchk `_ 184 | module of MolMod. 185 | 186 | .. literalinclude:: ../share/tutorials/water/qff-derive.py 187 | :language: python 188 | :lines: 32-47 189 | 190 | At this instance, the system does not yet contain force field atom types. To 191 | define these, we could use the `QuickFF feature guess_ffatypes `_. 192 | However, we can also use the `ATSELECT `_ 193 | language of Yaff: 194 | 195 | .. literalinclude:: ../share/tutorials/water/qff-derive.py 196 | :language: python 197 | :lines: 49-54 198 | 199 | The final input we need to parse, is the set of atomic charges. These charges 200 | are read from the dataset ``charges`` in the HDF5 file ``guassian_mbis.h5``. 201 | 202 | .. literalinclude:: ../share/tutorials/water/qff-derive.py 203 | :language: python 204 | :lines: 56-61 205 | 206 | ``scales`` is a list of 4 floats, representing the electrostatic scalings of 1-2, 207 | 1-3, 1-4 and 1-5 pairs. In this case, no scaling is applied to the electrostatic 208 | interactions. ``radii=None`` indicates that point charges are used. 209 | ``Average=True`` indicates that the set of charges are averaged over atoms of the same type. 210 | Finally, ``pbc=[0,0,0]`` indicates that the system is not periodic. The returned 211 | object ``ff_ei`` is an instance of the 212 | `YaffForceField class `_. 213 | 214 | Now we have all required input, and we will write a new Program class, which 215 | will inherits from the 216 | `BaseProgram class `_, 217 | and contain a sequence of instructions that will be executed consequently. In 218 | this case, first a diagonal force field will be constructed (i.e. without any 219 | cross terms), then we will add cross terms and fit the cross terms using a 220 | Hessian least squares fit while keeping the diagonal terms fixed: 221 | 222 | .. literalinclude:: ../share/tutorials/water/qff-derive.py 223 | :language: python 224 | :pyobject: Program 225 | 226 | Finally, we can now setup the program and run it: 227 | 228 | .. literalinclude:: ../share/tutorials/water/qff-derive.py 229 | :language: python 230 | :lines: 63-65 231 | 232 | To summarize, the entire script as well as the logger output is given below. 233 | 234 | .. container:: toggle 235 | 236 | .. container:: header 237 | 238 | **Click to show/hide the entire script** 239 | 240 | .. literalinclude:: ../share/tutorials/water/qff-derive.py 241 | :language: python 242 | 243 | .. container:: toggle 244 | 245 | .. container:: header 246 | 247 | **Click to show/hide the logger output** 248 | 249 | .. program-output:: python qff-derive.py 250 | :cwd: ../share/tutorials/water/ 251 | 252 | | 253 | 254 | .. _seclab_tu_biphenyl: 255 | 256 | Tutorial 3 - Biphenyl 257 | ******************** 258 | 259 | In the current tutorial, we will illustrate advanced features of QuickFF by 260 | constructing a force field for biphenyl. 261 | 262 | COMING SOON 263 | -------------------------------------------------------------------------------- /doc/updatelibdoc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 4 | # Copyright (C) 2012 - 2015 Louis Vanduyfhuys 5 | # Steven Vandenbrande , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | 27 | 28 | import importlib, os 29 | from glob import glob 30 | from cStringIO import StringIO 31 | 32 | from common import write_if_changed 33 | 34 | 35 | def discover(): 36 | # find packages 37 | packages = {'quickff': []} 38 | for fn in glob('../quickff/*/__init__.py'): 39 | subpackage = fn.split('/')[2] 40 | if subpackage == 'tests': 41 | continue 42 | packages['quickff.%s' % subpackage] = [] 43 | # find modules 44 | for package, modules in packages.iteritems(): 45 | stub = package.replace('.', '/') 46 | for fn in glob('../%s/*.py' % stub) + glob('../%s/*.so' % stub): 47 | module = fn.split('/')[-1][:-3] 48 | if module == '__init__': 49 | continue 50 | modules.append(module) 51 | 52 | return packages 53 | 54 | 55 | def get_first_docline(module): 56 | m = importlib.import_module(module) 57 | if m.__doc__ is not None: 58 | lines = m.__doc__.split('\n') 59 | if len(lines) > 0: 60 | return lines[0] 61 | return 'FIXME! Write module docstring.' 62 | 63 | 64 | def underline(line, char, f): 65 | print >> f, line 66 | print >> f, char*len(line) 67 | print >> f 68 | 69 | 70 | def main(): 71 | packages = discover() 72 | 73 | # Write new/updated rst files if needed 74 | fns_rst = [] 75 | for package, modules in sorted(packages.iteritems()): 76 | print package, modules 77 | # write the new file to a StringIO 78 | f = StringIO() 79 | print >> f, '..' 80 | print >> f, ' This file is automatically generated. Do not make ' 81 | print >> f, ' changes as these will be overwritten. Rather edit ' 82 | print >> f, ' the docstrings in the source code.' 83 | print >> f 84 | underline('``%s`` -- %s' % (package, get_first_docline(package)), '#', f) 85 | print >> f 86 | 87 | for module in sorted(modules): 88 | full = package + '.' + module 89 | print >> f, '.. _seclab_rg_%s_%s:' 90 | print >> f 91 | underline('``%s`` -- %s' % (full, get_first_docline(full)), '=', f) 92 | print >> f, '.. automodule::', full 93 | print >> f, ' :members:' 94 | print >> f 95 | print >> f 96 | 97 | # write if the contents have changed 98 | fn_rst = 'rg_%s.rst' % package.replace('.', '_') 99 | fns_rst.append(fn_rst) 100 | write_if_changed(fn_rst, f.getvalue()) 101 | fns_rst.append('rg_qff.rst') 102 | fns_rst.append('rg_qffinputei.rst') 103 | 104 | 105 | # Remove other rst files 106 | for fn_rst in glob('rg_*.rst'): 107 | if fn_rst not in fns_rst: 108 | print 'Removing %s' % fn_rst 109 | os.remove(fn_rst) 110 | 111 | 112 | if __name__ == '__main__': 113 | main() 114 | -------------------------------------------------------------------------------- /doc/vl.rst: -------------------------------------------------------------------------------- 1 | .. _seclab_vl_main: 2 | 3 | Validation 4 | ########## 5 | 6 | Validation methodology 7 | ********************** 8 | 9 | In this section, a force field is constructed using the current version 10 | of QuickFF (i.e. |release|), after which it is tested and evaluated for its 11 | ability to reproduce the *ab initio* input it was fitted to. The force field was 12 | constructed using the QuickFF script :ref:`qff.py `. The 13 | required *ab initio* input is contained in the file ``gaussian.fchk`` and the 14 | electrostatic partitioning in ``gaussian_mbis.h5``. The Yaff parameter file for 15 | the electrostatic contribution is generated using 16 | 17 | qff-input-ei.py -f --ffatypes=low --gaussian gaussian.fchk gaussian_mbis.h5:charges pars_ei_mbisgauss.txt 18 | 19 | The config file containing the settings that are used for the force field is 20 | given by ``config.txt`` and can be viewed below. Furthermore, all required input 21 | files as well as the generated output can be found in the directory 22 | ``share/validation``. 23 | 24 | .. container:: toggle 25 | 26 | .. container:: header 27 | 28 | **Click to show/hide the QuickFF config file used for generating the force field** 29 | 30 | .. include:: ../share/validation/config.txt 31 | :literal: 32 | 33 | To evaluate the performance of the force field, it is applied to perform a basic 34 | geometry optimization followed by a normal mode analysis using Yaff and TAMkin. 35 | Finally, two validations are performed for each system: 36 | 37 | * the force field energy is compared to the *ab initio* energy along the 38 | perturbation trajectories that were constructed by QuickFF. 39 | 40 | * the geometry (i.e. bond lengths, bending angles, dihedral angles and 41 | ut-of-plane distances) and normal mode frequencies as predicted by the force 42 | field are compared with the given *ab initio* input. To this end, the 43 | following statistics are used: 44 | 45 | - Root Mean Square Deviation (RMSD) 46 | 47 | .. math:: 48 | RMSD = \sqrt{\frac{1}{N}\sum_{i=1}^N \left(A_i - F_i\right)^2} 49 | 50 | - Mean Deviation (RMSD) 51 | 52 | .. math:: 53 | MD = \frac{1}{N}\sum_{i=1}^N \left(A_i-F_i\right) 54 | 55 | - Root Mean Square Error (RMSE) 56 | 57 | .. math:: 58 | RMSE = \sqrt{\frac{1}{N}\sum_{i=1}^N \left(A_i-F_i-MD\right)^2} 59 | 60 | These statistics satisfy the condition :math:`RMDS^2=RMSE^2+MD^2`. 61 | 62 | | 63 | | 64 | 65 | .. _seclab_vl_water: 66 | 67 | Validation 1 - water 68 | ********************** 69 | 70 | Force field construction 71 | ======================== 72 | 73 | .. container:: toggle 74 | 75 | .. container:: header 76 | 77 | **Click to show/hide the output of qff-input-ei.py** 78 | 79 | .. program-output:: qff-input-ei.py -v --ffatypes=low --gaussian gaussian.fchk gaussian_mbis.h5:charges pars_ei_mbisgauss.txt 80 | :cwd: ../share/validation/water 81 | 82 | 83 | .. container:: toggle 84 | 85 | .. container:: header 86 | 87 | **Click to show/hide the Yaff parameter file of the electrostatic contribution** 88 | 89 | .. program-output:: cat pars_ei_mbisgauss.txt 90 | :cwd: ../share/validation/water 91 | 92 | 93 | .. container:: toggle 94 | 95 | .. container:: header 96 | 97 | **Click to show/hide the QuickFF log file** 98 | 99 | .. program-output:: qff.py -c ../config.txt gaussian.fchk 100 | :cwd: ../share/validation/water 101 | 102 | 103 | .. container:: toggle 104 | 105 | .. container:: header 106 | 107 | **Click to show/hide the Yaff parameter file of the covalent contribution** 108 | 109 | .. program-output:: cat pars_cov.txt 110 | :cwd: ../share/validation/water 111 | 112 | | 113 | 114 | Force field evaluation 115 | ====================== 116 | 117 | Perturbation trajectories 118 | ------------------------- 119 | 120 | The figures below illustrate the reproduction of the *ab initio* energy along 121 | the constructed perturbation trajectories. For water, there are 3 such 122 | trajectories, two bonds and one bend. 123 | 124 | 125 | * **First O-H bond**: 126 | 127 | .. image:: /_static/water/trajectory-BondHarm-H.O-0_Ehc3.png 128 | :width: 400 129 | :target: /_static/water/trajectory-BondHarm-H.O-0_Ehc3.png 130 | 131 | * **Second O-H bond**: 132 | 133 | .. image:: /_static/water/trajectory-BondHarm-H.O-1_Ehc3.png 134 | :width: 400 135 | :target: /_static/water/trajectory-BondHarm-H.O-1_Ehc3.png 136 | 137 | * **H-O-H bend**: 138 | 139 | .. image:: /_static/water/trajectory-BendAHarm-H.O.H-2_Ehc3.png 140 | :width: 400 141 | :target: /_static/water/trajectory-BendAHarm-H.O.H-2_Ehc3.png 142 | 143 | 144 | Geometry and frequencies 145 | ------------------------ 146 | 147 | .. program-output:: python simulate.py 148 | :cwd: ../share/validation/water 149 | 150 | | 151 | 152 | .. _seclab_vl__static/benzene: 153 | 154 | Validation 2 - benzene 155 | ********************** 156 | 157 | Force field construction 158 | ======================== 159 | 160 | .. container:: toggle 161 | 162 | .. container:: header 163 | 164 | **Click to show/hide the output of qff-input-ei.py** 165 | 166 | .. program-output:: qff-input-ei.py -v --ffatypes=low --gaussian gaussian.fchk gaussian_mbis.h5:charges pars_ei_mbisgauss.txt 167 | :cwd: ../share/validation/benzene 168 | 169 | 170 | .. container:: toggle 171 | 172 | .. container:: header 173 | 174 | **Click to show/hide the Yaff parameter file of the electrostatic contribution** 175 | 176 | .. program-output:: cat pars_ei_mbisgauss.txt 177 | :cwd: ../share/validation/benzene 178 | 179 | 180 | .. container:: toggle 181 | 182 | .. container:: header 183 | 184 | **Click to show/hide the QuickFF log file** 185 | 186 | .. program-output:: qff.py -c ../config.txt gaussian.fchk 187 | :cwd: ../share/validation/benzene 188 | 189 | 190 | .. container:: toggle 191 | 192 | .. container:: header 193 | 194 | **Click to show/hide the Yaff parameter file of the covalent contribution** 195 | 196 | .. program-output:: cat pars_cov.txt 197 | :cwd: ../share/validation/benzene 198 | 199 | | 200 | 201 | Force field evaluation 202 | ====================== 203 | 204 | Perturbation trajectories 205 | ------------------------- 206 | 207 | The figures below illustrate the reproduction of the *ab initio* energy along 208 | the constructed perturbation trajectories. For water, there are 3 such 209 | trajectories, two bonds and one bend. 210 | 211 | 212 | * **C-H bonds**: 213 | 214 | .. image:: /_static/benzene/trajectory-BondHarm-C.H-0_Ehc3.png 215 | :width: 400 216 | :target: /_static/benzene/trajectory-BondHarm-C.H-0_Ehc3.png 217 | 218 | .. image:: /_static/benzene/trajectory-BondHarm-C.H-7_Ehc3.png 219 | :width: 400 220 | :target: /_static/benzene/trajectory-BondHarm-C.H-7_Ehc3.png 221 | 222 | .. image:: ./_static/benzene/trajectory-BondHarm-C.H-8_Ehc3.png 223 | :width: 400 224 | :target: /_static/benzene/trajectory-BondHarm-C.H-8_Ehc3.png 225 | 226 | .. image:: /_static/benzene/trajectory-BondHarm-C.H-9_Ehc3.png 227 | :width: 400 228 | :target: /_static/benzene/trajectory-BondHarm-C.H-9_Ehc3.png 229 | 230 | .. image:: /_static/benzene/trajectory-BondHarm-C.H-10_Ehc3.png 231 | :width: 400 232 | :target: /_static/benzene/trajectory-BondHarm-C.H-10_Ehc3.png 233 | 234 | .. image:: /_static/benzene/trajectory-BondHarm-C.H-11_Ehc3.png 235 | :width: 400 236 | :target: /_static/benzene/trajectory-BondHarm-C.H-11_Ehc3.png 237 | 238 | 239 | * **C-C bonds**: 240 | 241 | .. image:: /_static/benzene/trajectory-BondHarm-C.C-1_Ehc3.png 242 | :width: 400 243 | :target: /_static/benzene/trajectory-BondHarm-C.C-1_Ehc3.png 244 | 245 | .. image:: /_static/benzene/trajectory-BondHarm-C.C-2_Ehc3.png 246 | :width: 400 247 | :target: /_static/benzene/trajectory-BondHarm-C.C-2_Ehc3.png 248 | 249 | .. image:: /_static/benzene/trajectory-BondHarm-C.C-3_Ehc3.png 250 | :width: 400 251 | :target: /_static/benzene/trajectory-BondHarm-C.C-3_Ehc3.png 252 | 253 | .. image:: /_static/benzene/trajectory-BondHarm-C.C-4_Ehc3.png 254 | :width: 400 255 | :target: /_static/benzene/trajectory-BondHarm-C.C-4_Ehc3.png 256 | 257 | .. image:: /_static/benzene/trajectory-BondHarm-C.C-5_Ehc3.png 258 | :width: 400 259 | :target: /_static/benzene/trajectory-BondHarm-C.C-5_Ehc3.png 260 | 261 | .. image:: /_static/benzene/trajectory-BondHarm-C.C-6_Ehc3.png 262 | :width: 400 263 | :target: /_static/benzene/trajectory-BondHarm-C.C-6_Ehc3.png 264 | 265 | 266 | * **C-C-C bends**: 267 | 268 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.C-24_Ehc3.png 269 | :width: 400 270 | :target: /_static/benzene/trajectory-BendAHarm-C.C.C-24_Ehc3.png 271 | 272 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.C-25_Ehc3.png 273 | :width: 400 274 | :target: /_static/benzene/trajectory-BendAHarm-C.C.C-25_Ehc3.png 275 | 276 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.C-26_Ehc3.png 277 | :width: 400 278 | :target: /_static/benzene/trajectory-BendAHarm-C.C.C-26_Ehc3.png 279 | 280 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.C-27_Ehc3.png 281 | :width: 400 282 | :target: /_static/benzene/trajectory-BendAHarm-C.C.C-27_Ehc3.png 283 | 284 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.C-28_Ehc3.png 285 | :width: 400 286 | :target: /_static/benzene/trajectory-BendAHarm-C.C.C-28_Ehc3.png 287 | 288 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.C-29_Ehc3.png 289 | :width: 400 290 | :target: /_static/benzene/trajectory-BendAHarm-C.C.C-29_Ehc3.png 291 | 292 | 293 | * **C-C-H bends**: 294 | 295 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.H-12_Ehc3.png 296 | :width: 400 297 | :target: /_static/benzene/trajectory-BendAHarm-C.C.H-12_Ehc3.png 298 | 299 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.H-13_Ehc3.png 300 | :width: 400 301 | :target: /_static/benzene/trajectory-BendAHarm-C.C.H-13_Ehc3.png 302 | 303 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.H-14_Ehc3.png 304 | :width: 400 305 | :target: /_static/benzene/trajectory-BendAHarm-C.C.H-14_Ehc3.png 306 | 307 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.H-15_Ehc3.png 308 | :width: 400 309 | :target: /_static/benzene/trajectory-BendAHarm-C.C.H-15_Ehc3.png 310 | 311 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.H-16_Ehc3.png 312 | :width: 400 313 | :target: /_static/benzene/trajectory-BendAHarm-C.C.H-16_Ehc3.png 314 | 315 | .. image:: /_static/benzene/trajectory-BendAHarm-C.C.H-17_Ehc3.png 316 | :width: 400 317 | :target: /_static/benzene/trajectory-BendAHarm-C.C.H-17_Ehc3.png 318 | 319 | 320 | * **C-C-H-C out-of-plane distances**: 321 | 322 | .. image:: /_static/benzene/trajectory-Oopdist-C.C.H.C-54_Ehc3.png 323 | :width: 400 324 | :target: /_static/benzene/trajectory-Oopdist-C.C.H.C-54_Ehc3.png 325 | 326 | .. image:: /_static/benzene/trajectory-Oopdist-C.C.H.C-55_Ehc3.png 327 | :width: 400 328 | :target: /_static/benzene/trajectory-Oopdist-C.C.H.C-55_Ehc3.png 329 | 330 | .. image:: /_static/benzene/trajectory-Oopdist-C.C.H.C-56_Ehc3.png 331 | :width: 400 332 | :target: /_static/benzene/trajectory-Oopdist-C.C.H.C-56_Ehc3.png 333 | 334 | .. image:: /_static/benzene/trajectory-Oopdist-C.C.H.C-57_Ehc3.png 335 | :width: 400 336 | :target: /_static/benzene/trajectory-Oopdist-C.C.H.C-57_Ehc3.png 337 | 338 | .. image:: /_static/benzene/trajectory-Oopdist-C.C.H.C-58_Ehc3.png 339 | :width: 400 340 | :target: /_static/benzene/trajectory-Oopdist-C.C.H.C-58_Ehc3.png 341 | 342 | .. image:: /_static/benzene/trajectory-Oopdist-C.C.H.C-59_Ehc3.png 343 | :width: 400 344 | :target: /_static/benzene/trajectory-Oopdist-C.C.H.C-59_Ehc3.png 345 | 346 | 347 | Geometry and frequencies 348 | ------------------------ 349 | 350 | .. program-output:: python simulate.py 351 | :cwd: ../share/validation/benzene 352 | -------------------------------------------------------------------------------- /quickff/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | 27 | '''QuickFF is a code to quickly derive accurate force fields from ab initio input. 28 | ''' 29 | 30 | from yaff import System 31 | from yaff import log as yafflog 32 | yafflog.set_level(yafflog.silent) 33 | 34 | from quickff.reference import * 35 | from quickff.valence import * 36 | from quickff.perturbation import * 37 | from quickff.program import * 38 | from quickff.cost import * 39 | from quickff.io import * 40 | from quickff.tools import * 41 | from quickff.log import * 42 | from quickff.settings import * 43 | from quickff.scripts import * 44 | 45 | import numpy 46 | numpy.set_printoptions(linewidth=170) 47 | -------------------------------------------------------------------------------- /quickff/cost.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | 27 | from __future__ import absolute_import 28 | 29 | from molmod.units import * 30 | 31 | from quickff.tools import boxqp 32 | from quickff.log import log 33 | 34 | import numpy as np 35 | 36 | __all__ = ['HessianFCCost'] 37 | 38 | class HessianFCCost(object): 39 | ''' 40 | A class to implement the least-square cost function to fit the force 41 | field hessian to the ab initio hessian. 42 | ''' 43 | def __init__(self, system, ai, valence, fit_indices, ffrefs=[], do_mass_weighting=True): 44 | ''' 45 | **Arguments** 46 | 47 | system 48 | a Yaff system object 49 | 50 | ai 51 | an instance of the Reference representing the ab initio input 52 | 53 | valence 54 | A ValenceFF object containing all valence terms. 55 | 56 | fit_indices 57 | a list of indices indicating the terms for which the force 58 | constants should be determined. 59 | 60 | **Optional Arguments** 61 | 62 | ffrefs 63 | a list of Reference instances representing possible a priori 64 | determined contributions to the force field (such as eg. 65 | electrostatics and van der Waals) 66 | 67 | do_mass_weighting 68 | 69 | ''' 70 | #initialization 71 | self.init = np.zeros(len(fit_indices), float) 72 | self.upper = np.zeros(len(fit_indices), float)+np.inf 73 | self.lower = np.zeros(len(fit_indices), float) 74 | self.A = np.zeros([len(fit_indices), len(fit_indices)], float) 75 | self.B = np.zeros([len(fit_indices)], float) 76 | ndofs = 3*system.natom 77 | masses3 = np.array([[mass,]*3 for mass in system.masses]).reshape(len(system.masses)*3) 78 | masses3_inv_sqrt = np.diag(1.0/np.sqrt(masses3)) 79 | #compute the reference hessian 80 | if do_mass_weighting: 81 | href = np.dot(masses3_inv_sqrt, np.dot(ai.phess0.reshape([ndofs, ndofs]).copy(), masses3_inv_sqrt)) 82 | else: 83 | href = ai.phess0.reshape([ndofs, ndofs]).copy() 84 | for ffref in ffrefs: 85 | if do_mass_weighting: 86 | href -= np.dot(masses3_inv_sqrt, np.dot(ffref.hessian(system.pos).reshape([ndofs, ndofs]), masses3_inv_sqrt)) 87 | else: 88 | href -= ffref.hessian(system.pos).reshape([ndofs, ndofs]) 89 | #loop over valence terms and add to reference (if not in fit_indices or 90 | #its slaves) or add to covalent hessians hcovs (if in fit_indices) 91 | hcovs = [None,]*len(fit_indices) 92 | for master in valence.iter_masters(): 93 | if master.index in fit_indices: 94 | i = fit_indices.index(master.index) 95 | #self.init[i] = valence.get_params(master.index, only='fc') 96 | #add to covalent hessians (includes slaves as well) 97 | if do_mass_weighting: 98 | hcov = np.dot(masses3_inv_sqrt, np.dot(valence.get_hessian_contrib(master.index, fc=1.0), masses3_inv_sqrt)) 99 | else: 100 | hcov = valence.get_hessian_contrib(master.index, fc=1.0) 101 | hcovs[i] = hcov 102 | #set upper and lower 103 | if master.kind==4: 104 | self.upper[i] = 200*kjmol 105 | if master.kind==3: 106 | self.lower[i] = -np.inf 107 | else: 108 | if do_mass_weighting: 109 | hcov = np.dot(masses3_inv_sqrt, np.dot(valence.get_hessian_contrib(master.index), masses3_inv_sqrt)) 110 | else: 111 | hcov = valence.get_hessian_contrib(master.index) 112 | href -= hcov 113 | #construct the cost matrices A and B 114 | for index1, hcov1 in enumerate(hcovs): 115 | self.B[index1] = np.sum(href*hcov1) 116 | self.A[index1,index1] = np.sum(hcov1*hcov1) 117 | for index2, hcov2 in enumerate(hcovs[:index1]): 118 | tmp = np.sum(hcov1*hcov2) 119 | self.A[index1,index2] = tmp 120 | self.A[index2,index1] = tmp 121 | 122 | 123 | def estimate(self, init=None, lower=None, upper=None, do_svd=False, svd_rcond=0.0): 124 | ''' 125 | Estimate the force constants by minimizing the cost function 126 | 127 | ''' 128 | if init is None: 129 | assert self.init is not None, 'No initial fcs defined' 130 | init = self.init.copy() 131 | if lower is None: 132 | assert self.lower is not None, 'No lower limit fcs defined' 133 | lower = self.lower.copy() 134 | if upper is None: 135 | assert self.upper is not None, 'No upper limit fcs defined' 136 | upper = self.upper.copy() 137 | if do_svd: 138 | #perform SVD 139 | U, S, Vt = np.linalg.svd(self.A, full_matrices=True) 140 | mask = S/max(S)>svd_rcond 141 | a = np.diag(S[mask]) 142 | b = np.dot(U.T, self.B)[mask] 143 | vtx0 = np.dot(Vt, init)[mask] 144 | vtlower = -np.inf*np.ones(len(b),float) 145 | vtupper = np.inf*np.ones(len(b),float) 146 | vtx = boxqp(a, b, vtlower, vtupper, vtx0) 147 | x = np.dot(Vt.T[:,mask], vtx) 148 | else: 149 | x = boxqp(self.A, self.B, lower, upper, init) 150 | return x 151 | -------------------------------------------------------------------------------- /quickff/data/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/quickffrc: -------------------------------------------------------------------------------- 1 | #IO 2 | fn_yaff : pars_yaff.txt 3 | fn_charmm22_prm : None 4 | fn_charmm22_psf : None 5 | fn_sys : system.chk 6 | plot_traj : None 7 | xyz_traj : False 8 | fn_traj : None 9 | log_level : medium 10 | log_file : None 11 | 12 | #Program 13 | program_mode : DeriveFF 14 | 15 | #FF config 16 | only_traj : PT_ALL 17 | dont_traj : None 18 | ffatypes : None 19 | enforce_ffatypes : None 20 | ei : None 21 | ei_rcut : None #default is 20 (periodic) or 50 (non-per) A 22 | vdw : None 23 | vdw_rcut : 20*angstrom 24 | covres : None 25 | 26 | excl_bonds : None 27 | excl_bends : None 28 | excl_dihs : None 29 | excl_oopds : None 30 | 31 | do_hess_mass_weighting : True 32 | do_hess_negfreq_proj : False 33 | do_cross_svd : True 34 | pert_traj_tol : 1e-3 35 | pert_traj_ntrials : 2 36 | pert_traj_scipysolver : hybr 37 | pert_traj_energy_noise : None 38 | cross_svd_rcond : 1e-8 39 | 40 | do_bonds : True 41 | do_bends : True 42 | do_dihedrals : True 43 | do_oops : True 44 | do_cross_ASS : True 45 | do_cross_ASA : True 46 | do_cross_DSS : False 47 | do_cross_DSD : False 48 | do_cross_DAA : False 49 | do_cross_DAD : False 50 | consistent_cross_rvs : True 51 | remove_dysfunctional_cross : True 52 | 53 | bond_term : BondHarm 54 | bend_term : BendAHarm 55 | 56 | do_squarebend : True 57 | do_bendclin : True 58 | do_sqoopdist_to_oopdist : True 59 | -------------------------------------------------------------------------------- /quickff/data/systems/H2/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/H2/gaussian.fchk: -------------------------------------------------------------------------------- 1 | title 2 | Freq RB3LYP 6-311++G(d,p) 3 | Number of atoms I 2 4 | Info1-9 I N= 9 5 | 11 9 0 0 0 100 6 | 6 18 -502 7 | Charge I 0 8 | Multiplicity I 1 9 | Number of electrons I 2 10 | Number of alpha electrons I 1 11 | Number of beta electrons I 1 12 | Number of basis functions I 14 13 | Number of independent functions I 14 14 | Number of point charges in /Mol/ I 0 15 | Number of translation vectors I 0 16 | Atomic numbers I N= 2 17 | 1 1 18 | Nuclear charges R N= 2 19 | 1.00000000E+00 1.00000000E+00 20 | Current cartesian coordinates R N= 6 21 | 0.00000000E+00 0.00000000E+00 7.03202999E-01 8.61175302E-17 0.00000000E+00 22 | -7.03202999E-01 23 | Force Field I 0 24 | Int Atom Types I N= 2 25 | 0 0 26 | MM charges R N= 2 27 | 0.00000000E+00 0.00000000E+00 28 | Integer atomic weights I N= 2 29 | 1 1 30 | Real atomic weights R N= 2 31 | 1.00782504E+00 1.00782504E+00 32 | Atom fragment info I N= 2 33 | 0 0 34 | Atom residue num I N= 2 35 | 0 0 36 | Nuclear spins I N= 2 37 | 1 1 38 | Nuclear ZEff R N= 2 39 | -1.00000000E+00 -1.00000000E+00 40 | Nuclear QMom R N= 2 41 | 0.00000000E+00 0.00000000E+00 42 | Nuclear GFac R N= 2 43 | 2.79284600E+00 2.79284600E+00 44 | MicOpt I N= 2 45 | -1 -1 46 | Number of contracted shells I 10 47 | Number of primitive shells I 14 48 | Pure/Cartesian d shells I 0 49 | Pure/Cartesian f shells I 0 50 | Highest angular momentum I 1 51 | Largest degree of contraction I 3 52 | Shell types I N= 10 53 | 0 0 0 0 1 0 54 | 0 0 0 1 55 | Number of primitives per shell I N= 10 56 | 3 1 1 1 1 3 57 | 1 1 1 1 58 | Shell to atom map I N= 10 59 | 1 1 1 1 1 2 60 | 2 2 2 2 61 | Primitive exponents R N= 14 62 | 3.38650000E+01 5.09479000E+00 1.15879000E+00 3.25840000E-01 1.02741000E-01 63 | 3.60000000E-02 7.50000000E-01 3.38650000E+01 5.09479000E+00 1.15879000E+00 64 | 3.25840000E-01 1.02741000E-01 3.60000000E-02 7.50000000E-01 65 | Contraction coefficients R N= 14 66 | 2.54938145E-02 1.90373109E-01 8.52161486E-01 1.00000000E+00 1.00000000E+00 67 | 1.00000000E+00 1.00000000E+00 2.54938145E-02 1.90373109E-01 8.52161486E-01 68 | 1.00000000E+00 1.00000000E+00 1.00000000E+00 1.00000000E+00 69 | Coordinates of each shell R N= 30 70 | 0.00000000E+00 0.00000000E+00 7.03202999E-01 0.00000000E+00 0.00000000E+00 71 | 7.03202999E-01 0.00000000E+00 0.00000000E+00 7.03202999E-01 0.00000000E+00 72 | 0.00000000E+00 7.03202999E-01 0.00000000E+00 0.00000000E+00 7.03202999E-01 73 | 8.61175302E-17 0.00000000E+00 -7.03202999E-01 8.61175302E-17 0.00000000E+00 74 | -7.03202999E-01 8.61175302E-17 0.00000000E+00 -7.03202999E-01 8.61175302E-17 75 | 0.00000000E+00 -7.03202999E-01 8.61175302E-17 0.00000000E+00 -7.03202999E-01 76 | Constraint Structure R N= 6 77 | 0.00000000E+00 0.00000000E+00 7.03202999E-01 8.61175302E-17 0.00000000E+00 78 | -7.03202999E-01 79 | Num ILSW I 100 80 | ILSW I N= 100 81 | 0 0 0 0 2 0 82 | 0 0 0 0 402 -1 83 | 0 0 0 0 0 0 84 | 0 0 0 0 1 0 85 | 1 0 0 0 0 0 86 | 0 0 100000 0 -1 0 87 | 0 0 0 0 0 0 88 | 0 0 0 1 0 0 89 | 0 0 1 0 0 0 90 | 0 0 4 40 0 0 91 | 0 0 5 0 0 0 92 | 0 0 0 0 0 0 93 | 0 0 0 0 0 0 94 | 0 0 0 0 0 0 95 | 0 0 0 0 0 0 96 | 0 0 0 0 0 0 97 | 0 0 0 0 98 | Num RLSW I 40 99 | RLSW R N= 40 100 | 8.00000000E-01 7.20000000E-01 1.00000000E+00 8.10000000E-01 2.00000000E-01 101 | 0.00000000E+00 0.00000000E+00 1.00000000E+00 0.00000000E+00 0.00000000E+00 102 | 0.00000000E+00 0.00000000E+00 1.00000000E+00 0.00000000E+00 0.00000000E+00 103 | 0.00000000E+00 0.00000000E+00 1.00000000E+00 0.00000000E+00 0.00000000E+00 104 | 0.00000000E+00 0.00000000E+00 1.00000000E+00 0.00000000E+00 0.00000000E+00 105 | 0.00000000E+00 0.00000000E+00 1.00000000E+00 0.00000000E+00 0.00000000E+00 106 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 107 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 1.00000000E+00 1.00000000E+00 108 | MxBond I 1 109 | NBond I N= 2 110 | 1 1 111 | IBond I N= 2 112 | 2 1 113 | RBond R N= 2 114 | 1.00000000E+00 1.00000000E+00 115 | Virial Ratio R 2.037872796042644E+00 116 | SCF Energy R -1.179571528334374E+00 117 | Total Energy R -1.179571528334374E+00 118 | RMS Force R 3.489898987151686E-05 119 | RMS Density R 3.496863891797992E-09 120 | External E-field R N= 35 121 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 122 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 123 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 124 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 125 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 126 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 127 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 128 | IOpCl I 0 129 | IROHF I 0 130 | Alpha Orbital Energies R N= 14 131 | -4.33898478E-01 2.01790636E-02 3.17857060E-02 1.43971679E-01 3.45129446E-01 132 | 5.62580850E-01 1.08464254E+00 1.08464254E+00 1.61108200E+00 1.82671108E+00 133 | 1.82671108E+00 2.04807866E+00 2.48637758E+00 3.31093738E+00 134 | Alpha MO coefficients R N= 196 135 | 1.96884463E-01 2.72643412E-01 1.43638543E-01 -7.45686010E-04 0.00000000E+00 136 | 0.00000000E+00 -1.89413601E-02 1.96884463E-01 2.72643412E-01 1.43638543E-01 137 | -7.45686010E-04 0.00000000E+00 0.00000000E+00 1.89413601E-02 4.97480179E-02 138 | 1.93678426E-01 3.34449700E-01 3.05646600E+00 0.00000000E+00 0.00000000E+00 139 | 8.46807588E-03 -4.97480179E-02 -1.93678426E-01 -3.34449700E-01 -3.05646600E+00 140 | 0.00000000E+00 0.00000000E+00 8.46807588E-03 -6.50464521E-02 -4.78128934E-02 141 | -4.12241264E-01 7.79626334E-01 0.00000000E+00 0.00000000E+00 1.34185896E-02 142 | -6.50464521E-02 -4.78128934E-02 -4.12241264E-01 7.79626334E-01 0.00000000E+00 143 | 0.00000000E+00 -1.34185896E-02 -9.86879929E-02 -1.76653330E-02 -2.88677032E+00 144 | 4.50871675E+00 0.00000000E+00 0.00000000E+00 -6.14851179E-02 9.86879929E-02 145 | 1.76653330E-02 2.88677032E+00 -4.50871675E+00 0.00000000E+00 0.00000000E+00 146 | -6.14851179E-02 -7.73347677E-02 -8.42811116E-01 1.50845908E+00 -7.32196947E-01 147 | 0.00000000E+00 0.00000000E+00 1.20962412E-02 -7.73347677E-02 -8.42811116E-01 148 | 1.50845908E+00 -7.32196947E-01 0.00000000E+00 0.00000000E+00 -1.20962412E-02 149 | -1.34348803E-01 -2.03203503E+00 3.95215039E+00 -2.75377013E+00 0.00000000E+00 150 | 0.00000000E+00 1.27037804E-01 1.34348803E-01 2.03203503E+00 -3.95215039E+00 151 | 2.75377013E+00 0.00000000E+00 0.00000000E+00 1.27037804E-01 0.00000000E+00 152 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 5.81969328E-01 153 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 154 | 0.00000000E+00 5.81969328E-01 0.00000000E+00 0.00000000E+00 0.00000000E+00 155 | 0.00000000E+00 0.00000000E+00 5.81969328E-01 0.00000000E+00 0.00000000E+00 156 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 5.81969328E-01 157 | 0.00000000E+00 0.00000000E+00 -2.44846934E-01 8.08171849E-01 -6.45143345E-01 158 | 2.15856171E-01 0.00000000E+00 0.00000000E+00 6.35797735E-01 -2.44846934E-01 159 | 8.08171849E-01 -6.45143345E-01 2.15856171E-01 0.00000000E+00 0.00000000E+00 160 | -6.35797735E-01 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 161 | 0.00000000E+00 9.77095332E-01 0.00000000E+00 0.00000000E+00 0.00000000E+00 162 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 -9.77095332E-01 0.00000000E+00 163 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 9.77095332E-01 164 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 165 | 0.00000000E+00 -9.77095332E-01 0.00000000E+00 0.00000000E+00 -6.39735700E-01 166 | 3.84683430E+00 -2.71447420E+00 1.48552231E+00 0.00000000E+00 0.00000000E+00 167 | -1.38683988E+00 6.39735700E-01 -3.84683430E+00 2.71447420E+00 -1.48552231E+00 168 | 0.00000000E+00 0.00000000E+00 -1.38683988E+00 -1.14546903E+00 1.24712950E+00 169 | -7.41544640E-01 2.52513394E-01 0.00000000E+00 0.00000000E+00 -3.39711677E-01 170 | -1.14546903E+00 1.24712950E+00 -7.41544640E-01 2.52513394E-01 0.00000000E+00 171 | 0.00000000E+00 3.39711677E-01 -1.07076447E+00 -1.81049442E+00 3.20680302E-01 172 | -6.00132084E-02 0.00000000E+00 0.00000000E+00 1.92572915E+00 1.07076447E+00 173 | 1.81049442E+00 -3.20680302E-01 6.00132084E-02 0.00000000E+00 0.00000000E+00 174 | 1.92572915E+00 175 | Total SCF Density R N= 105 176 | 7.75269832E-02 1.07358503E-01 1.48668860E-01 5.65603945E-02 7.83242047E-02 177 | 4.12640618E-02 -2.93627979E-04 -4.06612756E-04 -2.14218503E-04 1.11209525E-06 178 | -1.14175643E-19 -1.58109159E-19 -8.32977002E-20 4.32432191E-22 1.34519125E-36 179 | -1.14175643E-19 -1.58109159E-19 -8.32977002E-20 4.32432191E-22 8.23692080E-53 180 | 1.34519125E-36 -7.45851901E-03 -1.03284741E-02 -5.44141872E-03 2.82486145E-05 181 | 1.09843201E-20 1.09843201E-20 7.17550246E-04 7.75269832E-02 1.07358503E-01 182 | 5.65603945E-02 -2.93627979E-04 -1.14175643E-19 -1.14175643E-19 -7.45851901E-03 183 | 7.75269832E-02 1.07358503E-01 1.48668860E-01 7.83242047E-02 -4.06612756E-04 184 | -1.58109159E-19 -1.58109159E-19 -1.03284741E-02 1.07358503E-01 1.48668860E-01 185 | 5.65603945E-02 7.83242047E-02 4.12640618E-02 -2.14218503E-04 -8.32977002E-20 186 | -8.32977002E-20 -5.44141872E-03 5.65603945E-02 7.83242047E-02 4.12640618E-02 187 | -2.93627979E-04 -4.06612756E-04 -2.14218503E-04 1.11209525E-06 4.32432191E-22 188 | 4.32432191E-22 2.82486145E-05 -2.93627979E-04 -4.06612756E-04 -2.14218503E-04 189 | 1.11209525E-06 1.14175643E-19 1.58109159E-19 8.32977002E-20 -4.32432191E-22 190 | -1.34519125E-36 -8.23692080E-53 -1.09843201E-20 1.14175643E-19 1.58109159E-19 191 | 8.32977002E-20 -4.32432191E-22 1.34519125E-36 1.14175643E-19 1.58109159E-19 192 | 8.32977002E-20 -4.32432191E-22 -8.23692080E-53 -1.34519125E-36 -1.09843201E-20 193 | 1.14175643E-19 1.58109159E-19 8.32977002E-20 -4.32432191E-22 8.23692080E-53 194 | 1.34519125E-36 7.45851901E-03 1.03284741E-02 5.44141872E-03 -2.82486145E-05 195 | -1.09843201E-20 -1.09843201E-20 -7.17550246E-04 7.45851901E-03 1.03284741E-02 196 | 5.44141872E-03 -2.82486145E-05 1.09843201E-20 1.09843201E-20 7.17550246E-04 197 | QEq coupling tensors R N= 12 198 | 1.73720568E-01 0.00000000E+00 1.73720568E-01 3.31401365E-17 0.00000000E+00 199 | -3.47441137E-01 1.73720568E-01 0.00000000E+00 1.73720568E-01 1.95492498E-17 200 | 0.00000000E+00 -3.47441137E-01 201 | Mulliken Charges R N= 2 202 | 2.27595720E-15 2.22044605E-15 203 | ONIOM Charges I N= 16 204 | 0 0 0 0 0 0 205 | 0 0 0 0 0 0 206 | 0 0 0 0 207 | ONIOM Multiplicities I N= 16 208 | 1 0 0 0 0 0 209 | 0 0 0 0 0 0 210 | 0 0 0 0 211 | Atom Layers I N= 2 212 | 1 1 213 | Atom Modifiers I N= 2 214 | 0 0 215 | Force Field I 0 216 | Int Atom Modified Types I N= 2 217 | 0 0 218 | Link Atoms I N= 2 219 | 0 0 220 | Atom Modified MM Charges R N= 2 221 | 0.00000000E+00 0.00000000E+00 222 | Link Distances R N= 8 223 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 224 | 0.00000000E+00 0.00000000E+00 0.00000000E+00 225 | Cartesian Gradient R N= 6 226 | -2.69867406E-17 -5.22728855E-19 6.04468236E-05 2.69867406E-17 5.22728855E-19 227 | -6.04468236E-05 228 | Cartesian Force Constants R N= 21 229 | 3.93595255E-05 5.06348827E-22 3.93595241E-05 5.72987801E-13 -2.20249793E-12 230 | 3.72034652E-01 -3.93595255E-05 -2.70752665E-22 -5.72986459E-13 3.93595255E-05 231 | 2.70752395E-22 -3.93595241E-05 -1.91671443E-12 -5.06348557E-22 3.93595241E-05 232 | -5.72986459E-13 1.91669255E-12 -3.72034652E-01 5.72985117E-13 2.20251982E-12 233 | 3.72034652E-01 234 | Dipole Moment R N= 3 235 | 1.72563323E-31 2.40741243E-35 -4.68375339E-17 236 | Dipole Derivatives R N= 18 237 | -1.34824335E-14 -2.79230180E-21 -8.03426663E-12 5.12586869E-21 -3.45969184E-14 238 | -3.81464828E-11 1.70629244E-12 -2.56742533E-12 6.30603370E-10 -1.28293101E-14 239 | 2.79230211E-21 -7.51765241E-12 -5.12586401E-21 -3.47669213E-14 3.81464828E-11 240 | 1.65208227E-12 2.56742533E-12 5.14061480E-10 241 | Polarizability R N= 6 242 | 1.09638551E+00 1.15304539E-21 1.09638551E+00 -2.73770882E-12 1.14481280E-12 243 | 6.91241895E+00 244 | -------------------------------------------------------------------------------- /quickff/data/systems/H2/gaussian_mbis.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molmod/QuickFF/40292b7cbc1b7b295dcf1310266a922f455ae8c8/quickff/data/systems/H2/gaussian_mbis.h5 -------------------------------------------------------------------------------- /quickff/data/systems/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/amoniak/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/amoniak/gaussian_mbis.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molmod/QuickFF/40292b7cbc1b7b295dcf1310266a922f455ae8c8/quickff/data/systems/amoniak/gaussian_mbis.h5 -------------------------------------------------------------------------------- /quickff/data/systems/benzene/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/benzene/gaussian_mbis.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molmod/QuickFF/40292b7cbc1b7b295dcf1310266a922f455ae8c8/quickff/data/systems/benzene/gaussian_mbis.h5 -------------------------------------------------------------------------------- /quickff/data/systems/clean_h5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | '''Remove largest pieces of unused data from gaussian_mbis.h5 files, and repack them. 3 | 4 | All gaussian_mbis.h5 files were first generated with the following bash loop: 5 | 6 | for d in */; do (cd $d; horton-wpart.py gaussian.fchk gaussian_mbis.h5 mbis 7 | --grid=ultrafine --lmax=1 --overwrite); done 8 | 9 | using HORTON 2.0.1. Then this clean_h5.py script is executed to get rid of excess data. 10 | ''' 11 | 12 | from glob import glob 13 | import os 14 | 15 | import h5py as h5 16 | 17 | for fn_h5 in glob('*/*.h5'): 18 | with h5.File(fn_h5, 'r') as f, h5.File(fn_h5 + '.tmp', 'w') as fnew: 19 | for key in f: 20 | if isinstance(f[key], h5.Dataset): 21 | f.copy(key, fnew) 22 | os.remove(fn_h5) 23 | os.rename(fn_h5 + '.tmp', fn_h5) 24 | -------------------------------------------------------------------------------- /quickff/data/systems/ethane/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/ethane/gaussian_mbis.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molmod/QuickFF/40292b7cbc1b7b295dcf1310266a922f455ae8c8/quickff/data/systems/ethane/gaussian_mbis.h5 -------------------------------------------------------------------------------- /quickff/data/systems/ethanol/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/ethanol/gaussian_mbis.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molmod/QuickFF/40292b7cbc1b7b295dcf1310266a922f455ae8c8/quickff/data/systems/ethanol/gaussian_mbis.h5 -------------------------------------------------------------------------------- /quickff/data/systems/ethene/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/ethene/gaussian_mbis.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molmod/QuickFF/40292b7cbc1b7b295dcf1310266a922f455ae8c8/quickff/data/systems/ethene/gaussian_mbis.h5 -------------------------------------------------------------------------------- /quickff/data/systems/methane/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/methane/gaussian_mbis.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molmod/QuickFF/40292b7cbc1b7b295dcf1310266a922f455ae8c8/quickff/data/systems/methane/gaussian_mbis.h5 -------------------------------------------------------------------------------- /quickff/data/systems/uio66-zr-brick/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/water/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/data/systems/water/gaussian_mbis.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molmod/QuickFF/40292b7cbc1b7b295dcf1310266a922f455ae8c8/quickff/data/systems/water/gaussian_mbis.h5 -------------------------------------------------------------------------------- /quickff/data/uff.prm: -------------------------------------------------------------------------------- 1 | # 2 | # Open Babel file: UFF.prm 3 | # 4 | # Force field parameters for UFF, the Universal Force Field 5 | # Used by OBForceField and OBUFFForceField 6 | # 7 | # J. Am. Chem. Soc. (1992) 114(25) p. 10024-10035. 8 | # The parameters in this file are taken from the UFF implementation in RDKit 9 | # http://rdkit.org/ 10 | # 11 | # Atom typing rules are based on UFF published atom descriptions 12 | # atom [SMARTS] [atomtype] [description] 13 | # These must be sorted according to the element and complexity 14 | # of the type rule (i.e., generic rules first, more specific rules later) 15 | # 16 | # Parameters follow later 17 | # param Atom r1 theta0 x1 D1 zeta Z1 Vi Uj Xi Hard Radius 18 | 19 | #atom [#0] Du Dummy atom (e.g., ligand attachment point) 20 | atom [#1] H_ Generic hydrogen 21 | atom [#1D2] H_b Bridging hydrogen 22 | atom [#2] He4+4 Helium 23 | atom [#3] Li Lithium 24 | atom [#4] Be3+2 Generic Be 25 | atom [#5] B_2 Trigonal planar boron 26 | atom [#5D4] B_3 Tetrahedral boron 27 | atom [#6] C_3 Generic sp3 C 28 | atom [C^2] C_2 sp2 non-aromatic C 29 | atom [C^1] C_1 sp hybridized C 30 | atom [c] C_R aromatic C 31 | atom [#6H1D3r5] C_R aromatic C (cyclopentadienyl ring) 32 | atom [#7] N_3 Generic sp3 N 33 | atom [N^2] N_2 sp2 non-aromatic N 34 | atom [N^1] N_1 sp hybridized N 35 | atom [n] N_R aromatic N 36 | atom [#8] O_3 generic, sp3 hybridized O 37 | atom [#8][#14] O_3_z sp3 hybridized O for zeolites 38 | atom [O^2] O_2 sp2 hybridized O 39 | atom [O^1] O_1 sp hybridized O 40 | atom [o] O_R aromatic O 41 | atom [#9] F_ generic F 42 | atom [#10] Ne4+4 43 | atom [#11] Na 44 | atom [#12] Mg3+2 45 | atom [#13] Al3 46 | atom [#14] Si3 47 | atom [#15] P_3+q Organometallic phosphine ligands 48 | atom [#15] P_3+3 generic phosphorus 49 | atom [#15D5] P_3+5 formal charge +5 50 | atom [#16] S_3+2 generic S 51 | atom [#16+4] S_3+4 S+4 ( SO2 ) 52 | atom [#16+6] S_3+6 S+6 ( SO3 / H2SO4 ) 53 | atom [S^2] S_2 non-aromatic sp2 S 54 | atom [s] S_R aromatic S 55 | atom [#17] Cl 56 | atom [#18] Ar4+4 57 | atom [#19] K_ 58 | atom [#20] Ca6+2 59 | atom [#21] Sc3+3 60 | atom [#22] Ti6+4 generic Ti (6-valent) 61 | atom [#22D3] Ti3+4 62 | atom [#23] V_3+5 63 | atom [#24] Cr6+3 64 | atom [#25] Mn6+2 65 | atom [#26] Fe6+2 generic Fe (6-valent) 66 | atom [#26D3] Fe3+2 67 | atom [#27] Co6+3 68 | atom [#28] Ni4+2 69 | atom [#29] Cu3+1 70 | atom [#30] Zn3+2 71 | atom [#31] Ga3+3 72 | atom [#32] Ge3 73 | atom [#33] As3+3 74 | atom [#34] Se3+2 75 | atom [#35] Br 76 | atom [#36] Kr4+4 77 | atom [#37] Rb 78 | atom [#38] Sr6+2 79 | atom [#39] Y_3+3 80 | atom [#40] Zr3+4 81 | atom [#41] Nb3+5 82 | atom [#42] Mo6+6 generic Mo (6-valent) 83 | atom [#42D3] Mo3+6 trivalent Mo 84 | atom [#43] Tc6+5 85 | atom [#44] Ru6+2 86 | atom [#45] Rh6+3 87 | atom [#46] Pd4+2 88 | atom [#47] Ag1+1 89 | atom [#48] Cd3+2 90 | atom [#49] In3+3 91 | atom [#50] Sn3 92 | atom [#51] Sb3+3 93 | atom [#52] Te3+2 94 | atom [#53] I_ 95 | atom [#54] Xe4+4 96 | atom [#55] Cs 97 | atom [#56] Ba6+2 98 | atom [#57] La3+3 99 | atom [#58] Ce6+3 100 | atom [#59] Pr6+3 101 | atom [#60] Nd6+3 102 | atom [#61] Pm6+3 103 | atom [#62] Sm6+3 104 | atom [#63] Eu6+3 105 | atom [#64] Gd6+3 106 | atom [#65] Tb6+3 107 | atom [#66] Dy6+3 108 | atom [#67] Ho6+3 109 | atom [#68] Er6+3 110 | atom [#69] Tm6+3 111 | atom [#70] Yb6+3 112 | atom [#71] Lu6+3 113 | atom [#72] Hf3+4 114 | atom [#73] Ta3+5 115 | atom [#74] W_6+6 generic W (6-valent) 116 | atom [#74D3+4] W_3+4 117 | atom [#74D3+6] W_3+6 118 | atom [#75] Re6+5 generic Re (6-valent) 119 | atom [#75D3] Re3+7 trivalent Re 120 | atom [#76] Os6+6 121 | atom [#77] Ir6+3 122 | atom [#78] Pt4+2 123 | atom [#79] Au4+3 124 | atom [#80] Hg1+2 125 | atom [#81] Tl3+3 126 | atom [#82] Pb3 127 | atom [#83] Bi3+3 128 | atom [#84] Po3+2 129 | atom [#85] At 130 | atom [#86] Rn4+4 131 | atom [#87] Fr 132 | atom [#88] Ra6+2 133 | atom [#89] Ac6+3 134 | atom [#90] Th6+4 135 | atom [#91] Pa6+4 136 | atom [#92] U_6+4 137 | atom [#93] Np6+4 138 | atom [#94] Pu6+4 139 | atom [#95] Am6+4 140 | atom [#96] Cm6+3 141 | atom [#97] Bk6+3 142 | atom [#98] Cf6+3 143 | atom [#99] Es6+3 144 | atom [#100] Fm6+3 145 | atom [#101] Md6+3 146 | atom [#102] No6+3 147 | atom [#103] Lw6+3 148 | 149 | #key Atom r1 theta0 x1 D1 zeta Z1 Vi Uj Xi Hard Radius 150 | param Du 0.01 180 0.4 5000 12 10.0 0 0 9.66 14.92 0.7 151 | param H_ 0.354 180 2.886 0.044 12 0.712 0 0 4.528 6.9452 0.371 152 | param H_b 0.46 83.5 2.886 0.044 12 0.712 0 0 4.528 6.9452 0.371 153 | param He4+4 0.849 90 2.362 0.056 15.24 0.098 0 0 9.66 14.92 1.3 154 | param Li 1.336 180 2.451 0.025 12 1.026 0 2 3.006 2.386 1.557 155 | param Be3+2 1.074 109.47 2.745 0.085 12 1.565 0 2 4.877 4.443 1.24 156 | param B_3 0.838 109.47 4.083 0.18 12.052 1.755 0 2 5.11 4.75 0.822 157 | param B_2 0.828 120 4.083 0.18 12.052 1.755 0 2 5.11 4.75 0.822 158 | param C_3 0.757 109.47 3.851 0.105 12.73 1.912 2.119 2 5.343 5.063 0.759 159 | param C_R 0.729 120 3.851 0.105 12.73 1.912 0 2 5.343 5.063 0.759 160 | param C_2 0.732 120 3.851 0.105 12.73 1.912 0 2 5.343 5.063 0.759 161 | param C_1 0.706 180 3.851 0.105 12.73 1.912 0 2 5.343 5.063 0.759 162 | param N_3 0.7 106.7 3.66 0.069 13.407 2.544 0.45 2 6.899 5.88 0.715 163 | param N_R 0.699 120 3.66 0.069 13.407 2.544 0 2 6.899 5.88 0.715 164 | param N_2 0.685 111.2 3.66 0.069 13.407 2.544 0 2 6.899 5.88 0.715 165 | param N_1 0.656 180 3.66 0.069 13.407 2.544 0 2 6.899 5.88 0.715 166 | param O_3 0.658 104.51 3.5 0.06 14.085 2.3 0.018 2 8.741 6.682 0.669 167 | param O_3_z 0.528 146 3.5 0.06 14.085 2.3 0.018 2 8.741 6.682 0.669 168 | param O_R 0.68 110 3.5 0.06 14.085 2.3 0 2 8.741 6.682 0.669 169 | param O_2 0.634 120 3.5 0.06 14.085 2.3 0 2 8.741 6.682 0.669 170 | param O_1 0.639 180 3.5 0.06 14.085 2.3 0 2 8.741 6.682 0.669 171 | param F_ 0.668 180 3.364 0.05 14.762 1.735 0 2 10.874 7.474 0.706 172 | param Ne4+4 0.92 90 3.243 0.042 15.44 0.194 0 2 11.04 10.55 1.768 173 | param Na 1.539 180 2.983 0.03 12 1.081 0 1.25 2.843 2.296 2.085 174 | param Mg3+2 1.421 109.47 3.021 0.111 12 1.787 0 1.25 3.951 3.693 1.5 175 | param Al3 1.244 109.47 4.499 0.505 11.278 1.792 0 1.25 4.06 3.59 1.201 176 | param Si3 1.117 109.47 4.295 0.402 12.175 2.323 1.225 1.25 4.168 3.487 1.176 177 | param P_3+3 1.101 93.8 4.147 0.305 13.072 2.863 2.4 1.25 5.463 4 1.102 178 | param P_3+5 1.056 109.47 4.147 0.305 13.072 2.863 2.4 1.25 5.463 4 1.102 179 | param P_3+q 1.056 109.47 4.147 0.305 13.072 2.863 2.4 1.25 5.463 4 1.102 180 | param S_3+2 1.064 92.1 4.035 0.274 13.969 2.703 0.484 1.25 6.928 4.486 1.047 181 | param S_3+4 1.049 103.2 4.035 0.274 13.969 2.703 0.484 1.25 6.928 4.486 1.047 182 | param S_3+6 1.027 109.47 4.035 0.274 13.969 2.703 0.484 1.25 6.928 4.486 1.047 183 | param S_R 1.077 92.2 4.035 0.274 13.969 2.703 0 1.25 6.928 4.486 1.047 184 | param S_2 0.854 120 4.035 0.274 13.969 2.703 0 1.25 6.928 4.486 1.047 185 | param Cl 1.044 180 3.947 0.227 14.866 2.348 0 1.25 8.564 4.946 0.994 186 | param Ar4+4 1.032 90 3.868 0.185 15.763 0.3 0 1.25 9.465 6.355 2.108 187 | param K_ 1.953 180 3.812 0.035 12 1.165 0 0.7 2.421 1.92 2.586 188 | param Ca6+2 1.761 90 3.399 0.238 12 2.141 0 0.7 3.231 2.88 2 189 | param Sc3+3 1.513 109.47 3.295 0.019 12 2.592 0 0.7 3.395 3.08 1.75 190 | param Ti3+4 1.412 109.47 3.175 0.017 12 2.659 0 0.7 3.47 3.38 1.607 191 | param Ti6+4 1.412 90 3.175 0.017 12 2.659 0 0.7 3.47 3.38 1.607 192 | param V_3+5 1.402 109.47 3.144 0.016 12 2.679 0 0.7 3.65 3.41 1.47 193 | param Cr6+3 1.345 90 3.023 0.015 12 2.463 0 0.7 3.415 3.865 1.402 194 | param Mn6+2 1.382 90 2.961 0.013 12 2.43 0 0.7 3.325 4.105 1.533 195 | param Fe3+2 1.27 109.47 2.912 0.013 12 2.43 0 0.7 3.76 4.14 1.393 196 | param Fe6+2 1.335 90 2.912 0.013 12 2.43 0 0.7 3.76 4.14 1.393 197 | param Co6+3 1.241 90 2.872 0.014 12 2.43 0 0.7 4.105 4.175 1.406 198 | param Ni4+2 1.164 90 2.834 0.015 12 2.43 0 0.7 4.465 4.205 1.398 199 | param Cu3+1 1.302 109.47 3.495 0.005 12 1.756 0 0.7 4.2 4.22 1.434 200 | param Zn3+2 1.193 109.47 2.763 0.124 12 1.308 0 0.7 5.106 4.285 1.4 201 | param Ga3+3 1.26 109.47 4.383 0.415 11 1.821 0 0.7 3.641 3.16 1.211 202 | param Ge3 1.197 109.47 4.28 0.379 12 2.789 0.701 0.7 4.051 3.438 1.189 203 | param As3+3 1.211 92.1 4.23 0.309 13 2.864 1.5 0.7 5.188 3.809 1.204 204 | param Se3+2 1.19 90.6 4.205 0.291 14 2.764 0.335 0.7 6.428 4.131 1.224 205 | param Br 1.192 180 4.189 0.251 15 2.519 0 0.7 7.79 4.425 1.141 206 | param Kr4+4 1.147 90 4.141 0.22 16 0.452 0 0.7 8.505 5.715 2.27 207 | param Rb 2.26 180 4.114 0.04 12 1.592 0 0.2 2.331 1.846 2.77 208 | param Sr6+2 2.052 90 3.641 0.235 12 2.449 0 0.2 3.024 2.44 2.415 209 | param Y_3+3 1.698 109.47 3.345 0.072 12 3.257 0 0.2 3.83 2.81 1.998 210 | param Zr3+4 1.564 109.47 3.124 0.069 12 3.667 0 0.2 3.4 3.55 1.758 211 | param Nb3+5 1.473 109.47 3.165 0.059 12 3.618 0 0.2 3.55 3.38 1.603 212 | param Mo6+6 1.467 90 3.052 0.056 12 3.4 0 0.2 3.465 3.755 1.53 213 | param Mo3+6 1.484 109.47 3.052 0.056 12 3.4 0 0.2 3.465 3.755 1.53 214 | param Tc6+5 1.322 90 2.998 0.048 12 3.4 0 0.2 3.29 3.99 1.5 215 | param Ru6+2 1.478 90 2.963 0.056 12 3.4 0 0.2 3.575 4.015 1.5 216 | param Rh6+3 1.332 90 2.929 0.053 12 3.5 0 0.2 3.975 4.005 1.509 217 | param Pd4+2 1.338 90 2.899 0.048 12 3.21 0 0.2 4.32 4 1.544 218 | param Ag1+1 1.386 180 3.148 0.036 12 1.956 0 0.2 4.436 3.134 1.622 219 | param Cd3+2 1.403 109.47 2.848 0.228 12 1.65 0 0.2 5.034 3.957 1.6 220 | param In3+3 1.459 109.47 4.463 0.599 11 2.07 0 0.2 3.506 2.896 1.404 221 | param Sn3 1.398 109.47 4.392 0.567 12 2.961 0.199 0.2 3.987 3.124 1.354 222 | param Sb3+3 1.407 91.6 4.42 0.449 13 2.704 1.1 0.2 4.899 3.342 1.404 223 | param Te3+2 1.386 90.25 4.47 0.398 14 2.882 0.3 0.2 5.816 3.526 1.38 224 | param I_ 1.382 180 4.5 0.339 15 2.65 0 0.2 6.822 3.762 1.333 225 | param Xe4+4 1.267 90 4.404 0.332 12 0.556 0 0.2 7.595 4.975 2.459 226 | param Cs 2.57 180 4.517 0.045 12 1.573 0 0.1 2.183 1.711 2.984 227 | param Ba6+2 2.277 90 3.703 0.364 12 2.727 0 0.1 2.814 2.396 2.442 228 | param La3+3 1.943 109.47 3.522 0.017 12 3.3 0 0.1 2.8355 2.7415 2.071 229 | param Ce6+3 1.841 90 3.556 0.013 12 3.3 0 0.1 2.774 2.692 1.925 230 | param Pr6+3 1.823 90 3.606 0.01 12 3.3 0 0.1 2.858 2.564 2.007 231 | param Nd6+3 1.816 90 3.575 0.01 12 3.3 0 0.1 2.8685 2.6205 2.007 232 | param Pm6+3 1.801 90 3.547 0.009 12 3.3 0 0.1 2.881 2.673 2 233 | param Sm6+3 1.78 90 3.52 0.008 12 3.3 0 0.1 2.9115 2.7195 1.978 234 | param Eu6+3 1.771 90 3.493 0.008 12 3.3 0 0.1 2.8785 2.7875 2.227 235 | param Gd6+3 1.735 90 3.368 0.009 12 3.3 0 0.1 3.1665 2.9745 1.968 236 | param Tb6+3 1.732 90 3.451 0.007 12 3.3 0 0.1 3.018 2.834 1.954 237 | param Dy6+3 1.71 90 3.428 0.007 12 3.3 0 0.1 3.0555 2.8715 1.934 238 | param Ho6+3 1.696 90 3.409 0.007 12 3.416 0 0.1 3.127 2.891 1.925 239 | param Er6+3 1.673 90 3.391 0.007 12 3.3 0 0.1 3.1865 2.9145 1.915 240 | param Tm6+3 1.66 90 3.374 0.006 12 3.3 0 0.1 3.2514 2.9329 2 241 | param Yb6+3 1.637 90 3.355 0.228 12 2.618 0 0.1 3.2889 2.965 2.158 242 | param Lu6+3 1.671 90 3.64 0.041 12 3.271 0 0.1 2.9629 2.4629 1.896 243 | param Hf3+4 1.611 109.47 3.141 0.072 12 3.921 0 0.1 3.7 3.4 1.759 244 | param Ta3+5 1.511 109.47 3.17 0.081 12 4.075 0 0.1 5.1 2.85 1.605 245 | param W_6+6 1.392 90 3.069 0.067 12 3.7 0 0.1 4.63 3.31 1.538 246 | param W_3+4 1.526 109.47 3.069 0.067 12 3.7 0 0.1 4.63 3.31 1.538 247 | param W_3+6 1.38 109.47 3.069 0.067 12 3.7 0 0.1 4.63 3.31 1.538 248 | param Re6+5 1.372 90 2.954 0.066 12 3.7 0 0.1 3.96 3.92 1.6 249 | param Re3+7 1.314 109.47 2.954 0.066 12 3.7 0 0.1 3.96 3.92 1.6 250 | param Os6+6 1.372 90 3.12 0.037 12 3.7 0 0.1 5.14 3.63 1.7 251 | param Ir6+3 1.371 90 2.84 0.073 12 3.731 0 0.1 5 4 1.866 252 | param Pt4+2 1.364 90 2.754 0.08 12 3.382 0 0.1 4.79 4.43 1.557 253 | param Au4+3 1.262 90 3.293 0.039 12 2.625 0 0.1 4.894 2.586 1.618 254 | param Hg1+2 1.34 180 2.705 0.385 12 1.75 0 0.1 6.27 4.16 1.6 255 | param Tl3+3 1.518 120 4.347 0.68 11 2.068 0 0.1 3.2 2.9 1.53 256 | param Pb3 1.459 109.47 4.297 0.663 12 2.846 0.1 0.1 3.9 3.53 1.444 257 | param Bi3+3 1.512 90 4.37 0.518 13 2.47 1 0.1 4.69 3.74 1.514 258 | param Po3+2 1.5 90 4.709 0.325 14 2.33 0.3 0.1 4.21 4.21 1.48 259 | param At 1.545 180 4.75 0.284 15 2.24 0 0.1 4.75 4.75 1.47 260 | param Rn4+4 1.42 90 4.765 0.248 16 0.583 0 0.1 5.37 5.37 2.2 261 | param Fr 2.88 180 4.9 0.05 12 1.847 0 0 2 2 2.3 262 | param Ra6+2 2.512 90 3.677 0.404 12 2.92 0 0 2.843 2.434 2.2 263 | param Ac6+3 1.983 90 3.478 0.033 12 3.9 0 0 2.835 2.835 2.108 264 | param Th6+4 1.721 90 3.396 0.026 12 4.202 0 0 3.175 2.905 2.018 265 | param Pa6+4 1.711 90 3.424 0.022 12 3.9 0 0 2.985 2.905 1.8 266 | param U_6+4 1.684 90 3.395 0.022 12 3.9 0 0 3.341 2.853 1.713 267 | param Np6+4 1.666 90 3.424 0.019 12 3.9 0 0 3.549 2.717 1.8 268 | param Pu6+4 1.657 90 3.424 0.016 12 3.9 0 0 3.243 2.819 1.84 269 | param Am6+4 1.66 90 3.381 0.014 12 3.9 0 0 2.9895 3.0035 1.942 270 | param Cm6+3 1.801 90 3.326 0.013 12 3.9 0 0 2.8315 3.1895 1.9 271 | param Bk6+3 1.761 90 3.339 0.013 12 3.9 0 0 3.1935 3.0355 1.9 272 | param Cf6+3 1.75 90 3.313 0.013 12 3.9 0 0 3.197 3.101 1.9 273 | param Es6+3 1.724 90 3.299 0.012 12 3.9 0 0 3.333 3.089 1.9 274 | param Fm6+3 1.712 90 3.286 0.012 12 3.9 0 0 3.4 3.1 1.9 275 | param Md6+3 1.689 90 3.274 0.011 12 3.9 0 0 3.47 3.11 1.9 276 | param No6+3 1.679 90 3.248 0.011 12 3.9 0 0 3.475 3.175 1.9 277 | param Lw6+3 1.698 90 3.236 0.011 12 3.9 0 0 3.5 3.2 1.9 278 | 279 | -------------------------------------------------------------------------------- /quickff/log.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | 27 | from __future__ import print_function, absolute_import, unicode_literals 28 | from io import IOBase 29 | import os, sys, datetime, getpass, atexit 30 | import numpy, scipy, matplotlib 31 | 32 | __all__ = ['version', 'log'] 33 | 34 | version = '2.2.7' 35 | 36 | header = """ 37 | ________________/\\\\\\_________/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\__/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\_________________ 38 | ______________/\\\\\\\\/\\\\\\\\_____\\/\\\\\\///////////__\\/\\\\\///////////_________________ 39 | _____________/\\\\\\//\\////\\\\\\___\\/\\\\\\_____________\\/\\\\\\___________________________ 40 | _____________/\\\\\\______\\//\\\\\\__\\/\\\\\\\\\\\\\\\\\\\\\\_____\\/\\\\\\\\\\\\\\\\\\\\\\__________________ 41 | _____________\\//\\\\\\______/\\\\\\___\\/\\\\\\///////______\\/\\\\\\///////__________________ 42 | _______________\\///\\\\\\\\/\\\\\\\\/____\\/\\\\\\_____________\\/\\\\\\________________________ 43 | __________________\\////\\\\\\//______\\/\\\\\\_____________\\/\\\\\\_______________________ 44 | ______________________\\///\\\\\\\\\\\\___\\/\\\\\\_____________\\/\\\\\\______________________ 45 | _________________________\\//////____\\///______________\\///______________________ 46 | 47 | Welcom to QuickFF 48 | a Python package to quickly derive force fields from ab initio input data 49 | 50 | Written by 51 | Louis Vanduyfhuys(1)*, Steven Vandenbrande(1) and Toon Verstraelen(1) 52 | 53 | (1) Center for Molecular Modeling, Ghent University Belgium. 54 | * mailto: Louis.Vanduyfhuys@UGent.be 55 | """ 56 | 57 | footer = """ 58 | __/\\\\\\__________________________________________________________________/\\\\\\____ 59 | \\ \\\\\\ \\ \\\\\\ 60 | \\ \\\\\\ End of file. Thanks for using QuickFF! Come back soon!! \\ \\\\\\ 61 | ____\\///__________________________________________________________________\\///__ 62 | """ 63 | 64 | def splitstring(string, length, separators=[' ','/','_']): 65 | result = [] 66 | remainder = string 67 | while len(remainder)>length: 68 | i=length-1 69 | while remainder[i] not in separators and i>0: 70 | i -= 1 71 | result.append(remainder[:i+1]) 72 | remainder = remainder[i+1:] 73 | if len(remainder)>0: 74 | result.append(remainder) 75 | return result 76 | 77 | 78 | class Section(object): 79 | def __init__(self, logger, label, level, timer_description): 80 | self.logger = logger 81 | self.old_label = logger.label 82 | self.new_label = label 83 | self.old_level = self.logger.section_level 84 | self.new_level = level 85 | self.timer_description = timer_description 86 | 87 | def __enter__(self): 88 | if self.new_label!=self.old_label and self.logger.log_level>0: 89 | self.logger.add_blank_line = True 90 | self.logger.label = self.new_label 91 | self.logger.section_level = self.new_level 92 | if self.timer_description is not None: 93 | self.begin = datetime.datetime.now() 94 | self.end = None 95 | 96 | def __exit__(self, type, value, traceback): 97 | if self.new_label!=self.old_label and self.logger.log_level>0: 98 | self.logger.add_blank_line = True 99 | self.logger.label = self.old_label 100 | self.logger.section_level = self.old_level 101 | if self.timer_description is not None: 102 | self.end = datetime.datetime.now() 103 | for i, (description, time) in enumerate(self.logger.timetable): 104 | if description==self.timer_description: 105 | self.logger.timetable[i][1] = time + self.end-self.begin 106 | return 107 | self.logger.timetable.append([self.timer_description, self.end-self.begin]) 108 | 109 | 110 | class Logger(object): 111 | def __init__(self, level, _f=sys.stdout, max_label_length=8, line_length=80): 112 | self.set_level(level) 113 | self._f = _f 114 | self.mll = max_label_length 115 | self.ll = line_length 116 | self._active = False 117 | self.label = 'QFF' 118 | self.add_blank_line = False 119 | self.timetable = [] 120 | 121 | def set_level(self, level): 122 | if isinstance(level, int): 123 | if level>=0 and level<=4: 124 | self.log_level = level 125 | else: 126 | raise ValueError('Integer level should be between 0 and 4 (boundaries included).') 127 | elif isinstance(level, str): 128 | allowed = ['silent', 'low', 'medium', 'high', 'highest'] 129 | if level.lower() in allowed: 130 | self.log_level = allowed.index(level.lower()) 131 | else: 132 | raise ValueError('String level should be silent, low, medium, high or highest.') 133 | self.section_level = None 134 | 135 | def write_to_file(self, f): 136 | if isinstance(f, str): 137 | self._f = open(f, 'w') 138 | elif isinstance(f, IOBase): 139 | self._f = f 140 | else: 141 | raise ValueError('File argument f should be a string representing a filename or a File instance') 142 | 143 | def section(self, label, level, timer=None): 144 | ''' 145 | Construct a section instance for use in with statements to control 146 | section printing and timing. 147 | ''' 148 | return Section(self, label, level, timer) 149 | 150 | def dump(self, message, new_line=True): 151 | if self.section_level<=self.log_level: 152 | if not self._active: 153 | self._active = True 154 | self.print_header() 155 | assert self.label is not None 156 | if new_line and self.add_blank_line: 157 | print('', file=self._f) 158 | self.add_blank_line = False 159 | line = '' 160 | for piece in splitstring(message, self.ll-self.mll): 161 | line += ' ' + self.label[:self.mll-2] + ' ' 162 | line += ' '*(self.mll-2 - len(self.label[:self.mll-2])) 163 | line += piece 164 | line += '\n' 165 | line = line.rstrip('\n') 166 | print(line, file=self._f) 167 | 168 | def warning(self, message, new_line=True): 169 | ''' 170 | Warnings are printed whenever log_level is higher than 0, i.e. not 171 | in silent mode. 172 | ''' 173 | if self.log_level>0: 174 | if not self._active: 175 | self._active = True 176 | self.print_header() 177 | assert self.label is not None 178 | if new_line and self.add_blank_line: 179 | print('', file=self._f) 180 | self.add_blank_line = False 181 | line = '' 182 | for piece in splitstring('WARNING: '+message, self.ll-self.mll): 183 | line += ' ' + self.label[:self.mll-2] + ' ' 184 | line += ' '*(self.mll-2 - len(self.label[:self.mll-2])) 185 | line += piece #.encode('utf-8') 186 | line += '\n' 187 | line = line.rstrip('\n') 188 | print(line, file=self._f) 189 | 190 | def print_header(self): 191 | if self.log_level>0: 192 | print(header, file=self._f) 193 | print('', file=self._f) 194 | mll = self.mll 195 | self.mll = 20 196 | with self.section('USER', 1): self.dump(getpass.getuser(), new_line=False) 197 | with self.section('MACHINE', 1): self.dump(' '.join(os.uname()), new_line=False) 198 | with self.section('TIME', 1): self.dump(datetime.datetime.now().isoformat().replace('T', ' '), new_line=False) 199 | with self.section('QUICKFF VERSION', 1): self.dump(version.replace('\n', ''), new_line=False) 200 | with self.section('PYTHON VERSION', 1): self.dump(sys.version.replace('\n', ''), new_line=False) 201 | with self.section('NUMPY VERSION', 1): self.dump(numpy.__version__, new_line=False) 202 | with self.section('SCIPY VERSION', 1): self.dump(scipy.__version__, new_line=False) 203 | with self.section('MATPLOTLIB VERSION', 1): self.dump(matplotlib.__version__, new_line=False) 204 | with self.section('CURRENT DIR', 1): self.dump(os.getcwd(), new_line=False) 205 | with self.section('COMMAND LINE', 1): self.dump(' '.join(sys.argv), new_line=False) 206 | self.mll = mll 207 | if self.log_level>0: 208 | print('', file=self._f) 209 | print('~'*80, file=self._f) 210 | 211 | def exit(self): 212 | if self._active: 213 | self.print_timetable() 214 | self.print_footer() 215 | self.close() 216 | 217 | def print_footer(self): 218 | if self.log_level>0: 219 | print(footer, file=self._f) 220 | 221 | def print_timetable(self): 222 | if self.log_level>0: 223 | print('~'*80, file=self._f) 224 | print('', file=self._f) 225 | with self.section('TIMING', 1): 226 | for label, time in self.timetable: 227 | line = '%30s ' %(label+' '*(30-len(label))) 228 | line += str(time) 229 | self.dump(line) 230 | 231 | def close(self): 232 | if isinstance(self._f, IOBase): 233 | self._f.close() 234 | 235 | 236 | log = Logger('medium') 237 | atexit.register(log.exit) 238 | -------------------------------------------------------------------------------- /quickff/paracontext.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | 27 | from __future__ import print_function, absolute_import 28 | 29 | ''' 30 | Convenience functions to enable using scoop. 31 | ''' 32 | 33 | __all__ = ['ParaContext', 'paracontext'] 34 | 35 | class FakeFuture(object): 36 | def __init__(self, fun, *args, **kargs): 37 | self.args = args 38 | self.kargs = kargs 39 | self._result = fun(*args, **kargs) 40 | 41 | def result(self): 42 | return self._result 43 | 44 | 45 | class ParaContext(object): 46 | def __init__(self): 47 | #initialize with serial version of map and submit by default 48 | self.use_stub() 49 | 50 | def use_stub(self): 51 | def my_map(fn, args, **kwargs): 52 | return [fn(arg, **kwargs) for arg in args] 53 | def my_wait_first(fs): 54 | return fs[:1], fs[1:] 55 | def debug_log(*args): 56 | with open('debug.log', 'a') as f: 57 | print(' '.join(str(arg) for arg in args), file=f) 58 | return 0 59 | self.map = my_map 60 | self.wait_first = my_wait_first 61 | self.submit = FakeFuture 62 | self.debug_log = debug_log 63 | 64 | def use_scoop(self): 65 | from scoop import futures 66 | def my_map(*args, **kwargs): 67 | return list(futures.map(*args, **kwargs)) 68 | def my_wait_first(fs): 69 | return futures.wait(fs, return_when=futures.FIRST_COMPLETED) 70 | def debug_log(*args): 71 | with open('debug.log', 'a') as f: 72 | print(' '.join(str(arg) for arg in args), file=f) 73 | return 0 74 | self.map = my_map 75 | self.wait_first = my_wait_first 76 | self.submit = futures.submit 77 | self.debug_log = debug_log 78 | 79 | 80 | paracontext = ParaContext() 81 | -------------------------------------------------------------------------------- /quickff/reference.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | 27 | from __future__ import absolute_import 28 | 29 | from yaff.pes.ff import ForceField, ForcePartValence, ForcePartPair 30 | from yaff.pes.ext import PairPotEI 31 | from yaff.pes.nlist import NeighborList 32 | from yaff.pes.scaling import Scalings 33 | from yaff.sampling.harmonic import estimate_cart_hessian 34 | 35 | from quickff.tools import global_translation, global_rotation 36 | from quickff.log import log 37 | 38 | from molmod.units import angstrom 39 | 40 | import numpy as np 41 | 42 | __all__ = ['SecondOrderTaylor', 'YaffForceField', 'get_ei_ff'] 43 | 44 | 45 | class Reference(object): 46 | ''' 47 | Abstract class for a model for reference data. A reference instance 48 | should be able to return energy, gradient and hessian for a given set 49 | of coordinates. 50 | ''' 51 | 52 | def __init__(self, name): 53 | self.name = name 54 | 55 | def energy(self, coords): 56 | raise NotImplementedError 57 | 58 | def gradient(self, coords): 59 | raise NotImplementedError 60 | 61 | def hessian(self, coords): 62 | raise NotImplementedError 63 | 64 | 65 | class SecondOrderTaylor(Reference): 66 | ''' 67 | Second-order Taylor expansion model, can be used for the ab initio input. 68 | ''' 69 | 70 | def __init__(self, name, coords=None, energy=0.0, grad=None, hess=None, pbc=[0,0,0]): 71 | log.dump('Initializing Second order taylor reference for %s' %name) 72 | self.coords0 = coords.copy() 73 | self.energy0 = energy 74 | self.grad0 = grad.copy() 75 | self.hess0 = hess.copy() 76 | assert np.all(np.array(pbc)==pbc[0]) and pbc[0] in [0,1], "PBC should be either all 0 or all 1" 77 | self.pbc = pbc 78 | self.phess0 = self._get_phess() 79 | super(SecondOrderTaylor, self).__init__(name) 80 | 81 | def update(self, coords=None, grad=None, hess=None, pbc=None): 82 | ''' 83 | Method to update one or more of the attributes. The meaning of the 84 | optional arguments is the same as with the constructor __init__ 85 | ''' 86 | if pbc is not None: 87 | assert np.all(np.array(pbc)==pbc[0]) and pbc[0] in [0,1], "PBC should be either all 0 or all 1" 88 | self.pbc == pbc 89 | if coords is not None: 90 | if self.coords0 is not None: 91 | assert self.coords0.shape == coords.shape 92 | self.coords0 = coords 93 | if grad is not None: 94 | if self.grad0 is not None: 95 | assert self.grad0.shape == grad.shape 96 | self.grad0 = grad 97 | if hess is not None: 98 | if self.hess0 is not None: 99 | assert self.hess0.shape == hess.shape 100 | self.hess0 = hess 101 | self.phess0 = self._get_phess() 102 | 103 | def _get_phess(self): 104 | ''' 105 | Constuct a hessian from which the translational and rotational 106 | degrees of freedom have been projected out. 107 | ''' 108 | hess = self.hess0.copy().reshape([np.prod(self.coords0.shape), np.prod(self.coords0.shape)]) 109 | VTx, VTy, VTz = global_translation(self.coords0) 110 | VRx, VRy, VRz = global_rotation(self.coords0) 111 | if np.all(np.array(self.pbc)==0): 112 | U, S, Vt = np.linalg.svd( 113 | np.array([VTx, VTy, VTz, VRx, VRy, VRz]).transpose() 114 | ) 115 | nproj = len([s for s in S if s>1e-6]) 116 | if nproj==5: 117 | log.dump('Only 5 out of the 6 trans-rot vectors were linearly independent. If the molecule is not linear, something went wrong!') 118 | elif not nproj==6: 119 | raise RuntimeError('Only %i of the 6 trans-rot vectors were linearly independent. Something went wrong!') 120 | elif np.all(np.array(self.pbc)==1): 121 | U = np.linalg.svd( 122 | np.array([VTx, VTy, VTz]).transpose() 123 | )[0] 124 | nproj = 3 125 | proj = np.dot(U[:, nproj:], U[:, nproj:].T) 126 | PHP = np.dot(proj, np.dot(hess, proj)) 127 | return PHP.reshape([self.coords0.shape[0], 3, self.coords0.shape[0], 3]) 128 | 129 | @classmethod 130 | def from_other_model(cls, model, coords0): 131 | energy0 = model.energy(coords0) 132 | grad0 = model.gradient(coords0).copy() 133 | hess0 = model.hessian(coords0).copy() 134 | name = model.name + ' (Harmonic)' 135 | if 'rvecs' in model.ff.system.__dict__: 136 | pbc = [1,1,1,] 137 | else: 138 | pbc = [0,0,0] 139 | return cls(name, coords=coords0, energy=energy0, grad=grad0, hess=hess0, pbc=pbc) 140 | 141 | def energy(self, coords): 142 | ''' 143 | Compute the energy for the given positions 144 | ''' 145 | assert np.all(coords.shape==self.coords0.shape) 146 | ndof = np.prod(self.coords0.shape) 147 | dx = (coords - self.coords0).reshape([ndof]) 148 | energy = self.energy0 + np.dot(self.grad0.reshape([ndof]), dx) 149 | energy += 0.5*np.dot(dx, np.dot(self.phess0.reshape([ndof,ndof]), dx)) 150 | return energy 151 | 152 | def gradient(self, coords): 153 | ''' 154 | Compute the gradient for the given positions 155 | ''' 156 | assert np.all(coords.shape==self.coords0.shape) 157 | ndof = np.prod(self.coords0.shape) 158 | dx = (coords - self.coords0).reshape([ndof]) 159 | grad = self.grad0.reshape([ndof]) + np.dot(self.phess0.reshape([ndof,ndof]), dx) 160 | return grad.reshape(self.coords0.shape) 161 | 162 | def hessian(self, coords): 163 | ''' 164 | Compute the hessian for the given positions 165 | ''' 166 | assert np.all(coords.shape==self.coords0.shape) 167 | return self.phess0.copy() 168 | 169 | 170 | class YaffForceField(Reference): 171 | ''' 172 | A model object based on a YAFF force field. Such a model can be used 173 | to account for non-covalent interactions or residual covalent 174 | interactions. 175 | ''' 176 | def __init__(self, name, ff): 177 | log.dump('Initializing Yaff force field reference for %s' %name) 178 | self.ff = ff 179 | Reference.__init__(self, name) 180 | 181 | def energy(self, coords): 182 | self.ff.update_pos(coords.copy()) 183 | return self.ff.compute() 184 | 185 | def gradient(self, coords): 186 | gpos = np.zeros(coords.shape, float) 187 | self.ff.update_pos(coords.copy()) 188 | energy = self.ff.compute(gpos=gpos) 189 | return gpos.reshape(coords.shape) 190 | 191 | def hessian(self, coords): 192 | self.ff.update_pos(coords.copy()) 193 | hess = estimate_cart_hessian(self.ff) 194 | natoms = len(coords) 195 | return hess.reshape([natoms, 3, natoms, 3]) 196 | 197 | 198 | def get_ei_ff(name, system, charges, scales, radii=None, average=True, pbc=[0,0,0]): 199 | ''' 200 | A routine to construct a Yaff force field for the electrostatics 201 | 202 | **Arguments** 203 | 204 | name 205 | A string for the name of the force field. This name will show in 206 | possible plots visualizing contributions along perturbation 207 | trajectories 208 | 209 | system 210 | A Yaff System instance representing the system 211 | 212 | charges 213 | A numpy array containing the charge of each separate atom 214 | 215 | scales 216 | A list of 4 floats, representing scale1, scale2, scale3, scale4, 217 | i.e. the electrostatic scaling factors 218 | 219 | **Optional Arguments** 220 | 221 | radii 222 | A numpy array containing the gaussian radii of each separate atom. 223 | If this argument is omitted, point charges are used. 224 | 225 | average 226 | If set to True, the charges and radii will first be averaged over 227 | atom types. This is True by default. 228 | ''' 229 | if not (np.array(pbc)==0).all(): 230 | raise NotImplementedError('Periodic system not implemented in get_ei_ff') 231 | if average: 232 | qs = {} 233 | rs = {} 234 | ffatypes = [system.ffatypes[i] for i in system.ffatype_ids] 235 | for i, atype in enumerate(ffatypes): 236 | if atype in qs: qs[atype].append(charges[i]) 237 | else: qs[atype] = [charges[i]] 238 | if radii is not None: 239 | if atype in rs: rs[atype].append(radii[i]) 240 | else: rs[atype] = [radii[i]] 241 | for i, atype in enumerate(ffatypes): 242 | charges[i] = np.array(qs[atype]).mean() 243 | if radii is not None: 244 | radii[i] = np.array(rs[atype]).mean() 245 | if radii is None: radii = np.zeros(len(system.ffatype_ids), float) 246 | if system.charges is None: system.charges = charges.copy() 247 | if system.radii is None: system.radii = radii.copy() 248 | pair_pot = PairPotEI(charges.astype(np.float), 0.0, 50*angstrom, None, 1.0, radii.astype(np.float)) 249 | nlist = NeighborList(system, 0) 250 | scalings = Scalings(system, scale1=scales[0], scale2=scales[1], scale3=scales[2], scale4=scales[3]) 251 | part = ForcePartPair(system, nlist, scalings, pair_pot) 252 | ff = ForceField(system, [part], nlist=nlist) 253 | return YaffForceField(name, ff) 254 | -------------------------------------------------------------------------------- /quickff/settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | 27 | from __future__ import print_function, absolute_import 28 | from io import IOBase 29 | from quickff.log import log 30 | from molmod.units import parse_unit 31 | import os 32 | 33 | try: 34 | from importlib.resources import path 35 | except ImportError: 36 | from importlib_resources import path 37 | 38 | 39 | __all__ = ['Settings'] 40 | 41 | 42 | def any_of(*checks): 43 | 'Any of the given checks should be satisfied' 44 | def check_one(key, value): 45 | for check in checks: 46 | try: 47 | check(key, value) 48 | return 49 | except IOError: 50 | pass 51 | raise IOError('Setting for key %s does not satisfy any of the requirements. Got %s' %(key, value)) 52 | return check_one 53 | 54 | 55 | def is_not_none(key, value): 56 | if value is None: 57 | raise IOError('Setting for key %s should be specified, is now None.' %(key)) 58 | 59 | 60 | def has_value(values): 61 | if values is None: return 62 | values = [v.lower() for v in values] 63 | def check(key, value): 64 | if value is None: return 65 | if value.lower() not in values: 66 | raise IOError('Setting for key %s should be one of %s. Got %s' %(key, str(values), value)) 67 | return check 68 | 69 | def is_larger_then(lbound): 70 | if lbound is None: return 71 | def check(key, value): 72 | if value is None: return 73 | if not value>lbound: 74 | raise IOError('Setting for key %s should be larger then %s. Got %s' %(key, str(lbound), str(value))) 75 | return check 76 | 77 | def is_float(key, value): 78 | if value is None: return 79 | try: 80 | value = float(value) 81 | except ValueError: 82 | raise IOError('Setting for key %s should be of type float. Got %s.' %(key, str(value))) 83 | 84 | def is_int(key, value): 85 | if value is None: return 86 | try: 87 | value = int(value) 88 | except ValueError: 89 | raise IOError('Setting for key %s should be of type int. Got %s.' %(key, str(value))) 90 | 91 | def is_bool(key, value): 92 | if not isinstance(value, bool): 93 | raise IOError('Setting for key %s should be of type bool. Got %s.' %(key, str(value))) 94 | 95 | 96 | def is_string(key, value): 97 | if value is None: return 98 | if not isinstance(value, str): 99 | raise IOError('Setting for key %s should be of type string. Got %s.' %(key, str(value))) 100 | 101 | 102 | def is_dictionary(key, value): 103 | if value is None: return 104 | if not isinstance(value, dict): 105 | raise IOError('Setting for key %s should be of type dictionary. Got %s.' %(key, str(value))) 106 | 107 | 108 | def is_list_strings(key, value): 109 | if value is None: return 110 | if ',' in value: 111 | value = value.split(',') 112 | for i,v in enumerate(value): 113 | if not isinstance(v,str): 114 | raise IOError('Setting for key %s should be a string or a list of strings. Element %i is %s.' %(key, i, v)) 115 | else: 116 | if not isinstance(value, str): 117 | raise IOError('Setting for key %s should be a string or a list of strings. Got %s.' %(key, str(value))) 118 | 119 | 120 | def is_nonexisting_file_name(key, value): 121 | if value is None: return 122 | if os.path.isfile(value): 123 | raise IOError('Setting for key %s should be non-existing file name, got %s which already exists.' %(key, value)) 124 | 125 | 126 | def is_existing_file_name(key, value): 127 | if value is None: return 128 | if not os.path.isfile(value): 129 | raise IOError('Setting for key %s should be existing file name, got %s which does not exist.' %(key, value)) 130 | 131 | 132 | key_checks = { 133 | 'fn_yaff' : [is_string, is_nonexisting_file_name], 134 | 'fn_charmm22_prm' : [is_string, is_nonexisting_file_name], 135 | 'fn_charmm22_psf' : [is_string, is_nonexisting_file_name], 136 | 'fn_sys' : [is_string, is_nonexisting_file_name], 137 | 'plot_traj' : [is_string, has_value(['None', 'Final', 'All'])], 138 | 'xyz_traj' : [is_bool], 139 | 'fn_traj' : [is_string], 140 | 'log_level' : [is_not_none, is_string, has_value(['silent','low','medium','high','highest'])], 141 | 'log_file' : [is_string, is_nonexisting_file_name], 142 | 'program_mode' : [is_not_none, has_value(['DeriveFF','MakeTrajectories','PlotTrajectories'])], 143 | 'only_traj' : [is_string], 144 | 'dont_traj' : [is_string], 145 | 'ffatypes' : [any_of(is_list_strings, has_value(['low', 'medium', 'high', 'highest']))], 146 | 'enforce_ffatypes' : [is_dictionary], 147 | 'ei' : [is_string, is_existing_file_name], 148 | 'ei_rcut' : [is_float], 149 | 'vdw' : [is_string, is_existing_file_name], 150 | 'vdw_rcut' : [is_float], 151 | 'covres' : [is_string, is_existing_file_name], 152 | 'excl_bonds' : [is_list_strings], 153 | 'excl_bends' : [is_list_strings], 154 | 'excl_dihs' : [is_list_strings], 155 | 'excl_oopds' : [is_list_strings], 156 | 'do_hess_mass_weighting': [is_bool], 157 | 'do_hess_negfreq_proj' : [is_bool], 158 | 'do_cross_svd' : [is_bool], 159 | 'cross_svd_rcond' : [is_float], 160 | 'pert_traj_tol' : [is_float], 161 | 'pert_traj_ntrials' : [is_int, is_larger_then(0)], 162 | 'pert_traj_scipysolver' : [is_string, has_value(['hybr', 'lm', 'broyden1', 'broyden2', 'anderson'])], 163 | 'pert_traj_energy_noise': [is_float], 164 | 'do_bonds' : [is_bool], 165 | 'do_bends' : [is_bool], 166 | 'do_dihedrals' : [is_bool], 167 | 'do_oops' : [is_bool], 168 | 'do_cross_ASS' : [is_bool], 169 | 'do_cross_ASA' : [is_bool], 170 | 'do_cross_DSS' : [is_bool], 171 | 'do_cross_DSD' : [is_bool], 172 | 'do_cross_DAA' : [is_bool], 173 | 'do_cross_DAD' : [is_bool], 174 | 'consistent_cross_rvs' : [is_bool], 175 | 'remove_dysfunctional_cross' : [is_bool], 176 | 'bond_term' : [is_not_none, is_string, has_value(['bondharm','bondfues','bondmm3'])], 177 | 'bend_term' : [is_not_none, is_string, has_value(['bendaharm','bendmm3'])], 178 | 'do_squarebend' : [is_bool], 179 | 'do_bendclin' : [is_bool], 180 | 'do_sqoopdist_to_oopdist': [is_bool], 181 | } 182 | 183 | 184 | def decode_enforce_ffatypes_dict(arg): 185 | d = {} 186 | if arg is None or arg.lower()=='none': 187 | return d 188 | if '{' in arg or '}' in arg: 189 | assert '{' in arg 190 | assert '}' in arg 191 | arg = arg.replace('{','').replace('{','') 192 | for entry in arg.split(','): 193 | if not ':' in entry: 194 | raise IOError('Setting for key enforce_ffatypes should be comma-seperated list of entries, each containing a colon. Entry %s does not!' %(entry)) 195 | words = entry.split(':') 196 | if not len(words)==2: 197 | raise IOError('Setting for key enforce_ffatypes should be comma-seperated list of entries, each containing one colon. Entry %s contains %i!' %(entry, len(words))) 198 | key, atype = words 199 | key = key.rstrip().lstrip() 200 | atype = atype.rstrip().lstrip() 201 | try: 202 | d[int(key)] = atype 203 | except ValueError: 204 | d[key] = atype 205 | return d 206 | 207 | 208 | decoders = { 209 | 'enforce_ffatypes' : decode_enforce_ffatypes_dict, 210 | } 211 | 212 | class Settings(object): 213 | 'Class to control the behaviour of a Quickff run' 214 | def __init__(self, fn=None, **kwargs): 215 | ''' 216 | **Keyword Arguments** 217 | 218 | fn 219 | file name of a config file from which settings can be read. 220 | Each line contains a single setting (except the lines starting 221 | with a #) and should have the following syntax 222 | 223 | key: value 224 | 225 | kwargs 226 | each setting can also be parsed directly through the use of 227 | keyword arguments in the __init__ constructor with the syntax 228 | key=value. The settings parsed through the use of kwargs 229 | overwrite those in the config file. 230 | 231 | ''' 232 | #first read general RC settings from .quickffrc file 233 | with path('quickff.data', 'quickffrc') as fn_default: 234 | self.read_config_file(fn_default) 235 | #if a config file is provided, read settings from this file and 236 | #overwrite the default RC settings 237 | if fn is not None: 238 | self.read_config_file(fn) 239 | #if settings are defined through keyword arguments to this init 240 | #constructor, read these settings and overwrite general RC as 241 | #wel as config file settings 242 | for key, value in kwargs.items(): 243 | #don't impose keyword argument that hasn't been set 244 | if value is None: continue 245 | key = key.lstrip().rstrip() 246 | if key=='suffix': 247 | continue 248 | self.set(key, value) 249 | if 'suffix' in list(kwargs.keys()) and kwargs['suffix'] is not None: 250 | self._set_suffix(kwargs['suffix']) 251 | self.check() 252 | self._set_log() 253 | 254 | with log.section('SETT', 2, 'Initializing'): 255 | self.dump_log() 256 | 257 | def read_config_file(self, fn): 258 | with open(fn, 'r') as f: 259 | for iline, line in enumerate(f.readlines()): 260 | line = line.split('#')[0].lstrip().rstrip().rstrip('\n') 261 | if len(line)==0: 262 | continue 263 | elif not ':' in line: 264 | raise IOError('Line %i in %s does not contain a colon' %(iline, fn)) 265 | else: 266 | words = line.split(':') 267 | key = words[0].lstrip().rstrip() 268 | value = ':'.join(words[1:]).lstrip().rstrip() 269 | if value.lower()=='none': 270 | value = None 271 | elif value.lower()=='true': 272 | value = True 273 | elif value.lower()=='false': 274 | value = False 275 | else: 276 | dtypes = [int, float] 277 | found_dtype = False 278 | for dtype in dtypes: 279 | try: 280 | value = dtype(value) 281 | found_dtype = True 282 | break 283 | except ValueError: 284 | try: 285 | value = parse_unit(value) 286 | found_dtype = True 287 | break 288 | except ValueError: 289 | pass 290 | self.set(key, value) 291 | 292 | def _set_suffix(self, suffix): 293 | for key, fn in self.__dict__.items(): 294 | if fn is None or not key.startswith('fn_') or key=='fn_traj': continue 295 | prefix, extension = fn.split('.') 296 | self.__dict__[key] = '%s%s.%s' %(prefix, suffix, extension) 297 | 298 | def _set_log(self): 299 | log.set_level(self.log_level) 300 | f = self.log_file 301 | if f is not None and (isinstance(f, str) or isinstance(f, IOBase)): 302 | log.write_to_file(f) 303 | 304 | def set(self, key, value): 305 | if key not in list(key_checks.keys()): 306 | IOError('Key %s is not allowed in settings routine' %key) 307 | if isinstance(value, str) and value.lower() in ['default']: 308 | return 309 | if key in decoders.keys(): 310 | value = decoders[key](value) 311 | self.__dict__[key] = value 312 | 313 | def check(self): 314 | for key, value in self.__dict__.items(): 315 | for check_function in key_checks[key]: 316 | check_function(key,value) 317 | 318 | def dump_log(self): 319 | sorted_keys = sorted(self.__dict__.keys()) 320 | with log.section('SETT', 3): 321 | for key in sorted_keys: 322 | value = str(self.__dict__[key]) 323 | log.dump('%s %s' %(key+' '*(30-len(key)), value)) 324 | 325 | def dump_file(self, fn): 326 | sorted_keys = sorted(self.__dict__.keys()) 327 | with open(fn, 'w') as f: 328 | for key in sorted_keys: 329 | value = str(self.__dict__[key]) 330 | print('%s: %s' %(key+' '*(30-len(key)), value), file=f) 331 | -------------------------------------------------------------------------------- /quickff/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | -------------------------------------------------------------------------------- /quickff/tests/common.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | from contextlib import contextmanager 27 | from glob import glob 28 | import os 29 | import shutil 30 | import tempfile 31 | 32 | import h5py as h5 33 | 34 | from quickff.io import read_abinitio 35 | 36 | from quickff.io import read_abinitio 37 | from quickff.reference import SecondOrderTaylor 38 | from quickff.valence import ValenceFF 39 | 40 | from yaff import System 41 | 42 | from quickff.log import log 43 | log.set_level('silent') 44 | 45 | try: 46 | from importlib.resources import path 47 | except ImportError: 48 | from importlib_resources import path 49 | 50 | 51 | __all__ = ['log', 'read_system', 'tmpdir'] 52 | 53 | def read_system(name): 54 | # Load system data 55 | dn = 'quickff.data.systems' 56 | if '/' in name: 57 | words = name.split('/') 58 | dn += '.%s' %('.'.join(words[:-1])) 59 | name = words[-1] 60 | with path(dn, name) as fn: 61 | numbers, coords, energy, grad, hess, masses, rvecs, pbc = read_abinitio(str(fn)) 62 | fns_wpart = glob(os.path.join(os.path.dirname(fn), 'gaussian_mbis.h5')) 63 | # Try to load charges. 64 | charges = None 65 | if len(fns_wpart) > 0: 66 | with h5.File(fns_wpart[0], 'r') as f: 67 | charges = f['charges'][:] 68 | # Create system object. 69 | system = System(numbers, coords, charges=charges) 70 | system.detect_bonds() 71 | system.set_standard_masses() 72 | # Load ab initio data. 73 | ai = SecondOrderTaylor('ai', coords=system.pos.copy(), energy=energy, grad=grad, hess=hess, pbc=pbc) 74 | return system, ai 75 | 76 | @contextmanager 77 | def tmpdir(name): 78 | """Create a temporary directory where output files of a test can be written to. 79 | 80 | The name argument can be used to obtained a recognizable test directory name. The 81 | temporary directory and its contents are automatically removed. 82 | """ 83 | dn = tempfile.mkdtemp(name) 84 | try: 85 | yield dn 86 | finally: 87 | shutil.rmtree(dn) 88 | -------------------------------------------------------------------------------- /quickff/tests/test_examples.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | import numpy as np 27 | import os 28 | 29 | from molmod.units import * 30 | from molmod.constants import lightspeed 31 | from molmod.periodic import periodic as pt 32 | from molmod.io import load_chk 33 | from yaff import System 34 | 35 | from quickff.tools import set_ffatypes 36 | from quickff.program import DeriveFF 37 | from quickff.settings import Settings 38 | from quickff.reference import SecondOrderTaylor 39 | 40 | from .common import log, read_system, tmpdir 41 | 42 | try: 43 | from importlib.resources import path 44 | except ImportError: 45 | from importlib_resources import path 46 | 47 | 48 | def test_h2(): 49 | #frequency of H2 stretch mode in gaussian.fchk calculation is 4416.656/cm 50 | #and an equilibrium bond length of 0.7442380 A. This test checks if the 51 | #force field predicts the same values 52 | r0 = 0.7442380*angstrom 53 | freq = (2*np.pi)*4416.65640485*lightspeed/centimeter 54 | mass = pt['H'].mass/2 #reduced mass for the H2 stretch mode 55 | #Load system, model and pert. theory and estimate ff 56 | with log.section('NOSETST', 2): 57 | system, ai = read_system('H2/gaussian.fchk') 58 | set_ffatypes(system, 'low') 59 | program = DeriveFF(system, ai, Settings()) 60 | program.do_pt_generate() 61 | program.do_pt_estimate() 62 | K_pt, rv_pt = program.valence.get_params(0, only='all') 63 | program.do_hc_estimatefc(['HC_FC_DIAG']) 64 | K_hc, rv_hc = program.valence.get_params(0, only='all') 65 | #print results 66 | print('') 67 | print('AI : K = %.3f kjmol/A^2 q0 = %.6f A' %(mass*freq**2/(kjmol/angstrom**2), r0/angstrom)) 68 | print('FF (PT): K = %.3f kjmol/A^2 q0 = %.6f A' %(K_pt/(kjmol/angstrom**2), rv_pt/angstrom)) 69 | print('FF (HC): K = %.3f kjmol/A^2 q0 = %.6f A' %(K_hc/(kjmol/angstrom**2), rv_hc/angstrom)) 70 | print('') 71 | #perform assertion checks 72 | assert abs(K_pt/(mass*freq**2)-1.0) < 1e-3 73 | assert abs(rv_pt/r0-1.0) < 1e-3 74 | assert abs(K_hc/(mass*freq**2)-1.0) < 1e-3 75 | assert abs(rv_hc/r0-1.0) < 1e-3 76 | assert abs(K_hc/K_pt-1.0) < 1e-6 77 | assert abs(rv_hc/rv_pt-1.0) < 1e-6 78 | 79 | 80 | def test_output_charmm22(): 81 | with log.section('NOSETST', 2): 82 | system, ai = read_system('ethanol/gaussian.fchk') 83 | set_ffatypes(system, 'low') 84 | with tmpdir('test_output_charmm22') as dn: 85 | fn_yaff = os.path.join(dn, 'pars_cov.txt') 86 | fn_charmm22_prm = os.path.join(dn, 'test.prm') 87 | fn_charmm22_psf = os.path.join(dn, 'test.psf') 88 | fn_sys = os.path.join(dn, 'system.chk') 89 | settings = Settings( 90 | do_cross_ASS=False, do_cross_ASA=False, 91 | fn_yaff=fn_yaff, fn_sys=fn_sys, 92 | fn_charmm22_prm=fn_charmm22_prm, 93 | fn_charmm22_psf=fn_charmm22_psf, 94 | ) 95 | program = DeriveFF(system, ai, settings) 96 | program.run() 97 | assert os.path.isfile(fn_yaff) 98 | assert os.path.isfile(fn_charmm22_prm) 99 | assert os.path.isfile(fn_charmm22_psf) 100 | assert os.path.isfile(fn_sys) 101 | 102 | # Count the number of BOND, ANGLES and DIHEDRAL lines in the PRM file. 103 | counts = {} 104 | with open(fn_charmm22_prm, 'r') as f: 105 | for line in f: 106 | print(line) 107 | line = line[:line.find('!')].strip() 108 | if len(line) == 0: 109 | continue 110 | if line in ['BONDS','ANGLES', 'DIHEDRALS', 'IMPROPER']: 111 | key = line 112 | counts[key] = 0 113 | else: 114 | counts[key] += 1 115 | assert counts['BONDS'] == 4 116 | assert counts['ANGLES'] == 5 117 | assert counts['DIHEDRALS'] == 3 118 | assert counts['IMPROPER'] == 0 119 | 120 | # Count the number atoms, bonds, angles and dihedrals in the PSF file and 121 | # check for consistency. 122 | with open(fn_charmm22_psf, 'r') as f: 123 | natom = 0 124 | assert next(f) == 'PSF\n' 125 | for line in f: 126 | if '!NATOM' in line: 127 | natom = int(line.split()[0]) 128 | break 129 | assert natom == system.natom 130 | for iatom in range(natom+1): 131 | next(f) 132 | line = next(f) 133 | assert '!NBOND: bonds' in line 134 | nbond = int(line.split()[0]) 135 | nline = int(np.ceil(nbond/4.0)) 136 | numbers = (''.join([next(f) for iline in range(nline)])).split() 137 | assert len(numbers) == nbond*2 138 | next(f) 139 | line = next(f) 140 | assert '!NTHETA: angles' in line 141 | ntheta = int(line.split()[0]) 142 | nline = int(np.ceil(ntheta/3.0)) 143 | numbers = (''.join([next(f) for iline in range(nline)])).split() 144 | assert len(numbers) == ntheta*3 145 | next(f) 146 | line = next(f) 147 | assert '!NPHI: dihedrals' in line 148 | nphi = int(line.split()[0]) 149 | nline = int(np.ceil(nphi/2.0)) 150 | numbers = (''.join([next(f) for iline in range(nline)])).split() 151 | assert len(numbers) == nphi*4 152 | next(f) 153 | line = next(f) 154 | assert '!NIMPHI: impropers' in line 155 | nimphi = int(line.split()[0]) 156 | assert nimphi == 0 157 | 158 | def compare_crossterm_rest_values(program,equal=True): 159 | print("%50s %15s %15s %15s"%("Basename","Cross RV","Diag RV","Delta")) 160 | for term in program.valence.terms: 161 | if not term.is_master(): continue 162 | if term.basename.startswith('Cross'): 163 | for i in [0,1]: 164 | rv0 = program.valence.get_params(term.index, only='rv%d'%i) 165 | if program.valence.terms[term.diag_term_indexes[i]].basename.startswith('Tors'): 166 | rv0_diag = -program.valence.get_params(term.diag_term_indexes[i], only='sign') 167 | assert (rv0==rv0_diag) # Torsion rest values are always the same 168 | else: 169 | rv0_diag = program.valence.get_params(term.diag_term_indexes[i], only='rv') 170 | assert (rv0==rv0_diag)==equal # Other rest values are only the 171 | # same if consistent_cross_rvs was set to True 172 | print("%50s %15.6f %15.6f %+15.2e" % (term.basename,rv0,rv0_diag,rv0-rv0_diag)) 173 | 174 | def test_benzene_consistent_crossterms(): 175 | with log.section('NOSETEST', 2): 176 | system, ai = read_system('benzene/gaussian.fchk') 177 | set_ffatypes(system, 'high') 178 | for consistent in [False, True]: 179 | with tmpdir('test_benzene_%s'%('consistent' if consistent else 'inconsistent')) as dn: 180 | fn_yaff = os.path.join(dn, 'pars_cov.txt') 181 | fn_sys = os.path.join(dn, 'system.chk') 182 | program = DeriveFF(system, ai, Settings(consistent_cross_rvs=consistent, 183 | fn_yaff=fn_yaff,fn_sys=fn_sys,do_cross_DSS=True,do_cross_DSD=True, 184 | do_cross_DAA=True,do_cross_DAD=True)) 185 | program.run() 186 | compare_crossterm_rest_values(program,equal=consistent) 187 | 188 | def test_methane_consistent_crossterms(): 189 | with log.section('NOSETEST', 2): 190 | system, ai = read_system('methane/gaussian.fchk') 191 | set_ffatypes(system, 'high') 192 | for consistent in [False, True]: 193 | with tmpdir('test_methane_%s'%('consistent' if consistent else 'inconsistent')) as dn: 194 | fn_yaff = os.path.join(dn, 'pars_cov.txt') 195 | fn_sys = os.path.join(dn, 'system.chk') 196 | program = DeriveFF(system, ai, Settings(consistent_cross_rvs=consistent, 197 | fn_yaff=fn_yaff,fn_sys=fn_sys,do_cross_DSS=True,do_cross_DSD=True, 198 | do_cross_DAA=True,do_cross_DAD=True)) 199 | program.run() 200 | compare_crossterm_rest_values(program,equal=consistent) 201 | 202 | def test_uio66zrbrick_crossterms(): 203 | with log.section('NOSETEST', 2): 204 | # Load input data for a ficticious system of an isolated 205 | # UiO-66 brick 206 | with path('quickff.data.systems.uio66-zr-brick', 'system.chk') as fn: 207 | data = load_chk(fn) 208 | system = System(data['numbers'],data['pos'],charges=data['charges'], 209 | ffatypes=data['ffatypes'],bonds=data['bonds'],radii=data['radii']) 210 | system.set_standard_masses() 211 | ai = SecondOrderTaylor('ai', coords=system.pos.copy(), 212 | grad=data['gradient'], hess=data['hessian']) 213 | # Run QuickFF 214 | with tmpdir('test_uio66') as dn: 215 | fn_yaff = os.path.join(dn, 'pars_cov.txt') 216 | fn_sys = os.path.join(dn, 'system.chk') 217 | fn_log = os.path.join(dn, 'quickff.log') 218 | program = DeriveFF(system, ai, Settings(consistent_cross_rvs=True, 219 | remove_dysfunctional_cross=True,fn_yaff=fn_yaff,fn_sys=fn_sys,log_file=fn_log)) 220 | program.run() 221 | # Check force constants of cross terms and corresponding diagonal terms 222 | print("%50s %15s %15s"%("Basename","Cross FC","Diag FC")) 223 | for term in program.valence.terms: 224 | if not term.is_master(): continue 225 | if term.basename.startswith('Cross'): 226 | fc = program.valence.get_params(term.index, only='fc') 227 | for i in [0,1]: 228 | fc_diag = program.valence.get_params(term.diag_term_indexes[i], only='fc') 229 | print("%50s %15.6f %15.6f %50s" % (term.basename,fc,fc_diag,program.valence.terms[term.diag_term_indexes[i]].basename)) 230 | if fc_diag==0.0: assert fc==0.0 231 | -------------------------------------------------------------------------------- /quickff/tests/test_reference.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 3 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | from molmod.units import angstrom, kjmol 27 | 28 | from .common import log, read_system 29 | 30 | from nose import SkipTest 31 | 32 | import numpy as np 33 | 34 | def do_taylor(name, ntests=10, eps=1e-4, gtol=1e-3*kjmol/angstrom, htol=1e-3*kjmol/angstrom**2): 35 | with log.section('NOSETST', 2): 36 | system, ref = read_system(name) 37 | print('') 38 | for i in range(ntests): 39 | npos = system.pos + np.random.normal(0.0, 0.1, system.pos.shape)*angstrom 40 | gref = ref.gradient(npos) 41 | gnum = np.zeros(3*len(system.numbers), float) 42 | for j in range(3*len(system.numbers)): 43 | dx = np.zeros(3*len(system.numbers), float) 44 | dx[j] = 1.0 45 | dx = dx.reshape(npos.shape) 46 | eplus = ref.energy(npos + eps*dx) 47 | emin = ref.energy(npos - eps*dx) 48 | gnum[j] = (eplus-emin)/(2.0*eps) 49 | std = gref.std() 50 | M = (abs(gref-gnum.reshape(gref.shape))).max() 51 | print(' Sample %i: STD=%.6e MaxDev=%.6e' %(i, std/(kjmol/angstrom), M/(kjmol/angstrom))) 52 | assert M 4 | # Steven Vandenbrande , 5 | # Jelle Wieme , 6 | # Toon Verstraelen , Center for Molecular Modeling 7 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 8 | # stated. 9 | # 10 | # This file is part of QuickFF. 11 | # 12 | # QuickFF is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU General Public License 14 | # as published by the Free Software Foundation; either version 3 15 | # of the License, or (at your option) any later version. 16 | # 17 | # QuickFF is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program; if not, see 24 | # 25 | #-- 26 | from molmod.units import angstrom, kjmol, rad, deg 27 | from molmod.ic import _dihed_angle_low, dihed_angle 28 | 29 | from quickff.valence import ValenceFF 30 | from quickff.settings import Settings 31 | from quickff.tools import set_ffatypes 32 | 33 | from itertools import permutations 34 | 35 | from .common import log, read_system 36 | 37 | import numpy as np 38 | 39 | def check_terms(name): 40 | 'Check whether all ICs are present in ValenceFF instance' 41 | #TODO: CROSS terms 42 | with log.section('NOSETST', 2): 43 | system, ref = read_system(name) 44 | set_ffatypes(system, 'high') 45 | valence = ValenceFF(system, Settings()) 46 | #check if every bond is present and harmonic 47 | for bond in system.iter_bonds(): 48 | found = False 49 | for term in valence.iter_terms('BONDHARM'): 50 | at0, at1 = term.get_atoms() 51 | if bond[0]==at0 and bond[1]==at1 \ 52 | or bond[0]==at1 and bond[1]==at0: 53 | assert not found, 'BondHarm term %s was already found!' %str(bond) 54 | found = True 55 | assert found, 'No BondHarm term found for bond %s' %str(bond) 56 | #check if every bend is present 57 | for angle in system.iter_angles(): 58 | found = False 59 | for term in valence.iter_terms('BENDAHARM'): 60 | at0, at1, at2 = term.get_atoms() 61 | if angle[0]==at0 and angle[1]==at1 and angle[2]==at2 \ 62 | or angle[0]==at2 and angle[1]==at1 and angle[2]==at0: 63 | assert not found, 'BendAHarm term %s was already found!' %str(angle) 64 | found = True 65 | assert found, 'No BendAHarm term found for bond %s' %str(angle) 66 | #check if every dihedral is present 67 | for dihed in system.iter_dihedrals(): 68 | found = False 69 | for term in valence.iter_terms('Tors'): 70 | at0, at1, at2, at3 = term.get_atoms() 71 | if dihed[0]==at0 and dihed[1]==at1 and dihed[2]==at2 and dihed[3]==at3\ 72 | or dihed[0]==at3 and dihed[1]==at2 and dihed[2]==at1 and dihed[3]==at0: 73 | assert not found, 'Torsion term %s was already found!' %str(dihed) 74 | found = True 75 | assert found, 'No Torsion term found for bond %s' %str(dihed) 76 | #check if every oop distance is present and Harm for rv of 0 and SQHARM else 77 | for oop in system.iter_oops(): 78 | found = False 79 | for term in valence.iter_terms('^OOPDIST/.*$', use_re=True): 80 | at0, at1, at2, at3 = term.get_atoms() 81 | for p0, p1, p2 in permutations([at0, at1, at2]): 82 | if oop[0]==p0 and oop[1]==p1 and oop[2]==p2 and oop[3]==at3: 83 | assert not found, 'OopDist term %s was already found!' %str(oop) 84 | found = True 85 | for term in valence.iter_terms('SQOOPDIST'): 86 | at0, at1, at2, at3 = term.get_atoms() 87 | for p0, p1, p2 in permutations([at0, at1, at2]): 88 | if oop[0]==p0 and oop[1]==p1 and oop[2]==p2 and oop[3]==at3: 89 | assert not found, 'SqOopDist term %s was already found!' %str(oop) 90 | found = True 91 | assert found, 'No (Sq)OopDist term found for bond %s (which is %s)' %( 92 | str(oop), 93 | ' '.join([system.ffatypes[system.ffatype_ids[i]] for i in [at0,at1,at2,at3]]) 94 | ) 95 | 96 | def get_analytic_numeric_hessian(valence, term, **ffpars): 97 | #setup ff 98 | valence.set_params(term.index, **ffpars) 99 | for term2 in valence.iter_terms(): 100 | assert len(term2.slaves)==0 101 | if term2.index!=term.index: 102 | valence.set_params(term2.index, rv0=0.0, fc=0.0) 103 | #compute hcov using built-in function (which uses yaff routine) 104 | ref = valence.get_hessian_contrib(term.index) 105 | #compute hcov numerically using valence.calc_energy 106 | eps = 1e-4 107 | natoms = len(valence.system.pos) 108 | num = np.zeros([3*natoms, 3*natoms], float) 109 | for i in range(3*natoms): 110 | Di = np.zeros(3*natoms, float) 111 | Di[i] = eps 112 | Di = Di.reshape([natoms, 3]) 113 | for j in range(3*natoms): 114 | Dj = np.zeros(3*natoms, float) 115 | Dj[j] = eps 116 | Dj = Dj.reshape([natoms, 3]) 117 | tmp = valence.calc_energy(valence.system.pos + Di + Dj) 118 | tmp -= valence.calc_energy(valence.system.pos + Di - Dj) 119 | tmp -= valence.calc_energy(valence.system.pos - Di + Dj) 120 | tmp += valence.calc_energy(valence.system.pos - Di - Dj) 121 | num[i,j] = tmp/(2.0*eps)**2 122 | num = 0.5*(num+num.T) 123 | return ref, num 124 | 125 | def get_indices_zero_nonzero(term, natoms): 126 | ''' 127 | Return list of index tuples inonzero and izero: 128 | inonzero: index tuples for which term contributes to the corresponding 129 | Hessian element 130 | izero : index tuples for which term does not contribute to the 131 | corresponding Hessian element 132 | ''' 133 | inonzero = [[],[]] 134 | izero = [[],[]] 135 | for i in range(natoms): 136 | iindices = [3*i,3*i,3*i, 3*i+1,3*i+1,3*i+1, 3*i+2,3*i+2,3*i+2] 137 | for j in range(natoms): 138 | jindices = [3*j,3*j+1,3*j+2, 3*j,3*j+1,3*j+2, 3*j,3*j+1,3*j+2] 139 | if i in term.get_atoms() and j in term.get_atoms(): 140 | inonzero[0] += iindices 141 | inonzero[1] += jindices 142 | else: 143 | izero[0] += iindices 144 | izero[1] += jindices 145 | return inonzero, izero 146 | 147 | def get_dihedral_angle(term, system): 148 | dihed = term.get_atoms() 149 | if system.cell.nvec>0: 150 | d10 = system.pos[dihed[0]] - system.pos[dihed[1]] 151 | d12 = system.pos[dihed[2]] - system.pos[dihed[1]] 152 | d23 = system.pos[dihed[3]] - system.pos[dihed[2]] 153 | system.cell.mic(d10) 154 | system.cell.mic(d12) 155 | system.cell.mic(d23) 156 | return _dihed_angle_low(d10, d12, d23, 0)[0] 157 | else: 158 | rs = np.array([system.pos[j] for j in dihed]) 159 | return dihed_angle(rs)[0] 160 | 161 | def check_hessian_bonds(name, tol=1e-3*kjmol/angstrom**2): 162 | with log.section('NOSETST', 2): 163 | system, ref = read_system(name) 164 | set_ffatypes(system, 'highest') 165 | valence = ValenceFF(system, Settings()) 166 | for term in valence.iter_terms('BONDHARM'): 167 | inonzero, izero = get_indices_zero_nonzero(term, len(system.numbers)) 168 | rv = np.random.uniform(low=1.00, high=2.00)*angstrom 169 | fc = np.random.uniform(low=1000, high=3000)*kjmol/angstrom**2 170 | ref, num = get_analytic_numeric_hessian(valence, term, fc=fc, rv0=rv) 171 | #assert that hessian elements of atoms not part of the current bond 172 | #are zero 173 | if len(izero[0])>0: 174 | assert (abs(ref[izero])).max()<1e-12*kjmol/angstrom**2 175 | assert (abs(num[izero])).max()<1e-12*kjmol/angstrom**2 176 | M = (abs(ref-num)).max() 177 | iM, jM = np.where(abs(ref-num)==M)[0][0], np.where(abs(ref-num)==M)[1][0] 178 | print('%25s (random FC=%8.3f kjmol/A^2 RV=%7.3f A ): MaxDev(%2i,%2i)=%.3e kjmol/A^2' %(term.basename, fc/(kjmol/angstrom**2), rv/angstrom, iM, jM, M/(kjmol/angstrom**2))) 179 | assert M0: 195 | assert (abs(ref[izero])).max()<1e-12*kjmol/angstrom**2 196 | assert (abs(num[izero])).max()<1e-12*kjmol/angstrom**2 197 | M = (abs(ref-num)).max() 198 | iM, jM = np.where(abs(ref-num)==M)[0][0], np.where(abs(ref-num)==M)[1][0] 199 | print('%25s (random FC=%8.3f kjmol/rad^2 RV=%7.3f deg): MaxDev(%2i,%2i)=%.3e kjmol/A^2' %(term.basename, fc/(kjmol/rad**2), rv/deg, iM, jM, M/(kjmol/angstrom**2))) 200 | assert M0: 218 | assert (abs(ref[izero])).max()<1e-12*kjmol/angstrom**2 219 | assert (abs(num[izero])).max()<1e-12*kjmol/angstrom**2 220 | M = (abs(ref-num)).max() 221 | iM, jM = np.where(abs(ref-num)==M)[0][0], np.where(abs(ref-num)==M)[1][0] 222 | print('%25s (eq=%.1f deg random FC=%8.3f kjmol RV=%7.3f deg): MaxDev(%2i,%2i)=%.3e kjmol/A^2' %( 223 | term.basename, psi0/deg, fc/kjmol, rv/deg, iM, jM, M/(kjmol/angstrom**2) 224 | )) 225 | assert M0: 241 | assert (abs(ref[izero])).max()<1e-12*kjmol/angstrom**2 242 | assert (abs(num[izero])).max()<1e-12*kjmol/angstrom**2 243 | M = (abs(ref-num)).max() 244 | iM, jM = np.where(abs(ref-num)==M)[0][0], np.where(abs(ref-num)==M)[1][0] 245 | print('%25s (random FC=%8.3f kjmol/A^2 RV=%7.3f A ): MaxDev(%2i,%2i)=%.3e kjmol/A^2' %( 246 | term.basename, fc/(kjmol/angstrom**2), rv/angstrom, iM, jM, M/(kjmol/angstrom**2) 247 | )) 248 | assert M0: 258 | assert (abs(ref[izero])).max()<1e-12*kjmol/angstrom**2 259 | assert (abs(num[izero])).max()<1e-12*kjmol/angstrom**2 260 | M = (abs(ref-num)).max() 261 | iM, jM = np.where(abs(ref-num)==M)[0][0], np.where(abs(ref-num)==M)[1][0] 262 | print('%25s (random FC=%8.3f kjmol/A^4 RV=%7.3f A^2): MaxDev(%2i,%2i)=%.3e kjmol/A^2' %(term.basename, fc/(kjmol/angstrom**4), rv/angstrom**2, iM, jM, M/(kjmol/angstrom**2))) 263 | assert M 5 | # Steven Vandenbrande , 6 | # Jelle Wieme , 7 | # Toon Verstraelen , Center for Molecular Modeling 8 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 9 | # stated. 10 | # 11 | # This file is part of QuickFF. 12 | # 13 | # QuickFF is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU General Public License 15 | # as published by the Free Software Foundation; either version 3 16 | # of the License, or (at your option) any later version. 17 | # 18 | # QuickFF is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | # GNU General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU General Public License 24 | # along with this program; if not, see 25 | # 26 | #-- 27 | 28 | from quickff.scripts import qff_input_ei 29 | 30 | if __name__=='__main__': 31 | qff_input_ei() 32 | -------------------------------------------------------------------------------- /scripts/qff.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 4 | # Copyright (C) 2012 - 2018 Louis Vanduyfhuys 5 | # Steven Vandenbrande , 6 | # Jelle Wieme , 7 | # Toon Verstraelen , Center for Molecular Modeling 8 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 9 | # stated. 10 | # 11 | # This file is part of QuickFF. 12 | # 13 | # QuickFF is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU General Public License 15 | # as published by the Free Software Foundation; either version 3 16 | # of the License, or (at your option) any later version. 17 | # 18 | # QuickFF is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | # GNU General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU General Public License 24 | # along with this program; if not, see 25 | # 26 | #-- 27 | 28 | from quickff.scripts import qff 29 | from quickff.paracontext import paracontext 30 | import sys 31 | 32 | #Set the parallel context if scoop is enabled. This should be performed outside 33 | #the __main__ block to ensure the set the context for all workers. 34 | if '--scoop' in sys.argv[1:]: 35 | paracontext.use_scoop() 36 | 37 | if __name__=='__main__': 38 | qff() 39 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # QuickFF is a code to quickly derive accurate force fields from ab initio input. 4 | # Copyright (C) 2012 - 2019 Louis Vanduyfhuys 5 | # Steven Vandenbrande , 6 | # Jelle Wieme , 7 | # Toon Verstraelen , Center for Molecular Modeling 8 | # (CMM), Ghent University, Ghent, Belgium; all rights reserved unless otherwise 9 | # stated. 10 | # 11 | # This file is part of QuickFF. 12 | # 13 | # QuickFF is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU General Public License 15 | # as published by the Free Software Foundation; either version 3 16 | # of the License, or (at your option) any later version. 17 | # 18 | # QuickFF is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | # GNU General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU General Public License 24 | # along with this program; if not, see 25 | # 26 | #-- 27 | 28 | #from __future__ import print_function 29 | 30 | #from glob import glob 31 | #import os, sys 32 | #from distutils.core import setup 33 | from setuptools import setup 34 | #from distutils.command.install_data import install_data 35 | 36 | #class my_install_data(install_data): 37 | # """Add a share_dir.txt file that points to the root for the shared files. 38 | # It is otherwise impossible to figure out the location of these data 39 | # files at runtime. 40 | # """ 41 | # def run(self): 42 | # # Do the normal install_data 43 | # install_data.run(self) 44 | # # Create the file share_dir.txt. It's exact content is only known 45 | # at installation time. 46 | # dist = self.distribution 47 | # libdir = dist.command_obj["install_lib"].install_dir 48 | # for name in dist.packages: 49 | # if '.' not in name: 50 | # destination = os.path.join(libdir, name, "share_dir.txt") 51 | # print("Creating %s" % destination) 52 | # if not self.dry_run: 53 | # f = open(destination, "w") 54 | # print(self.install_dir, file=f) 55 | # f.close() 56 | 57 | #def find_all_data_files(dn): 58 | # result = [] 59 | # for root, dirs, files in os.walk(dn): 60 | # if len(files) > 0: 61 | # files = [os.path.join(root, fn) for fn in files] 62 | # result.append(('share/quickff/' + root[6:], files)) 63 | # return result 64 | 65 | setup( 66 | name='QuickFF', 67 | version='2.2.8', 68 | description='Python library to quickly derive force fields from ab initio training data.', 69 | author='Louis Vanduyfhuys', 70 | author_email='Louis.Vanduyfhuys@UGent.be', 71 | url='https://github.com/molmod/QuickFF', 72 | package_dir = {'quickff': 'quickff'}, 73 | packages=['quickff', 'quickff.data', 'quickff.tests'], 74 | #cmdclass = {'install_data': my_install_data}, 75 | #data_files=find_all_data_files('share'), 76 | include_package_data=True, 77 | scripts=['scripts/qff.py', 'scripts/qff-input-ei.py'], 78 | classifiers=[ 79 | 'Development Status :: 3 - Alpha', 80 | 'Environment :: Console', 81 | 'Intended Audience :: Science/Research', 82 | 'License :: OSI Approved :: GNU General Public License (GPL)', 83 | 'Operating System :: POSIX :: Linux', 84 | 'Programming Language :: Python', 85 | 'Topic :: Science/Engineering :: Molecular Science' 86 | ], 87 | install_requires=['numpy>=1.0', 88 | 'importlib_resources; python_version < "3.7"'], 89 | ) 90 | -------------------------------------------------------------------------------- /updatesite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git checkout githubmaster && ( 3 | ./setup.py install --user 4 | ./cleanfiles.sh 5 | ( 6 | cd doc 7 | make html 8 | cd _build/html 9 | touch .nojekyll 10 | ) 11 | git checkout gh-pages && ( 12 | git rm $(git ls-tree $(git log --color=never | head -n1 | cut -f2 -d' ') -r --name-only) 13 | cp -rv doc/_build/html/* doc/_build/html/.* . 14 | for f in $(find doc/_build/html | cut -c17-); do 15 | echo Adding $f 16 | git add $f 17 | done 18 | git commit -a -m 'Automatic documentation update' 19 | git push github gh-pages:gh-pages 20 | ) 21 | ) && git checkout githubmaster 22 | --------------------------------------------------------------------------------