├── .coveragerc ├── .github └── workflows │ ├── build.yml │ └── ruff.yml ├── .gitignore ├── .readthedocs.yaml ├── .ruff.toml ├── .zenodo.json ├── LICENSE ├── README.md ├── changelog.md ├── docs ├── .gitignore ├── Makefile ├── requirements.txt └── source │ ├── conf.py │ ├── examples │ ├── data │ │ └── NaCl_800K_MD_XDATCAR │ └── rdfs.ipynb │ ├── index.rst │ ├── modules.rst │ └── modules │ ├── atom.rst │ ├── calculation.rst │ ├── cell.rst │ ├── configuration.rst │ ├── doscar.rst │ ├── grid.rst │ ├── kpoints.rst │ ├── optics.rst │ ├── outcar.rst │ ├── pimaim.rst │ ├── polyhedron.rst │ ├── poscar.rst │ ├── procar.rst │ ├── rdf.rst │ ├── summary.rst │ ├── vaspmeta.rst │ ├── vasppy.data.rst │ └── xdatcar.rst ├── requirements.txt ├── setup.py ├── tests ├── __init__.py ├── test_atom.py ├── test_band.py ├── test_calculation.py ├── test_cell.py ├── test_data │ ├── PROCAR_spin_polarised_test │ ├── PROCAR_test │ └── vasp_summary_test.yaml ├── test_doscar.py ├── test_kpoints.py ├── test_neighbour_list.py ├── test_optics.py ├── test_outcar.py ├── test_poscar.py ├── test_procar.py ├── test_rdf.py ├── test_summary.py ├── test_utils.py ├── test_vaspmeta.py ├── test_vasprun.py └── test_xdatcar.py └── vasppy ├── __init__.py ├── atom.py ├── band.py ├── calculation.py ├── cell.py ├── data ├── GGA_md5.yaml ├── GGA_nelect.yaml ├── LDA_52_md5.yaml ├── LDA_52_nelect.yaml ├── LDA_54_md5.yaml ├── LDA_54_nelect.yaml ├── LDA_54r_md5.yaml ├── LDA_54r_nelect.yaml ├── LDA_md5.yaml ├── LDA_nelect.yaml ├── PBE_52_md5.yaml ├── PBE_52_nelect.yaml ├── PBE_54_md5.yaml ├── PBE_54_nelect.yaml ├── PBE_54r_md5.yaml ├── PBE_54r_nelect.yaml ├── PBE_md5.yaml ├── PBE_nelect.yaml ├── USPP_GGA_md5.yaml ├── USPP_GGA_nelect.yaml ├── USPP_LDA_md5.yaml ├── USPP_LDA_nelect.yaml ├── __init__.py └── potcar_data.py ├── doscar.py ├── grid.py ├── kpoints.py ├── neighbour_list.py ├── optics.py ├── outcar.py ├── pimaim.py ├── polyhedron.py ├── poscar.py ├── procar.py ├── rdf.py ├── scripts ├── __init__.py ├── check_species.py ├── checkforce.py ├── convergence_testing.py ├── effective_mass.py ├── fat_bands.py ├── murnfit.py ├── pimaim_to_poscar.py ├── pimaim_to_xtl.py ├── poscar_to_cif.py ├── poscar_to_pimaim.py ├── poscar_to_xtl.py ├── potcar_spec.py ├── proc_poscar.py ├── r2r2_expansion.py ├── rotate_poscar.py ├── spacegroup.py ├── vasp_grid.py ├── vasp_summary.py ├── xdatcar_to_disp.py └── xdatcar_to_rdf.py ├── summary.py ├── units.py ├── utils.py ├── vaspmeta.py ├── vasprun.py ├── version.py └── xdatcar.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = vasppy 3 | omit = 4 | */python?.?/* 5 | */lib-python/?.?/*.py 6 | */lib_pypy/_*.py 7 | */site-packages/ordereddict.py 8 | */site-packages/nose/* 9 | */unittest2/* 10 | docs 11 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | # Controls when the action will run. 4 | on: [push, pull_request] 5 | 6 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 7 | jobs: 8 | tests: 9 | runs-on: ubuntu-latest 10 | timeout-minutes: 30 11 | strategy: 12 | matrix: 13 | python-version: ['3.9', '3.10', '3.11', '3.12'] 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Set up Python ${{matrix.python-version}} 17 | uses: actions/setup-python@v2 18 | with: 19 | python-version: ${{matrix.python-version}} 20 | - name: Install Python dependencies 21 | run: | 22 | pip install --upgrade pip 23 | pip install -r requirements.txt 24 | pip install -U numpy 25 | pip install mypy 26 | pip install types-PyYAML 27 | pip install pytest 28 | pip install pytest-cov 29 | pip install pylint 30 | pip install . 31 | pip list 32 | - name: Run tests 33 | run: | 34 | pytest --cov-config=.coveragerc --cov=vasppy --cov-report lcov 35 | - name: Coveralls GitHub Action 36 | uses: coverallsapp/github-action@v2 37 | with: 38 | file: ./coverage.lcov 39 | github-token: ${{ secrets.GITHUB_TOKEN }} 40 | - name: Static type checking 41 | run: | 42 | mypy vasppy 43 | - name: PyLint 44 | run: | 45 | pylint --errors-only vasppy 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/ruff.yml: -------------------------------------------------------------------------------- 1 | name: Ruff 2 | on: [push, pull_request] 3 | jobs: 4 | ruff: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v3 8 | - uses: chartboost/ruff-action@v1 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | __pycache__ 3 | MANIFEST 4 | /dist 5 | *.pyc 6 | *.swp 7 | .coverage 8 | /tests/.coverage 9 | .python-version 10 | /build 11 | /vasppy.egg-info 12 | /docs/build 13 | .nova/ 14 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the OS, Python version and other tools you might need 8 | build: 9 | os: ubuntu-22.04 10 | tools: 11 | python: "3.11" 12 | 13 | # Build documentation in the "docs/" directory with Sphinx 14 | sphinx: 15 | configuration: docs/source/conf.py 16 | 17 | # Optionally build your docs in additional formats such as PDF and ePub 18 | # formats: 19 | # - pdf 20 | # - epub 21 | 22 | # Optional but recommended, declare the Python requirements required 23 | # to build your documentation 24 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 25 | python: 26 | install: 27 | - requirements: docs/requirements.txt 28 | -------------------------------------------------------------------------------- /.ruff.toml: -------------------------------------------------------------------------------- 1 | # Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. 2 | select = ["E", "F", "B"] 3 | ignore = ["E501", "E741", "B905"] # B905 valid for 3.10 onwards 4 | 5 | # Allow autofix for all enabled rules (when `--fix`) is provided. 6 | fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"] 7 | unfixable = [] 8 | 9 | # Exclude a variety of commonly ignored directories. 10 | exclude = [ 11 | ".bzr", 12 | ".direnv", 13 | ".eggs", 14 | ".git", 15 | ".git-rewrite", 16 | ".hg", 17 | ".mypy_cache", 18 | ".nox", 19 | ".pants.d", 20 | ".pytype", 21 | ".ruff_cache", 22 | ".svn", 23 | ".tox", 24 | ".venv", 25 | "__pypackages__", 26 | "_build", 27 | "buck-out", 28 | "build", 29 | "dist", 30 | "node_modules", 31 | "venv", 32 | ] 33 | 34 | # Same as Black. 35 | line-length = 88 36 | 37 | # Allow unused variables when underscore-prefixed. 38 | dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" 39 | 40 | # Assume Python 3.9. 41 | target-version = "py39" 42 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "vasppy", 3 | "creators": [{ 4 | "name": "Morgan, Benjamin J.", 5 | "affiliation": "Department of Chemistry, University of Bath, Claverton Down, Bath, BA2 7AY, UK." 6 | }], 7 | "description": "A Python module for working with VASP input and output.", 8 | "access_right": "open", 9 | "license": "MIT", 10 | "grants": [{ 11 | "code": "UF130329", 12 | "funder": "The Royal Society" 13 | },{ 14 | "code": "608502", 15 | "funder": "EU FP7" 16 | },{ 17 | "code": "EP/N004302/1", 18 | "funder": "EPSRC" 19 | },{ 20 | "code": "EP/S003053/1", 21 | "funder": "The Faraday Institution" 22 | }] 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Benjamin J. Morgan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vasppy - a Python suite for manipulating VASP files 2 | 3 | [![DOI](https://zenodo.org/badge/17946870.svg)](https://zenodo.org/badge/latestdoi/17946870) 4 | [![PyPI version](https://badge.fury.io/py/vasppy.svg)](https://badge.fury.io/py/vasppy) 5 | [![Build Status](https://github.com/bjmorgan/vasppy/actions/workflows/build.yml/badge.svg)](https://github.com/bjmorgan/vasppy/actions/workflows/build.yml) 6 | [![Coverage Status](https://coveralls.io/repos/github/bjmorgan/vasppy/badge.svg?branch=main)](https://coveralls.io/github/bjmorgan/vasppy?branch=main) 7 | [![Documentation Status](https://readthedocs.org/projects/vasppy/badge/?version=latest)](http://vasppy.readthedocs.io/en/latest/?badge=latest) 8 | 9 | `vasppy` is a suite of Python tools and scripts written in Python for manipulating and processing [VASP](https://www.vasp.at/) input and output files. 10 | 11 | ## Tests 12 | 13 | Automated testing of the latest build happens [here](https://github.com/bjmorgan/vasppy/actions/workflows/build.yml) 14 | 15 | Manual tests can be run using 16 | ``` 17 | python3 -m unittest discover 18 | ``` 19 | 20 | ## API documentation 21 | 22 | API documentation is hosted at [Read the Docs](http://vasppy.readthedocs.io/en/latest/). 23 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | 2021-03-20: 2 | - Increased minimum Python version to 3.7 (for Pymatgen 2022.x compatibility) 3 | - Pymatgen imports changed to match v2022.x API. 4 | 5 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | **/.ipynb_checkpoints/ 3 | build 4 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = vasppy 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx~=6.2.1 2 | nbsphinx 3 | jupyter 4 | git+https://github.com/bjmorgan/figure_formatting.git 5 | -r ../requirements.txt 6 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # vasppy documentation build configuration file, created by 5 | # sphinx-quickstart on Tue Mar 6 13:36:30 2018. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | import os 21 | import sys 22 | sys.path.insert(0, os.path.abspath('../../')) 23 | 24 | 25 | # -- General configuration ------------------------------------------------ 26 | 27 | # If your documentation needs a minimal Sphinx version, state it here. 28 | # 29 | # needs_sphinx = '1.0' 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = ['sphinx.ext.autodoc', 35 | 'sphinx.ext.coverage', 36 | 'sphinx.ext.mathjax', 37 | 'sphinx.ext.viewcode', 38 | 'sphinx.ext.githubpages', 39 | 'sphinx.ext.napoleon', 40 | 'nbsphinx'] 41 | 42 | autoclass_content = 'both' 43 | 44 | # Add any paths that contain templates here, relative to this directory. 45 | templates_path = ['_templates'] 46 | 47 | # The suffix(es) of source filenames. 48 | # You can specify multiple suffix as a list of string: 49 | # 50 | # source_suffix = ['.rst', '.md'] 51 | source_suffix = '.rst' 52 | 53 | # The master toctree document. 54 | master_doc = 'index' 55 | 56 | # General information about the project. 57 | project = 'vasppy' 58 | copyright = '2018, Benjamin J. Morgan' 59 | author = 'Benjamin J. Morgan' 60 | 61 | # The version info for the project you're documenting, acts as replacement for 62 | # |version| and |release|, also used in various other places throughout the 63 | # built documents. 64 | # 65 | # The short X.Y version. 66 | version = '0.4' 67 | # The full version, including alpha/beta/rc tags. 68 | release = '0.4' 69 | 70 | # The language for content autogenerated by Sphinx. Refer to documentation 71 | # for a list of supported languages. 72 | # 73 | # This is also used if you do content translation via gettext catalogs. 74 | # Usually you set "language" from the command line for these cases. 75 | language = None 76 | 77 | # List of patterns, relative to source directory, that match files and 78 | # directories to ignore when looking for source files. 79 | # This patterns also effect to html_static_path and html_extra_path 80 | exclude_patterns = ['_build', '**.ipynb_checkpoints'] 81 | 82 | # The name of the Pygments (syntax highlighting) style to use. 83 | pygments_style = 'sphinx' 84 | 85 | # If true, the current module name will be prepended to all description 86 | # unit titles (such as .. function::). 87 | add_module_names = False 88 | 89 | # If true, `todo` and `todoList` produce output, else they produce nothing. 90 | todo_include_todos = False 91 | 92 | 93 | # -- Options for HTML output ---------------------------------------------- 94 | 95 | # The theme to use for HTML and HTML Help pages. See the documentation for 96 | # a list of builtin themes. 97 | # 98 | html_theme = 'sphinx_rtd_theme' 99 | 100 | # Theme options are theme-specific and customize the look and feel of a theme 101 | # further. For a list of options available for each theme, see the 102 | # documentation. 103 | # 104 | # html_theme_options = {} 105 | 106 | nbsphinx_prompt_width = 0 107 | 108 | # NbSphinx configuration 109 | nbsphinx_execute = 'never' 110 | nbsphinx_codecell_lexer = 'python3' 111 | 112 | # Add any paths that contain custom static files (such as style sheets) here, 113 | # relative to this directory. They are copied after the builtin static files, 114 | # so a file named "default.css" will overwrite the builtin "default.css". 115 | html_static_path = ['_static'] 116 | 117 | # Custom sidebar templates, must be a dictionary that maps document names 118 | # to template names. 119 | # 120 | # This is required for the alabaster theme 121 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars 122 | html_sidebars = { 123 | '**': [ 124 | 'relations.html', # needs 'show_related': True theme option to display 125 | 'searchbox.html', 126 | ] 127 | } 128 | 129 | 130 | # -- Options for HTMLHelp output ------------------------------------------ 131 | 132 | # Output file base name for HTML help builder. 133 | htmlhelp_basename = 'vasppydoc' 134 | 135 | 136 | # -- Options for LaTeX output --------------------------------------------- 137 | 138 | latex_elements = { 139 | # The paper size ('letterpaper' or 'a4paper'). 140 | # 141 | # 'papersize': 'letterpaper', 142 | 143 | # The font size ('10pt', '11pt' or '12pt'). 144 | # 145 | # 'pointsize': '10pt', 146 | 147 | # Additional stuff for the LaTeX preamble. 148 | # 149 | # 'preamble': '', 150 | 151 | # Latex figure (float) alignment 152 | # 153 | # 'figure_align': 'htbp', 154 | } 155 | 156 | # Grouping the document tree into LaTeX files. List of tuples 157 | # (source start file, target name, title, 158 | # author, documentclass [howto, manual, or own class]). 159 | latex_documents = [ 160 | (master_doc, 'vasppy.tex', 'vasppy Documentation', 161 | 'Benjamin J. Morgan', 'manual'), 162 | ] 163 | 164 | 165 | # -- Options for manual page output --------------------------------------- 166 | 167 | # One entry per manual page. List of tuples 168 | # (source start file, name, description, authors, manual section). 169 | man_pages = [ 170 | (master_doc, 'vasppy', 'vasppy Documentation', 171 | [author], 1) 172 | ] 173 | 174 | 175 | # -- Options for Texinfo output ------------------------------------------- 176 | 177 | # Grouping the document tree into Texinfo files. List of tuples 178 | # (source start file, target name, title, author, 179 | # dir menu entry, description, category) 180 | texinfo_documents = [ 181 | (master_doc, 'vasppy', 'vasppy Documentation', 182 | author, 'vasppy', 'One line description of project.', 183 | 'Miscellaneous'), 184 | ] 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | vasppy 2 | ====== 3 | 4 | .. toctree:: 5 | :caption: User Guide 6 | :maxdepth: 2 7 | 8 | .. toctree:: 9 | :caption: Examples 10 | :maxdepth: 1 11 | 12 | examples/rdfs 13 | 14 | .. toctree:: 15 | :hidden: 16 | :caption: API 17 | :maxdepth: 2 18 | 19 | modules 20 | 21 | * :ref:`genindex` 22 | * :ref:`modindex` 23 | * :ref:`search` 24 | -------------------------------------------------------------------------------- /docs/source/modules.rst: -------------------------------------------------------------------------------- 1 | API documentation 2 | ================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | modules/atom 11 | modules/calculation 12 | modules/cell 13 | modules/configuration 14 | modules/doscar 15 | modules/grid 16 | modules/kpoints 17 | modules/optics 18 | modules/outcar 19 | modules/pimaim 20 | modules/polyhedron 21 | modules/poscar 22 | modules/procar 23 | modules/rdf 24 | modules/summary 25 | modules/vaspmeta 26 | modules/vasppy.data 27 | modules/xdatcar 28 | -------------------------------------------------------------------------------- /docs/source/modules/atom.rst: -------------------------------------------------------------------------------- 1 | vasppy\.atom module 2 | ------------------- 3 | 4 | .. automodule:: vasppy.atom 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/calculation.rst: -------------------------------------------------------------------------------- 1 | vasppy\.calculation module 2 | -------------------------- 3 | 4 | .. automodule:: vasppy.calculation 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/cell.rst: -------------------------------------------------------------------------------- 1 | vasppy\.cell module 2 | ------------------- 3 | 4 | .. automodule:: vasppy.cell 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/configuration.rst: -------------------------------------------------------------------------------- 1 | vasppy\.configuration module 2 | ---------------------------- 3 | 4 | .. automodule:: vasppy.configuration 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/doscar.rst: -------------------------------------------------------------------------------- 1 | vasppy\.doscar module 2 | --------------------- 3 | 4 | .. automodule:: vasppy.doscar 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/grid.rst: -------------------------------------------------------------------------------- 1 | vasppy\.grid module 2 | ------------------- 3 | 4 | .. automodule:: vasppy.grid 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/kpoints.rst: -------------------------------------------------------------------------------- 1 | vasppy\.kpoints module 2 | ---------------------- 3 | 4 | .. automodule:: vasppy.kpoints 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/optics.rst: -------------------------------------------------------------------------------- 1 | vasppy\.optics module 2 | --------------------- 3 | 4 | .. automodule:: vasppy.optics 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/outcar.rst: -------------------------------------------------------------------------------- 1 | vasppy\.outcar module 2 | --------------------- 3 | 4 | .. automodule:: vasppy.outcar 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/pimaim.rst: -------------------------------------------------------------------------------- 1 | vasppy\.pimaim module 2 | --------------------- 3 | 4 | .. automodule:: vasppy.pimaim 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/polyhedron.rst: -------------------------------------------------------------------------------- 1 | vasppy\.polyhedron module 2 | ------------------------- 3 | 4 | .. automodule:: vasppy.polyhedron 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/poscar.rst: -------------------------------------------------------------------------------- 1 | vasppy\.poscar module 2 | --------------------- 3 | 4 | .. automodule:: vasppy.poscar 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/procar.rst: -------------------------------------------------------------------------------- 1 | vasppy\.procar module 2 | --------------------- 3 | 4 | .. automodule:: vasppy.procar 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/rdf.rst: -------------------------------------------------------------------------------- 1 | vasppy\.rdf module 2 | ------------------ 3 | 4 | .. automodule:: vasppy.rdf 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/summary.rst: -------------------------------------------------------------------------------- 1 | vasppy\.summary module 2 | ---------------------- 3 | 4 | .. automodule:: vasppy.summary 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/vaspmeta.rst: -------------------------------------------------------------------------------- 1 | vasppy\.vaspmeta module 2 | ----------------------- 3 | 4 | .. automodule:: vasppy.vaspmeta 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/source/modules/vasppy.data.rst: -------------------------------------------------------------------------------- 1 | vasppy\.data package 2 | ==================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | vasppy\.data\.potcar\_md5sum\_data module 8 | ----------------------------------------- 9 | 10 | .. automodule:: vasppy.data.potcar_data 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: vasppy.data 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /docs/source/modules/xdatcar.rst: -------------------------------------------------------------------------------- 1 | vasppy\.xdatcar module 2 | ---------------------- 3 | 4 | .. automodule:: vasppy.xdatcar 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy>=1.20,<2.0 2 | monty 3 | pandas 4 | pymatgen>=2023.6.28 5 | PyYAML 6 | fortranformat 7 | scipy>=1.4.1 8 | tqdm 9 | lxml 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """ 2 | vasppy: Python utilities for working with VASP inputs and outputs. 3 | """ 4 | 5 | from setuptools import setup, find_packages 6 | from vasppy.version import __version__ as VERSION 7 | 8 | readme = 'README.md' 9 | long_description = open(readme).read() 10 | 11 | scripts = ['check_species', 12 | 'checkforce', 13 | 'convergence_testing', 14 | 'murnfit', 15 | 'vasp_summary', 16 | 'poscar_to_cif', 17 | 'potcar_spec', 18 | 'effective_mass', 19 | 'fat_bands', 20 | 'pimaim_to_poscar', 21 | 'pimaim_to_xtl', 22 | 'poscar_to_pimaim', 23 | 'poscar_to_xtl', 24 | 'proc_poscar', 25 | 'rotate_poscar', 26 | 'spacegroup', 27 | 'vasp_grid', 28 | 'xdatcar_to_disp', 29 | 'xdatcar_to_poscart', 30 | 'xdatcar_to_rdf', 31 | 'r2r2_expansion'] 32 | 33 | setup( 34 | name='vasppy', 35 | version=VERSION, 36 | description='Python utilities for working with VASP inputs and outputs', 37 | long_description=long_description, 38 | long_description_content_type="text/markdown", 39 | author='Benjamin J. Morgan', 40 | author_email='bjm42@bath.ac.uk', 41 | url='https://github.com/bjmorgan/vasppy', 42 | download_url='https://github.com/bjmorgan/vasppy/archive/{}.tar.gz'.format(VERSION), 43 | keywords=['vasp'], # keywords 44 | packages=find_packages(exclude=['docs', 'tests*']), 45 | package_data={'vasppy': ['data/*.yaml']}, 46 | entry_points={'console_scripts':[ 47 | '{} = vasppy.scripts.{}:main'.format(s, s) for s in scripts]}, 48 | license='MIT', 49 | install_requires=['monty', 50 | 'numpy>=1.20,<2.0', 51 | 'pandas', 52 | 'pymatgen>=2023.6.28', 53 | 'PyYAML', 54 | 'fortranformat', 55 | 'scipy>=1.4.1', 56 | 'tqdm', 57 | 'lxml'], 58 | python_requires='>=3.9' 59 | ) 60 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmorgan/vasppy/f913b1bd034e4b106bb83e13c0f4c5a0e09151b7/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_atom.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | 4 | from vasppy.atom import Atom 5 | 6 | 7 | class AtomTestCase(unittest.TestCase): 8 | def test_init_atom(self): 9 | label = "A" 10 | r = np.array([0.1, 0.2, 0.3]) 11 | atom = Atom(label=label, r=r) 12 | self.assertEqual(atom.label, label) 13 | np.testing.assert_array_equal(atom.r, r) 14 | 15 | 16 | if __name__ == "__main__": 17 | unittest.main() 18 | -------------------------------------------------------------------------------- /tests/test_band.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import unittest 3 | from unittest.mock import patch, call 4 | 5 | from vasppy.band import Band, handle_occupancy 6 | 7 | 8 | class BandTestCase(unittest.TestCase): 9 | """Tests for procar.Band class""" 10 | 11 | def test_band_is_initialised(self): 12 | """Test Band object is initialised""" 13 | index = 2 14 | energy = 1.0 15 | occupancy = 0.5 16 | with patch("vasppy.band.handle_occupancy") as mock_handle_occupancy: 17 | mock_handle_occupancy.return_value = 0.5 18 | band = Band(index=index, energy=energy, occupancy=occupancy) 19 | self.assertEqual(index, band.index) 20 | self.assertEqual(energy, band.energy) 21 | self.assertEqual(occupancy, band.occupancy) 22 | mock_handle_occupancy.assert_has_calls([call(0.5, negative_occupancies="warn")]) 23 | 24 | def test_handle_occupancy_raises_valuerror_if_negative_occupancies_is_invalid_keyword( 25 | self, 26 | ): 27 | with self.assertRaises(ValueError): 28 | handle_occupancy(0.5, negative_occupancies="foo") 29 | 30 | def test_handle_occupancy_warns_about_negative_occupancies(self): 31 | with warnings.catch_warnings(record=True) as w: 32 | handle_occupancy(-0.1, negative_occupancies="warn") 33 | self.assertEqual(len(w), 1) 34 | self.assertTrue("negative" in str(w[-1].message)) 35 | 36 | def test_handle_occupancy_raises_exception_if_negative_occupancies_is_raise(self): 37 | with self.assertRaises(ValueError): 38 | handle_occupancy(-0.1, negative_occupancies="raise") 39 | 40 | def test_handle_occupancy_if_negative_occupancies_is_ignore(self): 41 | self.assertEqual(handle_occupancy(-0.1, negative_occupancies="ignore"), -0.1) 42 | 43 | def test_handle_occupancy_zeros_occupancies_if_negative_occupancies_is_zero(self): 44 | self.assertEqual(handle_occupancy(-0.1, negative_occupancies="zero"), 0.0) 45 | 46 | 47 | if __name__ == "__main__": 48 | unittest.main() 49 | -------------------------------------------------------------------------------- /tests/test_calculation.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import textwrap 3 | from unittest.mock import Mock, patch, mock_open 4 | from collections import Counter 5 | 6 | from vasppy.calculation import ( 7 | Calculation, 8 | delta_E, 9 | delta_stoichiometry, 10 | energy_string_to_float, 11 | import_calculations_from_file, 12 | ) 13 | 14 | 15 | class CalculationTestCase(unittest.TestCase): 16 | def test_calculation_is_initialised(self): 17 | this_title = "A" 18 | this_energy = -100.0 19 | this_stoichiometry = {"B": 1, "C": 2} 20 | calculation = Calculation( 21 | title=this_title, energy=this_energy, stoichiometry=this_stoichiometry 22 | ) 23 | self.assertEqual(this_title, calculation.title) 24 | self.assertEqual(this_energy, calculation.energy) 25 | self.assertEqual(this_stoichiometry, calculation.stoichiometry) 26 | 27 | def test_mul(self): 28 | title = "A" 29 | energy = -100.0 30 | stoichiometry = {"B": 1, "C": 2} 31 | calculation = Calculation( 32 | title=title, energy=energy, stoichiometry=stoichiometry 33 | ) 34 | calculation.scale_stoichiometry = Mock(return_value={"B": 2, "C": 4}) 35 | new_calculation = calculation * 2 36 | self.assertEqual(title, new_calculation.title) 37 | self.assertEqual(energy * 2.0, new_calculation.energy) 38 | self.assertEqual({"B": 2, "C": 4}, new_calculation.stoichiometry) 39 | calculation.scale_stoichiometry.assert_called_with(2) 40 | 41 | def test_truediv(self): 42 | title = "A" 43 | energy = -100.0 44 | stoichiometry = {"B": 4, "C": 2} 45 | calculation = Calculation( 46 | title=title, energy=energy, stoichiometry=stoichiometry 47 | ) 48 | with patch("vasppy.calculation.Calculation.__mul__") as mock_mul: 49 | calculation / 2 50 | mock_mul.assert_called_with(0.5) 51 | 52 | def test_scale_stoichiometry(self): 53 | title = "A" 54 | energy = -100.0 55 | stoichiometry = {"B": 1, "C": 2} 56 | calculation = Calculation( 57 | title=title, energy=energy, stoichiometry=stoichiometry 58 | ) 59 | self.assertEqual(calculation.scale_stoichiometry(2), {"B": 2, "C": 4}) 60 | 61 | 62 | class CalculationSupportFunctionsTestCase(unittest.TestCase): 63 | def test_delta_E(self): 64 | titles = ["A", "B", "C"] 65 | energies = [-50.5, -23.2, -10.1] 66 | stoichiometries = [{"B": 1, "C": 2}, {"B": 1, "C": 1}, {"C": 1}] 67 | calculations = [ 68 | Calculation(title=t, energy=e, stoichiometry=s) 69 | for t, e, s in zip(titles, energies, stoichiometries) 70 | ] 71 | self.assertAlmostEqual( 72 | delta_E(reactants=[calculations[0]], products=calculations[1:3]), +17.2 73 | ) 74 | 75 | @patch("vasppy.calculation.delta_stoichiometry") 76 | def test_delta_E_raises_value_error_if_not_balanced(self, mock_delta_stoichiometry): 77 | titles = ["A", "B", "C"] 78 | energies = [-50.5, -23.2, -10.1] 79 | stoichiometries = [{"B": 1, "C": 2}, {"B": 1, "C": 1}, {"C": 2}] 80 | calculations = [ 81 | Calculation(title=t, energy=e, stoichiometry=s) 82 | for t, e, s in zip(titles, energies, stoichiometries) 83 | ] 84 | with self.assertRaises(ValueError): 85 | delta_E(reactants=[calculations[0]], products=calculations[1:3]) 86 | mock_delta_stoichiometry.assert_called_with( 87 | [calculations[0]], calculations[1:3] 88 | ) 89 | 90 | def test_delta_stoichiometry(self): 91 | titles = ["A", "B", "C"] 92 | energies = [-50.5, -23.2, -10.1] 93 | stoichiometries = [{"B": 1, "C": 2}, {"D": 1, "C": 1}, {"C": 1}] 94 | calculations = [ 95 | Calculation(title=t, energy=e, stoichiometry=s) 96 | for t, e, s in zip(titles, energies, stoichiometries) 97 | ] 98 | self.assertEqual( 99 | delta_stoichiometry( 100 | reactants=[calculations[0]], products=calculations[1:3] 101 | ), 102 | {"B": -1, "D": 1}, 103 | ) 104 | 105 | def test_energy_string_to_float(self): 106 | test_strings = {"-1.2345 eV": -1.2345, "0.2341 eV": 0.2341} 107 | for k, v in test_strings.items(): 108 | self.assertEqual(energy_string_to_float(k), v) 109 | 110 | @patch("vasppy.calculation.energy_string_to_float") 111 | @patch("vasppy.calculation.Calculation") 112 | def test_import_calculation_from_file( 113 | self, mock_Calculation, mock_energy_converter 114 | ): 115 | mock_energy_converter.side_effect = [-0.2414] 116 | example_yaml = """ 117 | title: this_calculation 118 | stoichiometry: 119 | - A: 2 120 | - B: 4 121 | energy: -0.2414 eV 122 | """ 123 | with patch("builtins.open", mock_open(read_data=example_yaml), create=True): 124 | import_calculations_from_file("example_file") 125 | mock_Calculation.assert_called_with( 126 | energy=-0.2414, 127 | stoichiometry=Counter({"B": 4, "A": 2}), 128 | title="this_calculation", 129 | ) 130 | mock_energy_converter.assert_called_with("-0.2414 eV") 131 | 132 | def test_import_calculation_from_file_raises_ValueError_if_stoichiometry_is_not_set( 133 | self, 134 | ): 135 | example_yaml = """ 136 | title: this_calculation 137 | energy: -0.2414 eV 138 | """ 139 | with patch("builtins.open", mock_open(read_data=example_yaml), create=True): 140 | with self.assertRaises(ValueError): 141 | import_calculations_from_file("example_file") 142 | 143 | def test_import_calculation_from_file_skips_incomplete_files(self): 144 | example_yaml = """ 145 | title: this_calculation 146 | energy: -0.2414 eV 147 | """ 148 | with patch("builtins.open", mock_open(read_data=example_yaml), create=True): 149 | calcs = import_calculations_from_file( 150 | "example_file", skip_incomplete_records=True 151 | ) 152 | self.assertEqual(calcs, {}) 153 | 154 | 155 | def test_import_calculation_from_file_raises_ValueError_if_calculations_have_repeated_titles( 156 | self 157 | ): 158 | example_yaml = textwrap.dedent(""" 159 | --- 160 | title: this_calculation 161 | stoichiometry: 162 | - A: 2 163 | - B: 4 164 | energy: -0.2414 eV 165 | 166 | --- 167 | title: this_calculation 168 | stoichiometry: 169 | - A: 2 170 | - B: 4 171 | energy: -0.2414 eV 172 | """) 173 | with patch("builtins.open", mock_open(read_data=example_yaml), create=True): 174 | with self.assertRaises(ValueError): 175 | import_calculations_from_file("example_file") 176 | 177 | 178 | if __name__ == "__main__": 179 | unittest.main() 180 | -------------------------------------------------------------------------------- /tests/test_cell.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from vasppy.cell import angle, rotation_matrix, Cell 3 | from unittest.mock import patch, Mock 4 | import numpy as np 5 | import math 6 | 7 | 8 | class Test_Cell(unittest.TestCase): 9 | def test_cell_init(self): 10 | cell_matrix = np.array([[1.0, 1.0, 0.0], [1.0, 0.0, 1.0], [0.0, 1.0, 1.0]]) 11 | with patch("numpy.linalg.inv") as mock_invert: 12 | mock_invert.return_value = np.array( 13 | [[0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 0.0, 0.0]] 14 | ) 15 | cell = Cell(cell_matrix) 16 | mock_invert.assert_called_with(cell_matrix) 17 | np.testing.assert_array_equal(cell.matrix, cell_matrix) 18 | np.testing.assert_array_equal(cell.inv_matrix, mock_invert.return_value) 19 | 20 | def setUp(self): 21 | cell_matrix = np.array([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) 22 | self.cell = Cell(cell_matrix) 23 | 24 | def test_dr(self): 25 | r1 = np.array([0.5, 0.1, 0.1]) 26 | r2 = np.array([0.1, 0.4, 0.1]) 27 | self.assertEqual(self.cell.dr(r1, r2), 5.0) 28 | 29 | def test_dr_cutoff(self): 30 | r1 = np.array([0.5, 0.1, 0.1]) 31 | r2 = np.array([0.1, 0.4, 0.1]) 32 | self.assertEqual(self.cell.dr(r1, r2, cutoff=1.0), None) 33 | 34 | def test_nearest_image(self): 35 | r1 = np.array([0.5, 0.1, 0.1]) 36 | r2 = np.array([0.1, 0.4, 0.1]) 37 | self.cell.minimum_image = Mock(return_value=np.array([-0.4, 0.3, 0.0])) 38 | np.testing.assert_array_almost_equal(self.cell.nearest_image(r1, r2), r2) 39 | 40 | def test_minimum_image(self): 41 | r1 = np.array([0.5, 0.1, 0.1]) 42 | r2 = np.array([0.1, 0.4, 0.3]) 43 | np.testing.assert_array_almost_equal( 44 | self.cell.minimum_image(r1, r2), np.array([-0.4, 0.3, 0.2]) 45 | ) 46 | 47 | def test_minimum_image_2(self): 48 | r1 = np.array([0.5, 0.1, 0.1]) 49 | r2 = np.array([0.6, 0.8, 0.8]) 50 | np.testing.assert_array_almost_equal( 51 | self.cell.minimum_image(r1, r2), np.array([0.1, -0.3, -0.3]) 52 | ) 53 | 54 | def test_minimum_image_dr(self): 55 | r1 = np.array([0.5, 0.1, 0.1]) 56 | r2 = np.array([0.8, 0.7, 0.3]) 57 | self.cell.minimum_image = Mock(return_value=np.array([0.3, -0.4, 0.2])) 58 | self.assertAlmostEqual(self.cell.minimum_image_dr(r1, r2), 5.385164807) 59 | 60 | def test_lengths(self): 61 | np.testing.assert_array_equal(self.cell.lengths(), np.array([10.0, 10.0, 10.0])) 62 | 63 | def test_angles(self): 64 | self.assertEqual(self.cell.angles(), [90.0, 90.0, 90.0]) 65 | 66 | def test_cartesian_to_fractional_coordinates(self): 67 | coordinates = np.array([[1.0, 2.0, 3.0], [4.0, 6.0, 2.0]]) 68 | expected_fractional_coordinates = np.array([[0.1, 0.2, 0.3], [0.4, 0.6, 0.2]]) 69 | np.testing.assert_array_almost_equal( 70 | self.cell.cartesian_to_fractional_coordinates(coordinates), 71 | expected_fractional_coordinates, 72 | ) 73 | 74 | def test_fractional_to_cartesian_coordinates(self): 75 | coordinates = np.array([[0.1, 0.2, 0.3], [0.4, 0.6, 0.2]]) 76 | expected_cartesian_coordinates = np.array([[1.0, 2.0, 3.0], [4.0, 6.0, 2.0]]) 77 | np.testing.assert_array_almost_equal( 78 | self.cell.fractional_to_cartesian_coordinates(coordinates), 79 | expected_cartesian_coordinates, 80 | ) 81 | 82 | def test_inside_cell(self): 83 | c = np.array( 84 | [[[0.1, 0.2, 0.3], [0.1, 0.2, 0.3]], [[0.3, 1.2, 1.3], [0.3, 0.2, 0.3]]] 85 | ) 86 | for r1, r2 in c: 87 | np.testing.assert_array_almost_equal(self.cell.inside_cell(r1), r2) 88 | 89 | def test_volume(self): 90 | self.assertEqual(self.cell.volume(), 1000.0) 91 | 92 | def test_unit_vectors(self): 93 | np.testing.assert_array_equal( 94 | self.cell.unit_vectors(), 95 | np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), 96 | ) 97 | 98 | 99 | class Test_Cell_Support_Functions(unittest.TestCase): 100 | def test_angle(self): 101 | test_data = [ 102 | [np.array([1.0, 0.0, 0.0]), np.array([0.0, 1.0, 0.0]), 90.0], 103 | [np.array([2.0, 2.0, 0.0]), np.array([0.5, 0.0, 0.0]), 45.0], 104 | ] 105 | for data in test_data: 106 | self.assertAlmostEqual(angle(data[0], data[1]), data[2]) 107 | 108 | def test_rotation_matrix(self): 109 | test_matrix = np.array( 110 | [ 111 | [1.0, 0.0, 0.0], 112 | [0.0, math.sqrt(3) / 2, -0.5], 113 | [0.0, 0.5, math.sqrt(3) / 2], 114 | ] 115 | ) 116 | angle = math.pi / 6 117 | axis = np.array([1.0, 0.0, 0.0]) 118 | np.testing.assert_almost_equal(rotation_matrix(axis, angle), test_matrix) 119 | 120 | def test_rotation_matrix_2(self): 121 | test_matrix = np.array([[0.0, 0.0, 1.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) 122 | angle = math.pi * 2 / 3 123 | axis = np.array([1.0, 1.0, 1.0]) 124 | np.testing.assert_almost_equal(rotation_matrix(axis, angle), test_matrix) 125 | 126 | 127 | if __name__ == "__main__": 128 | unittest.main() 129 | -------------------------------------------------------------------------------- /tests/test_data/vasp_summary_test.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | title: foo 3 | data: foo_data 4 | 5 | --- 6 | title: bar 7 | data: bar_data 8 | 9 | -------------------------------------------------------------------------------- /tests/test_doscar.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | if __name__ == "__main__": 4 | unittest.main() 5 | -------------------------------------------------------------------------------- /tests/test_kpoints.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from vasppy.kpoints import AutoKPoints, get_convergence_testing_kspacing, get_subdivisions_from_kspacing 4 | import numpy as np 5 | 6 | class AutoKPointsTestCase(unittest.TestCase): 7 | def test_init_auto_kpoints(self): 8 | title = "title" 9 | subdivisions = np.array([2, 2, 2]) 10 | auto_kpoints = AutoKPoints(title, subdivisions) 11 | self.assertEqual(auto_kpoints.title, title) 12 | np.testing.assert_array_equal(auto_kpoints.subdivisions, subdivisions) 13 | np.testing.assert_array_equal(auto_kpoints.grid_centering, "G") 14 | np.testing.assert_array_equal(auto_kpoints.shift, np.array([0.0, 0.0, 0.0])) 15 | 16 | def test_init_auto_kpoints_mp(self): 17 | title = "title" 18 | subdivisions = np.array([2, 2, 2]) 19 | grid_centering = "MP" 20 | auto_kpoints = AutoKPoints(title, subdivisions, grid_centering=grid_centering) 21 | np.testing.assert_array_equal(auto_kpoints.grid_centering, "MP") 22 | 23 | def test_init_auto_kpoints_shift(self): 24 | title = "title" 25 | subdivisions = np.array([2, 2, 2]) 26 | shift = np.array([0.1, 0.2, 0.3]) 27 | auto_kpoints = AutoKPoints(title, subdivisions, shift=shift) 28 | np.testing.assert_array_equal(auto_kpoints.shift, shift) 29 | 30 | def test_init_auto_kpoints_invalid_grid_centering_raises_valueerror(self): 31 | title = "title" 32 | subdivisions = np.array([2, 2, 2]) 33 | grid_centering = "foo" 34 | with self.assertRaises(ValueError): 35 | AutoKPoints(title, subdivisions, grid_centering=grid_centering) 36 | 37 | class KspacingTestCase(unittest.TestCase): 38 | def test_subdivisions_from_kspacing(self): 39 | kspacing = 0.2 40 | reciprocal_lattice_vectors = np.array([[0.16, 0, 0], [0, 0.19, 0], [0, 0, 0.20]]) 41 | subdivisions = get_subdivisions_from_kspacing(kspacing, reciprocal_lattice_vectors) 42 | self.assertEqual(subdivisions, (6, 6, 7)) 43 | 44 | def test_convergence_testing_kspacing_default(self): 45 | reciprocal_lattice_vectors = np.array([[0.16, 0, 0], [0, 0.19, 0], [0, 0, 0.20]]) 46 | allowed_kspacing = get_convergence_testing_kspacing(reciprocal_lattice_vectors) 47 | self.assertEqual(allowed_kspacing, (0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.22, 0.24, 0.26, 0.3, 0.32, 0.34, 0.4, 0.42, 0.52, 0.6, 0.64)) 48 | 49 | def test_convergence_testing_kspacing_custom_range(self): 50 | reciprocal_lattice_vectors = np.array([[0.16, 0, 0], [0, 0.19, 0], [0, 0, 0.20]]) 51 | kspacing_range = (0.4, 0.6) 52 | allowed_kspacing = get_convergence_testing_kspacing(reciprocal_lattice_vectors, kspacing_range=kspacing_range) 53 | self.assertEqual(allowed_kspacing, (0.4, 0.42, 0.52, 0.6)) 54 | 55 | def test_convergence_testing_kspacing_custom_step(self): 56 | reciprocal_lattice_vectors = np.array([[0.16, 0, 0], [0, 0.19, 0], [0, 0, 0.20]]) 57 | step = 0.05 58 | allowed_kspacing = get_convergence_testing_kspacing(reciprocal_lattice_vectors, step=step) 59 | self.assertEqual(allowed_kspacing, (0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.55, 0.6, 0.65)) 60 | 61 | if __name__ == '__main__': 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /tests/test_optics.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from vasppy.optics import matrix_eigvals, to_matrix, parse_dielectric_data 3 | import numpy as np 4 | from unittest.mock import patch, call 5 | 6 | 7 | class Test_Optics(unittest.TestCase): 8 | def test_matrix_eigvals(self): 9 | matrix = np.array([[2, 0, 3], [0, 3, 0], [0, 0, 3]]) 10 | expected_eigenvalues = np.array([2, 3, 3]) 11 | np.testing.assert_array_equal(matrix_eigvals(matrix), expected_eigenvalues) 12 | 13 | def test_to_matrix(self): 14 | expected_matrix = np.array([[1, 2, 3], [2, 4, 5], [3, 5, 6]]) 15 | np.testing.assert_array_equal( 16 | to_matrix(xx=1, yy=4, zz=6, xy=2, yz=5, xz=3), expected_matrix 17 | ) 18 | 19 | @patch("vasppy.optics.to_matrix") 20 | @patch("vasppy.optics.matrix_eigvals") 21 | def test_parse_dielectric_data(self, mock_matrix_eigvals, mock_to_matrix): 22 | input_data = [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6], [1.1, 1.2, 1.3, 1.4, 1.5, 1.6]] 23 | matrix_a = np.array([[0.1, 0.4, 0.6], [0.4, 0.2, 0.5], [0.6, 0.5, 0.3]]) 24 | matrix_b = np.array([[1.1, 1.4, 1.6], [1.4, 1.2, 1.5], [1.6, 1.5, 1.3]]) 25 | mock_to_matrix.side_effect = [matrix_a, matrix_b] 26 | mock_matrix_eigvals.side_effect = [np.array([1, 2, 3]), np.array([4, 5, 6])] 27 | expected_data = np.array([[1, 2, 3], [4, 5, 6]]) 28 | np.testing.assert_array_equal(parse_dielectric_data(input_data), expected_data) 29 | mock_to_matrix.assert_has_calls([call(*input_data[0]), call(*input_data[1])]) 30 | mock_matrix_eigvals.assert_has_calls([call(matrix_a), call(matrix_b)]) 31 | 32 | 33 | if __name__ == "__main__": 34 | unittest.main() 35 | -------------------------------------------------------------------------------- /tests/test_outcar.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import patch, mock_open, call 3 | 4 | from vasppy.outcar import final_energy_from_outcar, potcar_eatom_list_from_outcar 5 | 6 | 7 | class OutcarTestCase(unittest.TestCase): 8 | def test_final_energy_from_outcar(self): 9 | example_file = """energy without entropy = -2997.63294724 energy(sigma->0) = -2997.63294724\n 10 | energy without entropy= -2997.63294724 energy(sigma->0) = -2997.63294724\n 11 | energy without entropy = -2997.63289805 energy(sigma->0) = -2997.63289805\n""" 12 | with patch("builtins.open", mock_open(read_data=example_file), create=True): 13 | self.assertEqual(final_energy_from_outcar(), -2997.63289805) 14 | 15 | def test_final_energy_from_outcar_with_filename(self): 16 | example_file = """energy without entropy = -2997.63294724 energy(sigma->0) = -2997.63294724\n 17 | energy without entropy= -2997.63294724 energy(sigma->0) = -2997.63294724\n 18 | energy without entropy = -2997.63289805 energy(sigma->0) = -2997.63289805\n""" 19 | with patch( 20 | "builtins.open", mock_open(read_data=example_file), create=True 21 | ) as m: 22 | final_energy_from_outcar(filename="foo") 23 | self.assertEqual(m.mock_calls[0], call("foo")) 24 | 25 | def test_potcar_eatom_list_from_potcar(self): 26 | example_file = """energy of atom 1 EATOM=-1042.3781\n 27 | kinetic energy error for atom= 0.0024 (will be added to EATOM!!)\n 28 | energy of atom 2 EATOM= -432.3788\n 29 | kinetic energy error for atom= 0.0224 (will be added to EATOM!!)\n 30 | energy of atom 3 EATOM= -659.6475\n 31 | kinetic energy error for atom= 0.0354 (will be added to EATOM!!)\n""" 32 | with patch("builtins.open", mock_open(read_data=example_file), create=True): 33 | self.assertEqual( 34 | potcar_eatom_list_from_outcar(), [-1042.3781, -432.3788, -659.6475] 35 | ) 36 | 37 | 38 | if __name__ == "__main__": 39 | unittest.main() 40 | -------------------------------------------------------------------------------- /tests/test_poscar.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import Mock, patch 3 | from io import StringIO 4 | 5 | from vasppy.poscar import Poscar 6 | from vasppy.cell import Cell 7 | import numpy as np 8 | from collections import Counter 9 | 10 | 11 | class PoscarTestCase(unittest.TestCase): 12 | def setUp(self): 13 | self.poscar = Poscar() 14 | self.poscar.title = "Title" 15 | self.poscar.scaling = 1.0 16 | self.poscar.cell = Mock(spec=Cell) 17 | self.poscar.cell.matrix = np.identity(3) 18 | self.poscar.atoms = ["A"] 19 | self.poscar.atom_numbers = [1] 20 | self.poscar.coordinate_type = "Direct" 21 | self.poscar.coordinates = np.array([[0.0, 0.0, 0.0]]) 22 | self.poscar.selective_dynamics = False 23 | 24 | def test_stoichiometry(self): 25 | poscar = Poscar() 26 | poscar.atoms = ["A", "B", "C"] 27 | poscar.atom_numbers = [1, 2, 3] 28 | self.assertEqual(poscar.stoichiometry, Counter({"A": 1, "B": 2, "C": 3})) 29 | 30 | @patch("sys.stdout", new_callable=StringIO) 31 | def test_output_header(self, mock_stdout): 32 | self.poscar.output_header() 33 | expected_header_string = ( 34 | "Title\n" 35 | "1.0\n" 36 | " 1.0000000000 0.0000000000 0.0000000000\n" 37 | " 0.0000000000 1.0000000000 0.0000000000\n" 38 | " 0.0000000000 0.0000000000 1.0000000000\n" 39 | "A\n" 40 | "1\n" 41 | "Direct\n" 42 | ) 43 | self.assertEqual(mock_stdout.getvalue(), expected_header_string) 44 | 45 | 46 | if __name__ == "__main__": 47 | unittest.main() 48 | -------------------------------------------------------------------------------- /tests/test_rdf.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from vasppy.rdf import RadialDistributionFunction 3 | import numpy as np 4 | from pymatgen.core import Structure, Lattice 5 | from unittest.mock import Mock, patch, call 6 | 7 | 8 | class TestRadialDistributionFunction(unittest.TestCase): 9 | def test_RadialDistributionFunction_raises_ValueError_if_weights_doesnt_match_structures( 10 | self, 11 | ): 12 | mock_structures = [Mock(spec=Structure), Mock(spec=Structure)] 13 | weights = [1, 2, 3] 14 | indices_i = [0, 1] 15 | with self.assertRaises(ValueError): 16 | RadialDistributionFunction( 17 | structures=mock_structures, indices_i=indices_i, weights=weights 18 | ) 19 | 20 | def test_RadialDistributionFunction_init(self): 21 | mock_structures = [Mock(spec=Structure), Mock(spec=Structure)] 22 | for s in mock_structures: 23 | s.lattice = Mock(spec=Lattice) 24 | s.lattice.volume = 1.0 25 | indices_i = [0, 1] 26 | with patch("vasppy.rdf.dr_ij") as mock_dr_ij: 27 | mock_dr_ij.side_effect = [np.array([5.0, 6.0]), np.array([6.0, 7.0])] 28 | with patch("vasppy.rdf.shell_volumes") as mock_shell_volumes: 29 | mock_shell_volumes.return_value = np.ones(500) 30 | rdf = RadialDistributionFunction( 31 | structures=mock_structures, indices_i=indices_i 32 | ) 33 | self.assertEqual(rdf.indices_i, [0, 1]) 34 | self.assertEqual(rdf.indices_j, [0, 1]) 35 | self.assertEqual(rdf.nbins, 500) 36 | self.assertEqual(rdf.range, (0.0, 10.0)) 37 | np.testing.assert_array_equal(rdf.intervals, np.linspace(0, 10, 501)) 38 | self.assertEqual(rdf.dr, 0.02) 39 | np.testing.assert_array_equal(rdf.r, np.linspace(0.01, 9.99, 500)) 40 | expected_rdf = np.zeros_like(rdf.r) 41 | expected_rdf[250] = 0.125 42 | expected_rdf[300] = 0.25 43 | expected_rdf[350] = 0.125 44 | expected_coordination_number = np.cumsum(expected_rdf) * 2.0 45 | np.testing.assert_array_almost_equal(rdf.rdf, expected_rdf) 46 | np.testing.assert_array_almost_equal( 47 | rdf.coordination_number, expected_coordination_number 48 | ) 49 | expected_calls = [ 50 | call( 51 | structure=mock_structures[0], 52 | indices_i=[0, 1], 53 | indices_j=[0, 1], 54 | self_reference=False, 55 | ), 56 | call( 57 | structure=mock_structures[1], 58 | indices_i=[0, 1], 59 | indices_j=[0, 1], 60 | self_reference=False, 61 | ), 62 | ] 63 | mock_dr_ij.assert_has_calls(expected_calls) 64 | 65 | 66 | if __name__ == "__main__": 67 | unittest.main() 68 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import hashlib 3 | from vasppy.utils import md5sum, file_md5, validate_checksum, dr_ij 4 | from unittest.mock import patch, mock_open 5 | import numpy as np 6 | from pymatgen.core import Lattice, Structure 7 | 8 | 9 | class UtilsTestCase(unittest.TestCase): 10 | def test_md5sum(self): 11 | string = "abcdefg" 12 | h = hashlib.new("md5") 13 | h.update(string.encode("utf-8")) 14 | self.assertEqual(md5sum(string), h.hexdigest()) 15 | 16 | def test_file_md5(self): 17 | example_file = "abc\nabc\n" 18 | with patch("vasppy.utils.md5sum") as mock_md5sum: 19 | mock_md5sum.return_value = "foo" 20 | with patch( 21 | "vasppy.utils.zopen", mock_open(read_data=example_file), create=True 22 | ) as m: 23 | self.assertEqual(file_md5(m), "foo") 24 | mock_md5sum.assert_called_with(example_file) 25 | 26 | def test_validate_checksum(self): 27 | with patch("vasppy.utils.match_filename"): 28 | with patch("vasppy.utils.file_md5") as mock_file_md5: 29 | mock_file_md5.return_value = "abcdef" 30 | validate_checksum(filename="foo", md5sum="abcdef") 31 | 32 | def test_validate_checksum_raises_ValueError_if_not_matched(self): 33 | with patch("vasppy.utils.match_filename") as mock_match_filename: 34 | mock_match_filename.return_value = "bar" 35 | with patch("vasppy.utils.file_md5") as mock_file_md5: 36 | mock_file_md5.return_value = "bcdefg" 37 | with self.assertRaises(ValueError): 38 | validate_checksum(filename="foo", md5sum="abcdef") 39 | 40 | 41 | class Test_drij(unittest.TestCase): 42 | def test_dr_ij_default(self): 43 | coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]]) 44 | atom_list = ["Na", "Cl"] 45 | lattice = Lattice.from_parameters( 46 | a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90 47 | ) 48 | structure = Structure(lattice, atom_list, coords) 49 | dr = dr_ij(structure) 50 | np.testing.assert_array_almost_equal(dr, np.array([[3.46410162], [3.46410162]])) 51 | 52 | def test_dr_ij_all_distances(self): 53 | coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]]) 54 | atom_list = ["Na", "Cl"] 55 | lattice = Lattice.from_parameters( 56 | a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90 57 | ) 58 | structure = Structure(lattice, atom_list, coords) 59 | dr = dr_ij(structure, self_reference=True) 60 | np.testing.assert_array_almost_equal( 61 | dr, np.array([[0.0, 3.46410162], [3.46410162, 0.0]]) 62 | ) 63 | 64 | def test_dr_ij_indices_i_set(self): 65 | coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]]) 66 | atom_list = ["Na", "Cl"] 67 | lattice = Lattice.from_parameters( 68 | a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90 69 | ) 70 | structure = Structure(lattice, atom_list, coords) 71 | dr = dr_ij(structure, indices_i=[0, 1]) 72 | np.testing.assert_array_almost_equal(dr, np.array([[3.46410162], [3.46410162]])) 73 | 74 | def test_dr_ij_indices_i_indices_j_set(self): 75 | coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]]) 76 | atom_list = ["Na", "Cl"] 77 | lattice = Lattice.from_parameters( 78 | a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90 79 | ) 80 | structure = Structure(lattice, atom_list, coords) 81 | dr = dr_ij(structure, indices_i=[0], indices_j=[1]) 82 | np.testing.assert_array_almost_equal(dr, np.array([[3.46410162]])) 83 | 84 | def test_dr_ij_indices_i_indices_j_set_as_numpy_arrays(self): 85 | coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]]) 86 | atom_list = ["Na", "Cl"] 87 | lattice = Lattice.from_parameters( 88 | a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90 89 | ) 90 | structure = Structure(lattice, atom_list, coords) 91 | dr = dr_ij(structure, indices_i=np.array([0]), indices_j=np.array([1])) 92 | np.testing.assert_array_almost_equal(dr, np.array([[3.46410162]])) 93 | 94 | def test_dr_ij_masking_with_unsorted_indices(self): 95 | coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]]) 96 | atom_list = ["Na", "Cl"] 97 | lattice = Lattice.from_parameters( 98 | a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90 99 | ) 100 | structure = Structure(lattice, atom_list, coords) 101 | dr = dr_ij(structure, indices_i=[1, 0], indices_j=[0, 1]) 102 | np.testing.assert_array_almost_equal(dr, np.array([[3.46410162], [3.46410162]])) 103 | 104 | def test_dr_ij_masking_with_partially_overlapping_indices(self): 105 | coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]]) 106 | atom_list = ["Na", "Cl"] 107 | lattice = Lattice.from_parameters( 108 | a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90 109 | ) 110 | structure = Structure(lattice, atom_list, coords) 111 | dr = dr_ij(structure, indices_i=[0], indices_j=[0, 1]) 112 | np.testing.assert_array_almost_equal(dr, np.array([[3.46410162]])) 113 | 114 | def test_dr_ij_masking_with_partially_overlapping_indices_with_self_reference(self): 115 | coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]]) 116 | atom_list = ["Na", "Cl"] 117 | lattice = Lattice.from_parameters( 118 | a=4.0, b=4.0, c=4.0, alpha=90, beta=90, gamma=90 119 | ) 120 | structure = Structure(lattice, atom_list, coords) 121 | dr = dr_ij(structure, indices_i=[0], indices_j=[0, 1], self_reference=True) 122 | np.testing.assert_array_almost_equal(dr, np.array([[0.0, 3.46410162]])) 123 | 124 | 125 | if __name__ == "__main__": 126 | unittest.main() 127 | -------------------------------------------------------------------------------- /tests/test_vaspmeta.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import patch, mock_open 3 | 4 | from vasppy.vaspmeta import VASPMeta 5 | 6 | 7 | class VASPMetaTestCase(unittest.TestCase): 8 | def test_init_vaspmeta(self): 9 | title = "title" 10 | description = "description" 11 | notes = "notes" 12 | valid_status = ["to-run", "incomplete", "finished", "dropped"] 13 | for s in valid_status: 14 | vaspmeta = VASPMeta(title, description, status=s, notes=notes) 15 | self.assertEqual(vaspmeta.title, title) 16 | self.assertEqual(vaspmeta.description, description) 17 | self.assertEqual(vaspmeta.status, s) 18 | self.assertEqual(vaspmeta.notes, notes) 19 | 20 | def test_init_vaspmeta_with_invalid_status_raises_valueerror(self): 21 | title = "title" 22 | description = "description" 23 | invalid_status = "foo" 24 | with self.assertRaises(ValueError): 25 | VASPMeta(title, description, status=invalid_status) 26 | 27 | def test_init_vaspmeta_with_invalid_type_raises_valueerror(self): 28 | title = "title" 29 | description = "description" 30 | status = "finished" 31 | type = "invalid type" 32 | with self.assertRaises(ValueError): 33 | VASPMeta(title, description, status, type=type) 34 | 35 | def test_init_vaspmeta_with_valid_type(self): 36 | title = "title" 37 | description = "description" 38 | status = "finished" 39 | valid_types = ["single-point", "neb"] 40 | for t in valid_types: 41 | vaspmeta = VASPMeta(title, description, status, type=t) 42 | self.assertEqual(vaspmeta.type, t) 43 | 44 | def test_init_vaspmeta_with_no_type(self): 45 | title = "title" 46 | description = "description" 47 | status = "finished" 48 | vaspmeta = VASPMeta(title, description, status) 49 | self.assertEqual(vaspmeta.type, None) 50 | 51 | def test_init_vaspmeta_with_no_notes(self): 52 | title = "title" 53 | description = "description" 54 | status = "finished" 55 | vaspmeta = VASPMeta(title, description, status) 56 | self.assertEqual(vaspmeta.notes, None) 57 | 58 | def test_init_vaspmeta_with_file_tracking(self): 59 | title = "title" 60 | description = "description" 61 | status = "finished" 62 | track = {"DOSCAR": "doscar", "CHGCAR": "chgcar"} 63 | vaspmeta = VASPMeta(title, description, status, track=track) 64 | self.assertEqual(vaspmeta.track, track) 65 | 66 | def test_init_vaspmeta_with_no_file_tracking(self): 67 | title = "title" 68 | description = "description" 69 | status = "finished" 70 | vaspmeta = VASPMeta(title, description, status) 71 | self.assertEqual(vaspmeta.track, None) 72 | 73 | def test_from_file(self): 74 | example_file = """\ 75 | title: title 76 | description: description 77 | notes: notes 78 | status: finished\ 79 | """ 80 | with patch("vasppy.vaspmeta.VASPMeta") as mock_VASPMeta: 81 | mock_VASPMeta.return_value = "my VASP metadata" 82 | with patch("builtins.open", mock_open(read_data=example_file), create=True): 83 | vaspmeta = VASPMeta.from_file(example_file) 84 | mock_VASPMeta.assert_called_with( 85 | "title", "description", "finished", notes="notes", type=None 86 | ) 87 | self.assertEqual(vaspmeta, mock_VASPMeta.return_value) 88 | 89 | def test_from_file_with_no_notes_entry(self): 90 | example_file = """\ 91 | title: title 92 | description: description 93 | status: finished\ 94 | """ 95 | with patch("vasppy.vaspmeta.VASPMeta") as mock_VASPMeta: 96 | mock_VASPMeta.return_value = "my VASP metadata" 97 | with patch("builtins.open", mock_open(read_data=example_file), create=True): 98 | vaspmeta = VASPMeta.from_file(example_file) 99 | mock_VASPMeta.assert_called_with( 100 | "title", "description", "finished", notes=None, type=None 101 | ) 102 | self.assertEqual(vaspmeta, mock_VASPMeta.return_value) 103 | 104 | def test_from_file_with_type(self): 105 | example_file = """\ 106 | title: title 107 | description: description 108 | status: finished 109 | type: single-point\ 110 | """ 111 | with patch("vasppy.vaspmeta.VASPMeta") as mock_VASPMeta: 112 | with patch("builtins.open", mock_open(read_data=example_file), create=True): 113 | vaspmeta = VASPMeta.from_file(example_file) 114 | mock_VASPMeta.assert_called_with( 115 | "title", "description", "finished", notes=None, type="single-point" 116 | ) 117 | self.assertEqual(vaspmeta, mock_VASPMeta.return_value) 118 | 119 | 120 | if __name__ == "__main__": 121 | unittest.main() 122 | -------------------------------------------------------------------------------- /tests/test_xdatcar.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from vasppy import xdatcar 4 | from vasppy.poscar import Poscar 5 | 6 | 7 | class TestXdatcar(unittest.TestCase): 8 | def test_xdatcar_is_initialised(self): 9 | xd = xdatcar.Xdatcar() 10 | self.assertEqual(type(xd.poscar[0]), Poscar) 11 | 12 | 13 | if __name__ == "__main__": 14 | unittest.main() 15 | -------------------------------------------------------------------------------- /vasppy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmorgan/vasppy/f913b1bd034e4b106bb83e13c0f4c5a0e09151b7/vasppy/__init__.py -------------------------------------------------------------------------------- /vasppy/atom.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class Atom: 5 | """ 6 | Class for individual atoms 7 | """ 8 | 9 | def __init__( 10 | self, label: str, r: np.ndarray 11 | ) -> None: # currently assume fractional coordinates 12 | """ 13 | Initialise an Atom instance 14 | 15 | Args: 16 | label (Str): a label for this atom 17 | r (numpy.array): the atom coordinates 18 | 19 | Returns: 20 | None 21 | """ 22 | self.label = label 23 | self.r = r 24 | -------------------------------------------------------------------------------- /vasppy/band.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | 4 | def handle_occupancy(occupancy, negative_occupancies="warn"): 5 | valid_negative_occupancies = ["warn", "raise", "ignore", "zero"] 6 | if negative_occupancies not in valid_negative_occupancies: 7 | raise ValueError( 8 | "valid options for negative_occupancies are {}".format( 9 | valid_negative_occupancies 10 | ) 11 | ) 12 | if occupancy < 0: 13 | if negative_occupancies == "warn": 14 | warnings.warn( 15 | "One or more occupancies in your PROCAR file are negative.", 16 | stacklevel=2, 17 | ) 18 | elif negative_occupancies == "raise": 19 | raise ValueError( 20 | "One or more occupancies in your PROCAR file are negative." 21 | ) 22 | elif negative_occupancies == "ignore": 23 | pass 24 | elif negative_occupancies == "zero": 25 | occupancy = 0.0 26 | return occupancy 27 | 28 | 29 | class Band: 30 | def __init__(self, index, energy, occupancy, negative_occupancies="warn"): 31 | self.index = index 32 | self.energy = energy 33 | self.occupancy = handle_occupancy( 34 | occupancy, negative_occupancies=negative_occupancies 35 | ) 36 | 37 | def __eq__(self, other): 38 | return ( 39 | (self.index == other.index) 40 | & (self.energy == other.energy) 41 | & (self.occupancy == other.occupancy) 42 | ) 43 | -------------------------------------------------------------------------------- /vasppy/calculation.py: -------------------------------------------------------------------------------- 1 | import yaml # type: ignore 2 | import re 3 | from collections import Counter 4 | 5 | 6 | class Calculation: 7 | """ 8 | Class describing a single VASP calculation 9 | """ 10 | 11 | def __init__(self, title, energy, stoichiometry): 12 | """ 13 | Initialise a Calculation object 14 | 15 | Args: 16 | title (Str): The title string for this calculation. 17 | energy (Float): Final energy in eV. 18 | stoichiometry (Dict{Str:Int}): A dict desribing the calculation stoichiometry, 19 | e.g. { 'Ti': 1, 'O': 2 } 20 | 21 | Returns: 22 | None 23 | """ 24 | self.title = title 25 | self.energy = energy 26 | self.stoichiometry = Counter(stoichiometry) 27 | 28 | def __mul__(self, scaling): 29 | """ 30 | "Multiply" this Calculation by a scaling factor. 31 | Returns a new Calculation with the same title, but scaled energy and stoichiometry. 32 | 33 | Args: 34 | scaling (float): The scaling factor. 35 | 36 | Returns: 37 | (vasppy.Calculation): The scaled Calculation. 38 | """ 39 | new_calculation = Calculation( 40 | title=self.title, 41 | energy=self.energy * scaling, 42 | stoichiometry=self.scale_stoichiometry(scaling), 43 | ) 44 | return new_calculation 45 | 46 | def __truediv__(self, scaling): 47 | """ 48 | Implements division by a scaling factor. 49 | Returns a new Calculation with the same title, but scaled energy and stoichiometry. 50 | 51 | Args: 52 | scaling (float): The scaling factor. 53 | 54 | Returns: 55 | (vasppy.Calculation): The scaled Calculation. 56 | """ 57 | return self * (1 / scaling) 58 | 59 | def scale_stoichiometry(self, scaling): 60 | """ 61 | Scale the Calculation stoichiometry 62 | Returns the stoichiometry, scaled by the argument scaling. 63 | 64 | Args: 65 | scaling (float): The scaling factor. 66 | 67 | Returns: 68 | (Counter(Str:Int)): The scaled stoichiometry as a :obj:`Counter` of ``label: stoichiometry`` pairs 69 | """ 70 | return {k: v * scaling for k, v in self.stoichiometry.items()} 71 | 72 | 73 | def delta_E(reactants, products, check_balance=True): 74 | """ 75 | Calculate the change in energy for reactants --> products. 76 | 77 | Args: 78 | reactants (list(:obj:`vasppy.Calculation`)): A `list` of :obj:`vasppy.Calculation` objects. The initial state. 79 | products (list(:obj:`vasppy.Calculation`)): A `list` of :obj:`vasppy.Calculation` objects. The final state. 80 | check_balance (:obj:`bool`, optional): Check that the reaction stoichiometry is balanced. Default is ``True``. 81 | 82 | Returns: 83 | (float) The change in energy. 84 | """ 85 | if check_balance: 86 | if delta_stoichiometry(reactants, products) != {}: 87 | raise ValueError( 88 | "reaction is not balanced: {}".format( 89 | delta_stoichiometry(reactants, products) 90 | ) 91 | ) 92 | return sum([r.energy for r in products]) - sum([r.energy for r in reactants]) 93 | 94 | 95 | def delta_stoichiometry(reactants, products): 96 | """ 97 | Calculate the change in stoichiometry for reactants --> products. 98 | 99 | Args: 100 | reactants (list(:obj:`vasppy.Calculation`): A `list` of :obj:`vasppy.Calculation objects.` The initial state. 101 | products (list(:obj:`vasppy.Calculation`): A `list` of :obj:`vasppy.Calculation objects.` The final state. 102 | 103 | Returns: 104 | (Counter): The change in stoichiometry. 105 | """ 106 | totals = Counter() 107 | for r in reactants: 108 | totals.update((r * -1.0).stoichiometry) 109 | for p in products: 110 | totals.update(p.stoichiometry) 111 | to_return = {} 112 | for c in totals: 113 | if totals[c] != 0: 114 | to_return[c] = totals[c] 115 | return to_return 116 | 117 | 118 | def energy_string_to_float(string): 119 | """ 120 | Convert a string of a calculation energy, e.g. '-1.2345 eV' to a float. 121 | 122 | Args: 123 | string (str): The string to convert. 124 | 125 | Return 126 | (float) 127 | """ 128 | energy_re = re.compile(r"(-?\d+\.\d+)") 129 | return float(energy_re.match(string).group(0)) 130 | 131 | 132 | def import_calculations_from_file(filename, skip_incomplete_records=False): 133 | """ 134 | Construct a list of :obj:`Calculation` objects by reading a YAML file. 135 | Each YAML document should include ``title``, ``stoichiometry``, and ``energy`` fields, e.g.:: 136 | 137 | title: my calculation 138 | stoichiometry: 139 | - A: 1 140 | - B: 2 141 | energy: -0.1234 eV 142 | 143 | Separate calculations should be distinct YAML documents, separated by `---` 144 | 145 | Args: 146 | filename (str): Name of the YAML file to read. 147 | skip_incomplete_records (bool): Do not parse YAML documents missing one or more of 148 | the required keys. Default is ``False``. 149 | 150 | Returns: 151 | (dict(vasppy.Calculation)): A dictionary of :obj:`Calculation` objects. For each :obj:`Calculation` object, the ``title`` field from the YAML input is used as the dictionary key. 152 | """ 153 | calcs = {} 154 | with open(filename, "r") as stream: 155 | docs = yaml.load_all(stream, Loader=yaml.SafeLoader) 156 | for d in docs: 157 | if skip_incomplete_records: 158 | if ( 159 | ("title" not in d) 160 | or ("stoichiometry" not in d) 161 | or ("energy" not in d) 162 | ): 163 | continue 164 | if "stoichiometry" in d: 165 | stoichiometry = Counter() 166 | for s in d["stoichiometry"]: 167 | stoichiometry.update(s) 168 | else: 169 | raise ValueError(f'stoichiometry not found for "{d["title"]}"') 170 | if d["title"] in calcs: 171 | raise ValueError(f'More than one calculation has the same title: {d["title"]}') 172 | calcs[d["title"]] = Calculation( 173 | title=d["title"], 174 | stoichiometry=stoichiometry, 175 | energy=energy_string_to_float(d["energy"]), 176 | ) 177 | return calcs 178 | -------------------------------------------------------------------------------- /vasppy/data/GGA_md5.yaml: -------------------------------------------------------------------------------- 1 | Ac: 8c84936e001650a36f2308a726c523e7 2 | Ac_s: 95a9fdb25011df32bf931bf9f95bf677 3 | Ag: 39277c945a9786a7ddf7d5a642c969fe 4 | Al: b1d947984379eb01f70e04f0b0786cc1 5 | Al_h: 369ed4d4996952afb98fb9bb74f73e08 6 | Ar: 90ed412274591809ed1a86c38d1e199c 7 | As: 863cd990362db2801eec3eae1ffab388 8 | Au: a05903b0a24d1f0640b2622c8c676610 9 | B: 855b4d620d15d485030279824e2ed395 10 | B_h: aa4fe162348dddda2a75bb20e2fcb467 11 | B_s: 37e9b34b0b4c52c93078cdcc0f2ec0e6 12 | Ba_sv: 6e953fc070f3c90dbb8ece8a4b996ba6 13 | Be: 70b0683ba3ff677ed42f47d84f894fa6 14 | Be_sv: ead81323e7cb91242e361b2ee1883596 15 | Bi: 2020144d04396db67a1dc65f9d1e5c8e 16 | Bi_d: 9fb8bff76611e718ffa9320224303393 17 | Br: 9a8aa54e918c215c6744e86545734a0b 18 | C: 5d9d9a5215191e6de6f5d444022eca48 19 | C_h: af13be43933f37f83cec9926e1434a5b 20 | C_s: 0e603e2c6acd7faf4d4c1d7cc3dc0b88 21 | Ca: 2cfcce07c35ee4fe15271ea82302f602 22 | Ca_pv: fa446392d2e89be634a977feccdca488 23 | Ca_sv: e6b809b9467f1ef0276d68a7bccc0079 24 | Cd: a38ee924516dda6188855d8250d20d72 25 | Ce: 93db055049ffb39a0831fae76649fc22 26 | Ce_3: 7e7e4f8be8dc7aeebe29201cad7e8e80 27 | Ce_s: dc17d9626412ad190fc2656cc338203b 28 | Cl: 07b6a81b71715cd88192659ca5b67446 29 | Cl_h: 555442dd0a61d08d0df0f0686f26b584 30 | Co: 17964872269e6da2031b2c6f74ff01ac 31 | Cr: 75a8ebf8b02a8c7668bc96fc47ea5af6 32 | Cr_pv: fd46d4a02214541f586c5c278dfe5446 33 | Cs_sv: 0c18ca1ceef9d2857d92368947335ad9 34 | Cu: 5bce98774a44d0db785b9702089f7e26 35 | Cu_pv: 85355af0ea6b73e2a38f987ad76414d3 36 | Dy_3: ca64394b868d9f2f7672d145853dcde5 37 | Er_3: e48c3b9311654d5dfa43d17fe669f755 38 | Eu: 9c48f4c306d61823ea26ae8080a0c2c9 39 | Eu_2: 629d544cd040f53e04e321c0b37a58a9 40 | F: f826add23862e81993aeb9f6f4578519 41 | F_h: 28dbc97cdfe84e185f0785bfc72b9d68 42 | F_s: fd4e522dee2c39e0f5545eef75481206 43 | Fe: af9162490c7ba1fb54470fe694ace46a 44 | Fe_pv: af7f2616461457bd969597675ac6b979 45 | Fe_sv: 9139fee9483e1c8584924f82d943a773 46 | Ga: 405d630dd6e727a5024306e762ee68f3 47 | Ga_d: e6507428267f7f2f3f0ca649f12c3963 48 | Ga_h: 147abcb548d98849c031596f476afb8d 49 | Gd: 0b1db9fb8111c07c7356ec36495b5aeb 50 | Gd_3: 05401c5df05a5fd78f5cfa9d754005f1 51 | Ge: e12cffd23c33aca36305586fe67154dd 52 | Ge_d: 40a9f10dbecf0be6c5df8790bf3fd66f 53 | Ge_h: bdc0c9f007a44bd876802904c7bbe586 54 | H: 140d7a0918df4c990b60772598e7777a 55 | H.5: 9e5203a9a302adf302e39465468fbc47 56 | H.75: 14a5416062998a59b4dd0fb549778699 57 | H1.25: a0bdb241168313d3e5bcf6029b509e93 58 | H1.5: f84b63437fdeb24765f6331a3524786a 59 | H_h: 9123b60bd1cddc4ad6bf50acd300680b 60 | He: 230942b78a7aba758fa46d46df42430d 61 | Hf: 3f1572eb155ff63457d12797af8834c8 62 | Hf_pv: 718eef4cb021cca014daca2c5cdc3332 63 | Hg: 2ce3e6d38658022c51d3bdfa1244511b 64 | Ho_3: cfd1f1c8cd6dcc911bc74df768a507a8 65 | I: e6bf346c007cf680c3a99d0ee59e5ff7 66 | In: 20fb7fcee23c859ea047eb692dabd341 67 | In_d: 97d352df20b81868b708a5adcbf94def 68 | Ir: 2eaff92eb3e3ba72087f9785e13f2ed7 69 | K_pv: bc68ea149e9e3e67465bdc977a341a74 70 | K_sv: 868206abf76a0fc503a7eabae9a0e671 71 | Kr: de3ea20f253c80645ba861128e9abb43 72 | La: 57e7cdb5a0b4016210318f2454ac21bd 73 | La_s: a1b69b0eec5940d1da2b4fa167344ad9 74 | Li: 389cf359a2f0670b0a03705da0d92e46 75 | Li_sv: ffa3b4f10c33767aa06e357f76bc1b03 76 | Lu_3: 81f00396937c990673b51ed6ab57335e 77 | Mg: b263f8856303eae039ad2d126e77bbc4 78 | Mg_pv: b0e3683054a3af1bcdb004403a20ec3d 79 | Mn: 9070657c1cd4b32eaa806fd6ec8b29cb 80 | Mn_pv: c2edf7adef8a5fbdf6981b13eb4197e9 81 | Mo: 1004f45fe661425924a18e81c9d096cb 82 | Mo_pv: d2f943e543db31280fd9a7576d4e2b0a 83 | N: c6c3f26fe10279a5a0a3cb5e6e27fbd5 84 | N_h: 1ea0a4b0dde67254cdb2d21854afc07b 85 | N_s: 0b169b910326506094ba9539081a744f 86 | Na: 6d8ecdda032ca319d5c741dd428f945e 87 | Na_pv: f245e8d730138b18c7caf93f34a8b14a 88 | Na_sv: 4a8f239d379f251f5b3171dbabc0528d 89 | Nb_pv: 85ec2df5e91ff10e49ae3c98d200e0fd 90 | Nb_sv: b2b3d55a3b6e58a8cb424b89c4ce2aa1 91 | Nd: 18f1e1c6e8d71d72b0dd1ccf4aad9dcb 92 | Nd_3: 04ceb4a4cd69799567bf8f8aa8453e9f 93 | Ne: 7fd5008321fbc87850280609433531df 94 | Ni: 5957d561dfeb8b2c0b77e3bbbf4647bd 95 | Ni_pv: 1edb477085ee6c779ae372f2440ee416 96 | Np: e0f5dee9dd03bc613d938e258b19dbfe 97 | Np_s: a5979d83571970358fba40303e0ad2a3 98 | O: 0255483b998f590aadc1e7e62c6a6216 99 | O_h: c8c387625fa7c285f5288ee1df71c07a 100 | O_s: 9f52520f0334686f5cb4aa87bd37486e 101 | Os: 7f9fb06e0b23cce4ca9eafa18e474d50 102 | Os_pv: c73d8aaa09137dd1e4e530844ccf25c2 103 | P: 51f8c161115885a5dac34b247420a44b 104 | P_h: 53d4705c22eeb658eb431f717cac6160 105 | Pa: 62d018bb49199dd57f30efdc682354cc 106 | Pa_s: 5fa3a950c7e1052ea7db98486d985f3b 107 | Pb: 9c294738ea6f122616dcef855b070475 108 | Pb_d: b9da96e65065129ef12f567887580213 109 | Pd: ee97427ffae5455bc023b7e0a0490897 110 | Pd_pv: 8f9d5f875d5542d128fa970f182337cd 111 | Pm: 0c30c48294be3e9a934574e8f5376a62 112 | Pm_3: 403c86a40bee813002550b29984bef58 113 | Pr: 8caae85e789f9214ebb686b47eb5cd4a 114 | Pr_3: ecd8e2a732a84124ebb3c3c8b545c379 115 | Pt: d69e9d0cf59724336f11730eb2cd0b95 116 | Pu: e4eca723428170e48cd9edbe94a8ba09 117 | Pu_s: c00d31bcc05e7ce7c30165529823627e 118 | Rb_pv: d11489b0828ff100e5ab1d3284e62074 119 | Rb_sv: 93f351b07d19603049a34f7c2119fe52 120 | Re: 1c97528913c74947ecceeb64ff778c3c 121 | Re_pv: 16fad93aa36332c46b240dc3b8558999 122 | Rh: 55547fbd6fcf11d7fde25ab6232a6a5a 123 | Rh_pv: daa23016fd24638a294fa7f0c3d10e23 124 | Ru: 720e3f3d755eb2cde8aa7faa216f1781 125 | Ru_pv: 1b6aae0ea6dee02e54668ec33ef9d115 126 | Ru_sv: fd509a1aa4b612eca306347785c72cc2 127 | S: 884522c45d0383c14624834330e2d638 128 | S_h: 71ed906b8389b448c483fc7a99581617 129 | Sb: 6d8948cd37189f4e4dd25bf2faf5be25 130 | Sc: bd9560671f4b74598083a443cbd7656b 131 | Sc_sv: d3fa5a5cf94262f1f318fa3d4b58abb7 132 | Se: ae289f0158094845f991fea1e6bc3213 133 | Si: fa1ca8b47f680b37e46b843a4651a032 134 | Si_h: d79218f73e4b0bf14e388d9c9a4745ae 135 | Sm: a570875c483ed910946dc4adc77b0494 136 | Sm_2: 46e61197044ee8d4e9051cf194f5104c 137 | Sm_3: 34081ab91826e45b3fbd4f9cc9399862 138 | Sn: c82c3f0930c9668e91889c9d570e6267 139 | Sn_d: 3a8b5620d6c4b13255d2302e300c2610 140 | Sr_sv: ed80aa48f32e3e4ef74e323b99eb68e6 141 | Ta: c3c61844b66931cb585351de2f62d57e 142 | Ta_pv: da7bd3a2eb2d81b354149d1c59e76080 143 | Tb_3: 65c0a820fda66135023edf357f7702c8 144 | Tc: fb05ed41e1cd708a1f32a48ae163b15e 145 | Tc_pv: 191032ad2564da987e8d595f4e39d55b 146 | Te: 91cd7274b96cf472bf9e79a6c1405d4e 147 | Th: 1e742a973b4c6446721452ab61fb64b3 148 | Th_s: a69dbeeffcef4afe95855eff44e6e297 149 | Ti: 67c881248b8abc77fd6f1ec60ba28ce0 150 | Ti_pv: ba5214f37a41c0c71bc3ae99267952d7 151 | Ti_sv: 5fe2d8774445fe6fc0e37e01bb1a6e90 152 | Tl: 9bc99bd15449c24eb2734e48653a22c5 153 | Tl_d: 2b6b043891ac43d5ab739f9623684138 154 | Tm: f4e0aa99eff443800adb7ddc059cb7fe 155 | Tm_3: 28607d252d2cd67f0d04c58110bf4c5e 156 | U: 6219c236d4d45ece6cbc5b677a1fcb55 157 | U_s: e57ba4c4f85bccd52273d66629ad6f18 158 | V: 7df88700b3ff7977361fc356ac1c79e2 159 | V_pv: 94434d67b75fcc5d3c34adc75e4c4da5 160 | V_sv: 52b4cc9580238169a2383464b6ff9761 161 | W: 82300ce6b9d788d569075df2b7e46d05 162 | W_pv: f991cc70c485b3432e5f66df766b9814 163 | Xe: 03a1562eb378b4d860fd567a27703dfe 164 | Y_sv: 771600ced66e074503cdbaf6b9aa7307 165 | Yb: 40cd72ff0c968f687103edb6e8873566 166 | Yb_2: 2b565166c1f60ed89adf666f1b31fa5b 167 | Zn: a0062191fe4e00dcf6cfd024e2a3afc9 168 | Zr: 69c81c5905d00dfa22d3275a732ec205 169 | Zr_sv: c8b381ec47a5b1c7e2bfcbee29cdc581 170 | -------------------------------------------------------------------------------- /vasppy/data/GGA_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ac_s: 9 3 | Ag: 11 4 | Al: 3 5 | Al_h: 3 6 | Ar: 8 7 | As: 5 8 | Au: 11 9 | B: 3 10 | B_h: 3 11 | B_s: 3 12 | Ba_sv: 10 13 | Be: 2 14 | Be_sv: 4 15 | Bi: 5 16 | Bi_d: 15 17 | Br: 7 18 | C: 4 19 | C_h: 4 20 | C_s: 4 21 | Ca: 2 22 | Ca_pv: 8 23 | Ca_sv: 10 24 | Cd: 12 25 | Ce: 12 26 | Ce_3: 11 27 | Ce_s: 10 28 | Cl: 7 29 | Cl_h: 7 30 | Co: 9 31 | Cr: 6 32 | Cr_pv: 12 33 | Cs_sv: 9 34 | Cu: 11 35 | Cu_pv: 17 36 | Dy_3: 9 37 | Er_3: 9 38 | Eu: 17 39 | Eu_2: 8 40 | F: 7 41 | F_h: 7 42 | F_s: 7 43 | Fe: 8 44 | Fe_pv: 14 45 | Fe_sv: 16 46 | Ga: 3 47 | Ga_d: 13 48 | Ga_h: 13 49 | Gd: 18 50 | Gd_3: 9 51 | Ge: 4 52 | Ge_d: 14 53 | Ge_h: 14 54 | H: 1 55 | H.5: 0 56 | H.75: 0 57 | H1.25: 1 58 | H1.5: 1 59 | H_h: 1 60 | He: 2 61 | Hf: 4 62 | Hf_pv: 10 63 | Hg: 12 64 | Ho_3: 9 65 | I: 7 66 | In: 3 67 | In_d: 13 68 | Ir: 9 69 | K_pv: 7 70 | K_sv: 9 71 | Kr: 8 72 | La: 11 73 | La_s: 9 74 | Li: 1 75 | Li_sv: 3 76 | Lu_3: 9 77 | Mg: 2 78 | Mg_pv: 8 79 | Mn: 7 80 | Mn_pv: 13 81 | Mo: 6 82 | Mo_pv: 12 83 | N: 5 84 | N_h: 5 85 | N_s: 5 86 | Na: 1 87 | Na_pv: 7 88 | Na_sv: 9 89 | Nb_pv: 11 90 | Nb_sv: 13 91 | Nd: 14 92 | Nd_3: 11 93 | Ne: 8 94 | Ni: 10 95 | Ni_pv: 16 96 | Np: 15 97 | Np_s: 15 98 | O: 6 99 | O_h: 6 100 | O_s: 6 101 | Os: 8 102 | Os_pv: 14 103 | P: 5 104 | P_h: 5 105 | Pa: 13 106 | Pa_s: 11 107 | Pb: 4 108 | Pb_d: 14 109 | Pd: 10 110 | Pd_pv: 16 111 | Pm: 15 112 | Pm_3: 11 113 | Pr: 13 114 | Pr_3: 11 115 | Pt: 10 116 | Pu: 16 117 | Pu_s: 16 118 | Rb_pv: 7 119 | Rb_sv: 9 120 | Re: 7 121 | Re_pv: 13 122 | Rh: 9 123 | Rh_pv: 15 124 | Ru: 8 125 | Ru_pv: 14 126 | Ru_sv: 16 127 | S: 6 128 | S_h: 6 129 | Sb: 5 130 | Sc: 3 131 | Sc_sv: 11 132 | Se: 6 133 | Si: 4 134 | Si_h: 4 135 | Sm: 16 136 | Sm_2: 10 137 | Sm_3: 11 138 | Sn: 4 139 | Sn_d: 14 140 | Sr_sv: 10 141 | Ta: 5 142 | Ta_pv: 11 143 | Tb_3: 9 144 | Tc: 7 145 | Tc_pv: 13 146 | Te: 6 147 | Th: 12 148 | Th_s: 10 149 | Ti: 4 150 | Ti_pv: 10 151 | Ti_sv: 12 152 | Tl: 3 153 | Tl_d: 13 154 | Tm: 23 155 | Tm_3: 9 156 | U: 14 157 | U_s: 14 158 | V: 5 159 | V_pv: 11 160 | V_sv: 13 161 | W: 6 162 | W_pv: 12 163 | Xe: 8 164 | Y_sv: 11 165 | Yb: 24 166 | Yb_2: 8 167 | Zn: 12 168 | Zr: 4 169 | Zr_sv: 12 170 | -------------------------------------------------------------------------------- /vasppy/data/LDA_52_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ag: 11 3 | Ag_GW: 11 4 | Ag_pv: 17 5 | Al: 3 6 | Al_GW: 3 7 | Al_sv_GW: 11 8 | Am: 17 9 | Ar: 8 10 | Ar_GW: 8 11 | As: 5 12 | As_GW: 5 13 | As_d: 15 14 | At: 7 15 | At_d: 17 16 | Au: 11 17 | Au_GW: 11 18 | Au_pv_GW: 17 19 | B: 3 20 | B_GW: 3 21 | B_h: 3 22 | B_s: 3 23 | Ba_sv: 10 24 | Ba_sv_GW: 10 25 | Be: 2 26 | Be_GW: 2 27 | Be_sv: 4 28 | Be_sv_GW: 4 29 | Bi: 5 30 | Bi_GW: 5 31 | Bi_d: 15 32 | Bi_d_GW: 15 33 | Br: 7 34 | Br_GW: 7 35 | C: 4 36 | C_GW: 4 37 | C_GW_new: 4 38 | C_h: 4 39 | C_s: 4 40 | Ca_pv: 8 41 | Ca_sv: 10 42 | Ca_sv_GW: 10 43 | Cd: 12 44 | Cd_GW: 12 45 | Cd_pv_GW: 18 46 | Cd_sv_GW: 20 47 | Ce: 12 48 | Ce_GW: 12 49 | Ce_h: 12 50 | Cl: 7 51 | Cl_GW: 7 52 | Cl_h: 7 53 | Cm: 18 54 | Co: 9 55 | Co_GW: 9 56 | Co_pv: 15 57 | Co_sv: 17 58 | Co_sv_GW: 17 59 | Cr: 6 60 | Cr_pv: 12 61 | Cr_sv: 14 62 | Cr_sv_GW: 14 63 | Cs_sv: 9 64 | Cs_sv_GW: 9 65 | Cu: 11 66 | Cu_GW: 11 67 | Cu_pv: 17 68 | Cu_pv_GW: 17 69 | F: 7 70 | F_GW: 7 71 | F_GW_new: 7 72 | F_h: 7 73 | F_s: 7 74 | Fe: 8 75 | Fe_GW: 8 76 | Fe_pv: 14 77 | Fe_sv: 16 78 | Fe_sv_GW: 16 79 | Fr_sv: 9 80 | Ga: 3 81 | Ga_GW: 3 82 | Ga_d: 13 83 | Ga_d_GW: 13 84 | Ga_h: 13 85 | Ga_pv_GW: 19 86 | Ga_sv_GW: 21 87 | Ge: 4 88 | Ge_GW: 4 89 | Ge_d: 14 90 | Ge_d_GW: 14 91 | Ge_h: 14 92 | Ge_sv_GW: 22 93 | H: 1 94 | H.25: 0 95 | H.33: 0 96 | H.42: 0 97 | H.5: 0 98 | H.58: 0 99 | H.66: 0 100 | H.75: 0 101 | H1.25: 1 102 | H1.33: 1 103 | H1.5: 1 104 | H1.66: 1 105 | H1.75: 1 106 | H_AE: 1 107 | H_GW: 1 108 | H_h: 1 109 | H_h_GW: 1 110 | H_s: 1 111 | He: 2 112 | He_GW: 2 113 | Hf: 4 114 | Hf_pv: 10 115 | Hf_sv: 12 116 | Hf_sv_GW: 12 117 | Hg: 12 118 | I: 7 119 | I_GW: 7 120 | In: 3 121 | In_d: 13 122 | In_d_GW: 13 123 | Ir: 9 124 | Ir_sv_GW: 17 125 | K_pv: 7 126 | K_sv: 9 127 | K_sv_GW: 9 128 | Kr: 8 129 | Kr_GW: 8 130 | La: 11 131 | La_s: 9 132 | Li: 1 133 | Li_AE_GW: 3 134 | Li_GW: 1 135 | Li_sv: 3 136 | Li_sv_GW: 3 137 | Mg: 2 138 | Mg_GW: 2 139 | Mg_pv: 8 140 | Mg_pv_GW: 8 141 | Mg_sv: 10 142 | Mg_sv_GW: 10 143 | Mn: 7 144 | Mn_GW: 7 145 | Mn_pv: 13 146 | Mn_sv: 15 147 | Mn_sv_GW: 15 148 | Mo: 6 149 | Mo_pv: 12 150 | Mo_sv: 14 151 | Mo_sv_GW: 14 152 | N: 5 153 | N_GW: 5 154 | N_GW_new: 5 155 | N_h: 5 156 | N_s: 5 157 | N_s_GW: 5 158 | Na: 1 159 | Na_pv: 7 160 | Na_sv: 9 161 | Na_sv_GW: 9 162 | Nb_pv: 11 163 | Nb_sv: 13 164 | Nb_sv_GW: 13 165 | Ne: 8 166 | Ne_GW: 8 167 | Ne_GW_soft: 8 168 | Ni: 10 169 | Ni_GW: 10 170 | Ni_pv: 16 171 | Ni_sv_GW: 18 172 | Np: 15 173 | Np_s: 15 174 | O: 6 175 | O_GW: 6 176 | O_GW_new: 6 177 | O_h: 6 178 | O_s: 6 179 | O_s_GW: 6 180 | Os: 8 181 | Os_pv: 14 182 | Os_sv_GW: 16 183 | P: 5 184 | P_GW: 5 185 | P_h: 5 186 | Pa: 13 187 | Pa_s: 11 188 | Pb: 4 189 | Pb_d: 14 190 | Pb_d_GW: 14 191 | Pd: 10 192 | Pd_GW: 10 193 | Pd_pv: 16 194 | Po: 6 195 | Po_d: 16 196 | Pt: 10 197 | Pt_GW: 10 198 | Pt_pv: 16 199 | Pt_pv_GW: 16 200 | Pt_sv_GW: 18 201 | Pu: 16 202 | Pu_s: 16 203 | Ra_sv: 10 204 | Rb_pv: 7 205 | Rb_sv: 9 206 | Rb_sv_GW: 9 207 | Re: 7 208 | Re_pv: 13 209 | Re_sv_GW: 15 210 | Rh: 9 211 | Rh_GW: 9 212 | Rh_pv: 15 213 | Rh_pv_GW: 15 214 | Rh_sv_GW: 17 215 | Rn: 8 216 | Ru: 8 217 | Ru_pv: 14 218 | Ru_pv_GW: 14 219 | Ru_sv: 16 220 | Ru_sv_GW: 16 221 | S: 6 222 | S_GW: 6 223 | S_h: 6 224 | Sb: 5 225 | Sb_GW: 5 226 | Sb_d_GW: 15 227 | Sc: 3 228 | Sc_sv: 11 229 | Sc_sv_GW: 11 230 | Se: 6 231 | Se_GW: 6 232 | Si: 4 233 | Si_GW: 4 234 | Si_sv_GW: 12 235 | Sn: 4 236 | Sn_d: 14 237 | Sn_d_GW: 14 238 | Sr_sv: 10 239 | Sr_sv_GW: 10 240 | Ta: 5 241 | Ta_pv: 11 242 | Ta_sv_GW: 13 243 | Tc: 7 244 | Tc_pv: 13 245 | Tc_sv: 15 246 | Tc_sv_GW: 15 247 | Te: 6 248 | Te_GW: 6 249 | Th: 12 250 | Th_s: 10 251 | Ti: 4 252 | Ti_pv: 10 253 | Ti_sv: 12 254 | Ti_sv_GW: 12 255 | Tl: 3 256 | Tl_d: 13 257 | U: 14 258 | U_s: 14 259 | V: 5 260 | V_pv: 11 261 | V_sv: 13 262 | V_sv_GW: 13 263 | W: 6 264 | W_pv: 12 265 | W_sv_GW: 14 266 | Xe: 8 267 | Xe_GW: 8 268 | Y_sv: 11 269 | Y_sv_GW: 11 270 | Zn: 12 271 | Zn_GW: 12 272 | Zn_pv_GW: 18 273 | Zn_sv_GW: 20 274 | Zr_sv: 12 275 | Zr_sv_GW: 12 276 | -------------------------------------------------------------------------------- /vasppy/data/LDA_54_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ag: 11 3 | Ag_GW: 11 4 | Ag_pv: 17 5 | Ag_sv_GW: 19 6 | Al: 3 7 | Al_GW: 3 8 | Al_sv_GW: 11 9 | Am: 17 10 | Ar: 8 11 | Ar_GW: 8 12 | As: 5 13 | As_GW: 5 14 | As_d: 15 15 | As_sv_GW: 23 16 | At: 7 17 | At_d_GW: 17 18 | At_sv_GW: 25 19 | Au: 11 20 | Au_GW: 11 21 | Au_sv_GW: 19 22 | B: 3 23 | B_GW: 3 24 | B_h: 3 25 | B_s: 3 26 | Ba_sv: 10 27 | Ba_sv_GW: 10 28 | Be: 2 29 | Be_GW: 2 30 | Be_sv: 4 31 | Be_sv_GW: 4 32 | Bi: 5 33 | Bi_GW: 5 34 | Bi_d: 15 35 | Bi_d_GW: 17 36 | Bi_sv_GW: 23 37 | Br: 7 38 | Br_GW: 7 39 | Br_sv_GW: 25 40 | C: 4 41 | C_GW: 4 42 | C_GW_new: 4 43 | C_h: 4 44 | C_h_GW: 4 45 | C_s: 4 46 | Ca_pv: 8 47 | Ca_sv: 10 48 | Ca_sv_GW: 10 49 | Cd: 12 50 | Cd_GW: 12 51 | Cd_sv_GW: 20 52 | Ce: 12 53 | Ce_GW: 12 54 | Ce_h: 12 55 | Cl: 7 56 | Cl_GW: 7 57 | Cl_h: 7 58 | Cm: 18 59 | Co: 9 60 | Co_GW: 9 61 | Co_pv: 15 62 | Co_sv: 17 63 | Co_sv_GW: 17 64 | Cr: 6 65 | Cr_pv: 12 66 | Cr_sv: 14 67 | Cr_sv_GW: 14 68 | Cs_sv: 9 69 | Cs_sv_GW: 9 70 | Cu: 11 71 | Cu_GW: 11 72 | Cu_pv: 17 73 | Cu_sv_GW: 19 74 | F: 7 75 | F_GW: 7 76 | F_GW_new: 7 77 | F_h: 7 78 | F_h_GW: 7 79 | F_s: 7 80 | Fe: 8 81 | Fe_GW: 8 82 | Fe_pv: 14 83 | Fe_sv: 16 84 | Fe_sv_GW: 16 85 | Fr_sv: 9 86 | Ga: 3 87 | Ga_GW: 3 88 | Ga_d: 13 89 | Ga_d_GW: 13 90 | Ga_h: 13 91 | Ga_sv_GW: 21 92 | Ge: 4 93 | Ge_GW: 4 94 | Ge_d: 14 95 | Ge_d_GW: 14 96 | Ge_h: 14 97 | Ge_sv_GW: 22 98 | H: 1 99 | H.25: 0 100 | H.33: 0 101 | H.42: 0 102 | H.5: 0 103 | H.58: 0 104 | H.66: 0 105 | H.75: 0 106 | H1.25: 1 107 | H1.33: 1 108 | H1.5: 1 109 | H1.66: 1 110 | H1.75: 1 111 | H_AE: 1 112 | H_GW: 1 113 | H_h: 1 114 | H_h_GW: 1 115 | H_s: 1 116 | He: 2 117 | He_GW: 2 118 | Hf: 4 119 | Hf_pv: 10 120 | Hf_sv: 12 121 | Hf_sv_GW: 12 122 | Hg: 12 123 | Hg_sv_GW: 20 124 | I: 7 125 | I_GW: 7 126 | I_sv_GW: 25 127 | In: 3 128 | In_d: 13 129 | In_d_GW: 13 130 | In_sv_GW: 21 131 | Ir: 9 132 | Ir_sv_GW: 17 133 | K_pv: 7 134 | K_sv: 9 135 | K_sv_GW: 9 136 | Kr: 8 137 | Kr_GW: 8 138 | La: 11 139 | La_GW: 11 140 | La_s: 9 141 | Li: 1 142 | Li_AE_GW: 3 143 | Li_GW: 1 144 | Li_sv: 3 145 | Li_sv_GW: 3 146 | Mg: 2 147 | Mg_GW: 2 148 | Mg_pv: 8 149 | Mg_pv_GW: 8 150 | Mg_sv: 10 151 | Mg_sv_GW: 10 152 | Mn: 7 153 | Mn_GW: 7 154 | Mn_pv: 13 155 | Mn_sv: 15 156 | Mn_sv_GW: 15 157 | Mo: 6 158 | Mo_pv: 12 159 | Mo_sv: 14 160 | Mo_sv_GW: 14 161 | N: 5 162 | N_GW: 5 163 | N_GW_new: 5 164 | N_h: 5 165 | N_h_GW: 5 166 | N_s: 5 167 | N_s_GW: 5 168 | Na: 1 169 | Na_pv: 7 170 | Na_sv: 9 171 | Na_sv_GW: 9 172 | Nb_pv: 11 173 | Nb_sv: 13 174 | Nb_sv_GW: 13 175 | Ne: 8 176 | Ne_GW: 8 177 | Ne_s_GW: 8 178 | Ni: 10 179 | Ni_GW: 10 180 | Ni_pv: 16 181 | Ni_sv_GW: 18 182 | Np: 15 183 | Np_s: 15 184 | O: 6 185 | O_GW: 6 186 | O_GW_new: 6 187 | O_h: 6 188 | O_h_GW: 6 189 | O_s: 6 190 | O_s_GW: 6 191 | Os: 8 192 | Os_pv: 14 193 | Os_sv_GW: 16 194 | P: 5 195 | P_GW: 5 196 | P_h: 5 197 | Pa: 13 198 | Pa_s: 11 199 | Pb: 4 200 | Pb_d: 14 201 | Pb_d_GW: 16 202 | Pb_sv_GW: 22 203 | Pd: 10 204 | Pd_GW: 10 205 | Pd_pv: 16 206 | Pd_sv_GW: 18 207 | Po: 6 208 | Po_d: 16 209 | Po_d_GW: 18 210 | Po_sv_GW: 24 211 | Pt: 10 212 | Pt_GW: 10 213 | Pt_pv: 16 214 | Pt_sv_GW: 18 215 | Pu: 16 216 | Pu_s: 16 217 | Ra_sv: 10 218 | Rb_pv: 7 219 | Rb_sv: 9 220 | Rb_sv_GW: 9 221 | Re: 7 222 | Re_pv: 13 223 | Re_sv_GW: 15 224 | Rh: 9 225 | Rh_GW: 9 226 | Rh_pv: 15 227 | Rh_sv_GW: 17 228 | Rn: 8 229 | Rn_d_GW: 18 230 | Rn_sv_GW: 26 231 | Ru: 8 232 | Ru_pv: 14 233 | Ru_sv: 16 234 | Ru_sv_GW: 16 235 | S: 6 236 | S_GW: 6 237 | S_h: 6 238 | Sb: 5 239 | Sb_GW: 5 240 | Sb_d_GW: 15 241 | Sb_sv_GW: 23 242 | Sc: 3 243 | Sc_sv: 11 244 | Sc_sv_GW: 11 245 | Se: 6 246 | Se_GW: 6 247 | Se_sv_GW: 24 248 | Si: 4 249 | Si_GW: 4 250 | Si_sv_GW: 12 251 | Sn: 4 252 | Sn_d: 14 253 | Sn_d_GW: 14 254 | Sn_sv_GW: 22 255 | Sr_sv: 10 256 | Sr_sv_GW: 10 257 | Ta: 5 258 | Ta_pv: 11 259 | Ta_sv_GW: 13 260 | Tc: 7 261 | Tc_pv: 13 262 | Tc_sv: 15 263 | Tc_sv_GW: 15 264 | Te: 6 265 | Te_GW: 6 266 | Te_sv_GW: 24 267 | Th: 12 268 | Th_s: 10 269 | Ti: 4 270 | Ti_pv: 10 271 | Ti_sv: 12 272 | Ti_sv_GW: 12 273 | Tl: 3 274 | Tl_d: 13 275 | Tl_d_GW: 15 276 | Tl_sv_GW: 21 277 | U: 14 278 | U_s: 14 279 | V: 5 280 | V_pv: 11 281 | V_sv: 13 282 | V_sv_GW: 13 283 | W: 6 284 | W_sv: 14 285 | W_sv_GW: 14 286 | Xe: 8 287 | Xe_GW: 8 288 | Xe_sv_GW: 26 289 | Y_sv: 11 290 | Y_sv_GW: 11 291 | Zn: 12 292 | Zn_GW: 12 293 | Zn_sv_GW: 20 294 | Zr_sv: 12 295 | Zr_sv_GW: 12 296 | -------------------------------------------------------------------------------- /vasppy/data/LDA_54r_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ag: 11 3 | Ag_GW: 11 4 | Ag_pv: 17 5 | Ag_sv_GW: 19 6 | Al: 3 7 | Al_GW: 3 8 | Al_sv_GW: 11 9 | Am: 17 10 | Ar: 8 11 | Ar_GW: 8 12 | As: 5 13 | As_GW: 5 14 | As_d: 15 15 | As_sv_GW: 23 16 | At: 7 17 | At_d_GW: 17 18 | At_sv_GW: 25 19 | Au: 11 20 | Au_GW: 11 21 | Au_sv_GW: 19 22 | B: 3 23 | B_GW: 3 24 | B_h: 3 25 | B_s: 3 26 | Ba_sv: 10 27 | Ba_sv_GW: 10 28 | Be: 2 29 | Be_GW: 2 30 | Be_sv: 4 31 | Be_sv_GW: 4 32 | Bi: 5 33 | Bi_GW: 5 34 | Bi_d: 15 35 | Bi_d_GW: 17 36 | Bi_sv_GW: 23 37 | Br: 7 38 | Br_GW: 7 39 | Br_sv_GW: 25 40 | C: 4 41 | C_GW: 4 42 | C_GW_new: 4 43 | C_h: 4 44 | C_h_GW: 4 45 | C_s: 4 46 | Ca_pv: 8 47 | Ca_sv: 10 48 | Ca_sv_GW: 10 49 | Cd: 12 50 | Cd_GW: 12 51 | Cd_sv_GW: 20 52 | Ce: 12 53 | Ce_GW: 12 54 | Ce_h: 12 55 | Cl: 7 56 | Cl_GW: 7 57 | Cl_h: 7 58 | Cm: 18 59 | Co: 9 60 | Co_GW: 9 61 | Co_pv: 15 62 | Co_sv: 17 63 | Co_sv_GW: 17 64 | Cr: 6 65 | Cr_pv: 12 66 | Cr_sv: 14 67 | Cr_sv_GW: 14 68 | Cs_sv: 9 69 | Cs_sv_GW: 9 70 | Cu: 11 71 | Cu_GW: 11 72 | Cu_pv: 17 73 | Cu_sv_GW: 19 74 | F: 7 75 | F_GW: 7 76 | F_GW_new: 7 77 | F_h: 7 78 | F_h_GW: 7 79 | F_s: 7 80 | Fe: 8 81 | Fe_GW: 8 82 | Fe_pv: 14 83 | Fe_sv: 16 84 | Fe_sv_GW: 16 85 | Fr_sv: 9 86 | Ga: 3 87 | Ga_GW: 3 88 | Ga_d: 13 89 | Ga_d_GW: 13 90 | Ga_h: 13 91 | Ga_sv_GW: 21 92 | Ge: 4 93 | Ge_GW: 4 94 | Ge_d: 14 95 | Ge_d_GW: 14 96 | Ge_h: 14 97 | Ge_sv_GW: 22 98 | H: 1 99 | H.25: 0 100 | H.33: 0 101 | H.42: 0 102 | H.5: 0 103 | H.58: 0 104 | H.66: 0 105 | H.75: 0 106 | H1.25: 1 107 | H1.33: 1 108 | H1.5: 1 109 | H1.66: 1 110 | H1.75: 1 111 | H_AE: 1 112 | H_GW: 1 113 | H_h: 1 114 | H_h_GW: 1 115 | H_s: 1 116 | He: 2 117 | He_GW: 2 118 | Hf: 4 119 | Hf_pv: 10 120 | Hf_sv: 12 121 | Hf_sv_GW: 12 122 | Hg: 12 123 | Hg_sv_GW: 20 124 | I: 7 125 | I_GW: 7 126 | I_sv_GW: 25 127 | In: 3 128 | In_d: 13 129 | In_d_GW: 13 130 | In_sv_GW: 21 131 | Ir: 9 132 | Ir_sv_GW: 17 133 | K_pv: 7 134 | K_sv: 9 135 | K_sv_GW: 9 136 | Kr: 8 137 | Kr_GW: 8 138 | La: 11 139 | La_GW: 11 140 | La_s: 9 141 | Li: 1 142 | Li_AE_GW: 3 143 | Li_GW: 1 144 | Li_sv: 3 145 | Li_sv_GW: 3 146 | Mg: 2 147 | Mg_GW: 2 148 | Mg_pv: 8 149 | Mg_pv_GW: 8 150 | Mg_sv: 10 151 | Mg_sv_GW: 10 152 | Mn: 7 153 | Mn_GW: 7 154 | Mn_pv: 13 155 | Mn_sv: 15 156 | Mn_sv_GW: 15 157 | Mo: 6 158 | Mo_pv: 12 159 | Mo_sv: 14 160 | Mo_sv_GW: 14 161 | N: 5 162 | N_GW: 5 163 | N_GW_new: 5 164 | N_h: 5 165 | N_h_GW: 5 166 | N_s: 5 167 | N_s_GW: 5 168 | Na: 1 169 | Na_pv: 7 170 | Na_sv: 9 171 | Na_sv_GW: 9 172 | Nb_pv: 11 173 | Nb_sv: 13 174 | Nb_sv_GW: 13 175 | Ne: 8 176 | Ne_GW: 8 177 | Ne_s_GW: 8 178 | Ni: 10 179 | Ni_GW: 10 180 | Ni_pv: 16 181 | Ni_sv_GW: 18 182 | Np: 15 183 | Np_s: 15 184 | O: 6 185 | O_GW: 6 186 | O_GW_new: 6 187 | O_h: 6 188 | O_h_GW: 6 189 | O_s: 6 190 | O_s_GW: 6 191 | Os: 8 192 | Os_pv: 14 193 | Os_sv_GW: 16 194 | P: 5 195 | P_GW: 5 196 | P_h: 5 197 | Pa: 13 198 | Pa_s: 11 199 | Pb: 4 200 | Pb_d: 14 201 | Pb_d_GW: 16 202 | Pb_sv_GW: 22 203 | Pd: 10 204 | Pd_GW: 10 205 | Pd_pv: 16 206 | Pd_sv_GW: 18 207 | Po: 6 208 | Po_d: 16 209 | Po_d_GW: 18 210 | Po_sv_GW: 24 211 | Pt: 10 212 | Pt_GW: 10 213 | Pt_pv: 16 214 | Pt_sv_GW: 18 215 | Pu: 16 216 | Pu_s: 16 217 | Ra_sv: 10 218 | Rb_pv: 7 219 | Rb_sv: 9 220 | Rb_sv_GW: 9 221 | Re: 7 222 | Re_pv: 13 223 | Re_sv_GW: 15 224 | Rh: 9 225 | Rh_GW: 9 226 | Rh_pv: 15 227 | Rh_sv_GW: 17 228 | Rn: 8 229 | Rn_d_GW: 18 230 | Rn_sv_GW: 26 231 | Ru: 8 232 | Ru_pv: 14 233 | Ru_sv: 16 234 | Ru_sv_GW: 16 235 | S: 6 236 | S_GW: 6 237 | S_h: 6 238 | Sb: 5 239 | Sb_GW: 5 240 | Sb_d_GW: 15 241 | Sb_sv_GW: 23 242 | Sc: 3 243 | Sc_sv: 11 244 | Sc_sv_GW: 11 245 | Se: 6 246 | Se_GW: 6 247 | Se_sv_GW: 24 248 | Si: 4 249 | Si_GW: 4 250 | Si_sv_GW: 12 251 | Sn: 4 252 | Sn_d: 14 253 | Sn_d_GW: 14 254 | Sn_sv_GW: 22 255 | Sr_sv: 10 256 | Sr_sv_GW: 10 257 | Ta: 5 258 | Ta_pv: 11 259 | Ta_sv_GW: 13 260 | Tc: 7 261 | Tc_pv: 13 262 | Tc_sv: 15 263 | Tc_sv_GW: 15 264 | Te: 6 265 | Te_GW: 6 266 | Te_sv_GW: 24 267 | Th: 12 268 | Th_s: 10 269 | Ti: 4 270 | Ti_pv: 10 271 | Ti_sv: 12 272 | Ti_sv_GW: 12 273 | Tl: 3 274 | Tl_d: 13 275 | Tl_d_GW: 15 276 | Tl_sv_GW: 21 277 | U: 14 278 | U_s: 14 279 | V: 5 280 | V_pv: 11 281 | V_sv: 13 282 | V_sv_GW: 13 283 | W: 6 284 | W_sv: 14 285 | W_sv_GW: 14 286 | Xe: 8 287 | Xe_GW: 8 288 | Xe_sv_GW: 26 289 | Y_sv: 11 290 | Y_sv_GW: 11 291 | Zn: 12 292 | Zn_GW: 12 293 | Zn_sv_GW: 20 294 | Zr_sv: 12 295 | Zr_sv_GW: 12 296 | -------------------------------------------------------------------------------- /vasppy/data/LDA_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ac_s: 9 3 | Ag: 11 4 | Ag_GW: 11 5 | Ag_f_GW: 11 6 | Ag_new: 11 7 | Al: 3 8 | Al_d_GW: 3 9 | Al_pv: 9 10 | Al_s: 3 11 | Al_sv_GW: 11 12 | Ar: 8 13 | Ar_GW: 8 14 | As: 5 15 | As_GW: 5 16 | As_GW_n: 5 17 | As_NC2: 5 18 | As_d: 15 19 | As_d2_GW: 15 20 | As_d_GW: 15 21 | At: 7 22 | At_d: 17 23 | Au: 11 24 | Au_new: 11 25 | B: 3 26 | B_GW: 3 27 | B_h: 3 28 | B_s: 3 29 | Ba_sv: 10 30 | Be: 2 31 | Be_AE_GW: 4 32 | Be_GW: 2 33 | Be_sv: 4 34 | Bi: 5 35 | Bi_d: 15 36 | Bi_d_GW: 15 37 | Bi_pv: 21 38 | Br: 7 39 | C: 4 40 | C_GW: 4 41 | C_d: 4 42 | C_f_AE: 6 43 | C_f_GW: 4 44 | C_h: 4 45 | C_h_GW: 4 46 | C_local: 4 47 | C_nc_GW: 4 48 | C_s: 4 49 | Ca_pv: 8 50 | Ca_sv: 10 51 | Cd: 12 52 | Cd_GW: 12 53 | Cd_GW.old: 12 54 | Cd_f_GW: 12 55 | Cd_pv_GW: 18 56 | Cd_sv_GW: 20 57 | Ce: 12 58 | Ce_h: 12 59 | Ce_s: 10 60 | Cl: 7 61 | Cl_d_GW: 7 62 | Cl_h: 7 63 | Cl_h_new: 7 64 | Co: 9 65 | Co_GW: 9 66 | Co_pv: 15 67 | Co_pv_GW: 15 68 | Co_sv_GW: 17 69 | Cr: 6 70 | Cr_pv: 12 71 | Cs_sv: 9 72 | Cu: 11 73 | Cu_GW: 11 74 | Cu_GW_h: 11 75 | Cu_new: 11 76 | Cu_pv: 17 77 | Cu_pv_GW: 17 78 | F: 7 79 | F_GW: 7 80 | F_d_GW: 7 81 | F_h: 7 82 | F_h_GW: 7 83 | F_s: 7 84 | Fe: 8 85 | Fe_GW: 8 86 | Fe_pv: 14 87 | Fe_pv_GW: 14 88 | Fe_sv: 16 89 | Fe_sv_GW: 16 90 | Fe_sv_GW_f: 16 91 | Fr_sv: 9 92 | Free: 0 93 | Ga: 3 94 | Ga_GW: 3 95 | Ga_NC2: 3 96 | Ga_d: 13 97 | Ga_d_GW: 13 98 | Ga_d_GW.old: 13 99 | Ga_h: 13 100 | Ga_pv_GW: 19 101 | Ga_pv_GW.nrel: 19 102 | Ga_pv_GW.old: 19 103 | Ga_s: 3 104 | Ga_sv_GW: 21 105 | Ga_sv_GW.old: 21 106 | Ga_sv_GW2: 21 107 | Ge: 4 108 | Ge_GW: 4 109 | Ge_d: 14 110 | Ge_d_GW: 14 111 | Ge_h: 14 112 | H: 1 113 | H.25: 0 114 | H.33: 0 115 | H.5: 0 116 | H.66: 0 117 | H.75: 0 118 | H1.25: 1 119 | H1.33: 1 120 | H1.5: 1 121 | H1.66: 1 122 | H1.75: 1 123 | H_AE: 1 124 | H_GW: 1 125 | H_h: 1 126 | H_h_GW: 1 127 | H_nc_GW: 1 128 | He: 2 129 | He_GW: 2 130 | Hf: 4 131 | Hf_pv: 10 132 | Hf_sv: 12 133 | Hf_sv_GW: 12 134 | Hg: 12 135 | I: 7 136 | In: 3 137 | In_d: 13 138 | In_d_GW: 13 139 | In_pv: 19 140 | Ir: 9 141 | K: 7 142 | K_pv: 7 143 | K_sv: 9 144 | Kr: 8 145 | Kr_GW: 8 146 | La: 11 147 | La_s: 9 148 | Li: 1 149 | Li_AE_GW: 3 150 | Li_AE_GW2: 3 151 | Li_GW: 1 152 | Li_sv: 3 153 | Li_sv_GW: 3 154 | Li_sv_GW_: 3 155 | Li_sv_old: 3 156 | Mg: 2 157 | Mg_GW: 2 158 | Mg_pv: 8 159 | Mg_pv.old: 8 160 | Mg_pv_GW: 8 161 | Mg_pv_parsv_GW: 8 162 | Mg_sv: 10 163 | Mg_sv_GW: 10 164 | Mn: 7 165 | Mn_GW: 7 166 | Mn_pv: 13 167 | Mn_pv_GW: 13 168 | Mn_sv_GW: 15 169 | Mo: 6 170 | Mo_pv: 12 171 | Mo_pv_new: 12 172 | Mo_sv: 14 173 | N: 5 174 | N_GW: 5 175 | N_h: 5 176 | N_s: 5 177 | N_s_GW: 5 178 | Na: 1 179 | Na_GW: 1 180 | Na_pv: 7 181 | Na_pv_GW: 7 182 | Na_sv: 9 183 | Na_sv_GW: 9 184 | Nb_pv: 11 185 | Nb_sv: 13 186 | Ne: 8 187 | Ne_AE: 10 188 | Ne_GW: 8 189 | Ne_GW2: 8 190 | Ni: 10 191 | Ni_GW: 10 192 | Ni_h: 10 193 | Ni_pv: 16 194 | Ni_pv_GW: 16 195 | Ni_sv_GW: 18 196 | Np: 15 197 | Np_s: 15 198 | O: 6 199 | O_GW: 6 200 | O_h: 6 201 | O_h_GW: 6 202 | O_s: 6 203 | O_s_GW: 6 204 | Os: 8 205 | Os_pv: 14 206 | P: 5 207 | P_d_GW: 5 208 | P_h: 5 209 | Pa: 13 210 | Pa_s: 11 211 | Pb: 4 212 | Pb_d: 14 213 | Pb_d_GW: 14 214 | Pb_dr: 4 215 | Pd: 10 216 | Pd_GW: 10 217 | Pd_f_GW: 10 218 | Pd_new: 10 219 | Pd_pv: 16 220 | Pd_pv_new: 16 221 | Po: 6 222 | Po_d: 16 223 | Pt: 10 224 | Pt_f_GW: 10 225 | Pt_new: 10 226 | Pu: 16 227 | Pu_s: 16 228 | Ra_sv: 10 229 | Rb_pv: 7 230 | Rb_sv: 9 231 | Re: 7 232 | Re_pv: 13 233 | Rh: 9 234 | Rh_GW: 9 235 | Rh_f_GW: 9 236 | Rh_new: 9 237 | Rh_pv: 15 238 | Rh_pv_GW: 15 239 | Rh_pv_new: 15 240 | Rn: 8 241 | Ru: 8 242 | Ru_GW: 8 243 | Ru_f_GW: 8 244 | Ru_new: 8 245 | Ru_pv: 14 246 | Ru_pv_GW: 14 247 | Ru_pv_new: 14 248 | S: 6 249 | S_d_GW: 6 250 | S_h: 6 251 | Sb: 5 252 | Sb_: 5 253 | Sb_GW: 5 254 | Sb_d_GW: 15 255 | Sc: 3 256 | Sc_sv: 11 257 | Se: 6 258 | Se_GW: 6 259 | Si: 4 260 | Si_d_GW: 4 261 | Si_d_GW_nr: 4 262 | Si_f_GW: 4 263 | Si_h: 4 264 | Si_nopc: 4 265 | Si_sv_GW: 12 266 | Si_sv_GW_: 12 267 | Si_sv_GW__: 12 268 | Si_sv_GW_nr: 12 269 | Sn: 4 270 | Sn_GW: 4 271 | Sn_d: 14 272 | Sr_sv: 10 273 | Ta: 5 274 | Ta_pv: 11 275 | Tc: 7 276 | Tc_new: 7 277 | Tc_pv: 13 278 | Tc_pv_new: 13 279 | Te: 6 280 | Te_GW: 6 281 | Te_rel: 6 282 | Th: 12 283 | Th_s: 10 284 | Ti: 4 285 | Ti_pv: 10 286 | Ti_s: 2 287 | Ti_sv: 12 288 | Ti_sv_GW: 12 289 | Ti_sv_new: 12 290 | Tl: 3 291 | Tl_d: 13 292 | U: 14 293 | U_s: 14 294 | V: 5 295 | V_pv: 11 296 | V_sv: 13 297 | W: 6 298 | W_pv: 12 299 | Xe: 8 300 | Xe_GW: 8 301 | Y_sv: 11 302 | Zn: 12 303 | Zn_GW: 12 304 | Zn_GW.old: 12 305 | Zn_GW2: 12 306 | Zn_pv: 18 307 | Zn_pv_GW: 18 308 | Zn_pv_GW.old: 18 309 | Zn_sv_GW: 20 310 | Zn_sv_GW.old: 20 311 | Zn_sv_GW_: 20 312 | Zn_sv_LDApU: 20 313 | Zr: 4 314 | Zr_sv: 12 315 | Zr_sv_GW: 12 316 | Zr_sv_new: 12 317 | -------------------------------------------------------------------------------- /vasppy/data/PBE_52_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ag: 11 3 | Ag_GW: 11 4 | Ag_pv: 17 5 | Al: 3 6 | Al_GW: 3 7 | Al_sv_GW: 11 8 | Am: 17 9 | Ar: 8 10 | Ar_GW: 8 11 | As: 5 12 | As_GW: 5 13 | As_d: 15 14 | At: 7 15 | At_d: 17 16 | Au: 11 17 | Au_GW: 11 18 | Au_pv_GW: 17 19 | B: 3 20 | B_GW: 3 21 | B_h: 3 22 | B_s: 3 23 | Ba_sv: 10 24 | Ba_sv_GW: 10 25 | Be: 2 26 | Be_GW: 2 27 | Be_sv: 4 28 | Be_sv_GW: 4 29 | Bi: 5 30 | Bi_GW: 5 31 | Bi_d: 15 32 | Bi_d_GW: 15 33 | Br: 7 34 | Br_GW: 7 35 | C: 4 36 | C_GW: 4 37 | C_GW_new: 4 38 | C_h: 4 39 | C_s: 4 40 | Ca_pv: 8 41 | Ca_sv: 10 42 | Ca_sv_GW: 10 43 | Cd: 12 44 | Cd_GW: 12 45 | Cd_pv_GW: 18 46 | Cd_sv_GW: 20 47 | Ce: 12 48 | Ce_3: 11 49 | Ce_GW: 12 50 | Ce_h: 12 51 | Cl: 7 52 | Cl_GW: 7 53 | Cl_h: 7 54 | Cm: 18 55 | Co: 9 56 | Co_GW: 9 57 | Co_pv: 15 58 | Co_sv: 17 59 | Co_sv_GW: 17 60 | Cr: 6 61 | Cr_pv: 12 62 | Cr_sv: 14 63 | Cr_sv_GW: 14 64 | Cs_sv: 9 65 | Cs_sv_GW: 9 66 | Cu: 11 67 | Cu_GW: 11 68 | Cu_pv: 17 69 | Cu_pv_GW: 17 70 | Dy: 20 71 | Dy_3: 9 72 | Er: 22 73 | Er_2: 8 74 | Er_3: 9 75 | Eu: 17 76 | Eu_2: 8 77 | Eu_3: 9 78 | F: 7 79 | F_GW: 7 80 | F_GW_new: 7 81 | F_h: 7 82 | F_s: 7 83 | Fe: 8 84 | Fe_GW: 8 85 | Fe_pv: 14 86 | Fe_sv: 16 87 | Fe_sv_GW: 16 88 | Fr_sv: 9 89 | Ga: 3 90 | Ga_GW: 3 91 | Ga_d: 13 92 | Ga_d_GW: 13 93 | Ga_h: 13 94 | Ga_pv_GW: 19 95 | Ga_sv_GW: 21 96 | Gd: 18 97 | Gd_3: 9 98 | Ge: 4 99 | Ge_GW: 4 100 | Ge_d: 14 101 | Ge_d_GW: 14 102 | Ge_h: 14 103 | Ge_sv_GW: 22 104 | H: 1 105 | H.25: 0 106 | H.33: 0 107 | H.42: 0 108 | H.5: 0 109 | H.58: 0 110 | H.66: 0 111 | H.75: 0 112 | H1.25: 1 113 | H1.33: 1 114 | H1.5: 1 115 | H1.66: 1 116 | H1.75: 1 117 | H_AE: 1 118 | H_GW: 1 119 | H_h: 1 120 | H_h_GW: 1 121 | H_s: 1 122 | He: 2 123 | He_GW: 2 124 | Hf: 4 125 | Hf_pv: 10 126 | Hf_sv: 12 127 | Hf_sv_GW: 12 128 | Hg: 12 129 | Ho: 21 130 | Ho_3: 9 131 | I: 7 132 | I_GW: 7 133 | In: 3 134 | In_d: 13 135 | In_d_GW: 13 136 | Ir: 9 137 | Ir_sv_GW: 17 138 | K_pv: 7 139 | K_sv: 9 140 | K_sv_GW: 9 141 | Kr: 8 142 | Kr_GW: 8 143 | La: 11 144 | La_s: 9 145 | Li: 1 146 | Li_AE_GW: 3 147 | Li_GW: 1 148 | Li_sv: 3 149 | Li_sv_GW: 3 150 | Lu: 25 151 | Lu_3: 9 152 | Mg: 2 153 | Mg_GW: 2 154 | Mg_pv: 8 155 | Mg_pv_GW: 8 156 | Mg_sv: 10 157 | Mg_sv_GW: 10 158 | Mn: 7 159 | Mn_GW: 7 160 | Mn_pv: 13 161 | Mn_sv: 15 162 | Mn_sv_GW: 15 163 | Mo: 6 164 | Mo_pv: 12 165 | Mo_sv: 14 166 | Mo_sv_GW: 14 167 | N: 5 168 | N_GW: 5 169 | N_GW_new: 5 170 | N_h: 5 171 | N_s: 5 172 | N_s_GW: 5 173 | Na: 1 174 | Na_pv: 7 175 | Na_sv: 9 176 | Na_sv_GW: 9 177 | Nb_pv: 11 178 | Nb_sv: 13 179 | Nb_sv_GW: 13 180 | Nd: 14 181 | Nd_3: 11 182 | Ne: 8 183 | Ne_GW: 8 184 | Ne_GW_soft: 8 185 | Ni: 10 186 | Ni_GW: 10 187 | Ni_pv: 16 188 | Ni_sv_GW: 18 189 | Np: 15 190 | Np_s: 15 191 | O: 6 192 | O_GW: 6 193 | O_GW_new: 6 194 | O_h: 6 195 | O_s: 6 196 | O_s_GW: 6 197 | Os: 8 198 | Os_pv: 14 199 | Os_sv_GW: 16 200 | P: 5 201 | P_GW: 5 202 | P_h: 5 203 | Pa: 13 204 | Pa_s: 11 205 | Pb: 4 206 | Pb_d: 14 207 | Pb_d_GW: 14 208 | Pd: 10 209 | Pd_GW: 10 210 | Pd_pv: 16 211 | Pm: 15 212 | Pm_3: 11 213 | Po: 6 214 | Po_d: 16 215 | Pr: 13 216 | Pr_3: 11 217 | Pt: 10 218 | Pt_GW: 10 219 | Pt_pv: 16 220 | Pt_pv_GW: 16 221 | Pt_sv_GW: 18 222 | Pu: 16 223 | Pu_s: 16 224 | Ra_sv: 10 225 | Rb_pv: 7 226 | Rb_sv: 9 227 | Rb_sv_GW: 9 228 | Re: 7 229 | Re_pv: 13 230 | Re_sv_GW: 15 231 | Rh: 9 232 | Rh_GW: 9 233 | Rh_pv: 15 234 | Rh_pv_GW: 15 235 | Rh_sv_GW: 17 236 | Rn: 8 237 | Ru: 8 238 | Ru_pv: 14 239 | Ru_pv_GW: 14 240 | Ru_sv: 16 241 | Ru_sv_GW: 16 242 | S: 6 243 | S_GW: 6 244 | S_h: 6 245 | Sb: 5 246 | Sb_GW: 5 247 | Sb_d_GW: 15 248 | Sc: 3 249 | Sc_sv: 11 250 | Sc_sv_GW: 11 251 | Se: 6 252 | Se_GW: 6 253 | Si: 4 254 | Si_GW: 4 255 | Si_sv_GW: 12 256 | Sm: 16 257 | Sm_3: 11 258 | Sn: 4 259 | Sn_d: 14 260 | Sn_d_GW: 14 261 | Sr_sv: 10 262 | Sr_sv_GW: 10 263 | Ta: 5 264 | Ta_pv: 11 265 | Ta_sv_GW: 13 266 | Tb: 19 267 | Tb_3: 9 268 | Tc: 7 269 | Tc_pv: 13 270 | Tc_sv: 15 271 | Tc_sv_GW: 15 272 | Te: 6 273 | Te_GW: 6 274 | Th: 12 275 | Th_s: 10 276 | Ti: 4 277 | Ti_pv: 10 278 | Ti_sv: 12 279 | Ti_sv_GW: 12 280 | Tl: 3 281 | Tl_d: 13 282 | Tm: 23 283 | Tm_3: 9 284 | U: 14 285 | U_s: 14 286 | V: 5 287 | V_pv: 11 288 | V_sv: 13 289 | V_sv_GW: 13 290 | W: 6 291 | W_pv: 12 292 | W_sv_GW: 14 293 | Xe: 8 294 | Xe_GW: 8 295 | Y_sv: 11 296 | Y_sv_GW: 11 297 | Yb: 24 298 | Yb_2: 8 299 | Zn: 12 300 | Zn_GW: 12 301 | Zn_pv_GW: 18 302 | Zn_sv_GW: 20 303 | Zr_sv: 12 304 | Zr_sv_GW: 12 305 | -------------------------------------------------------------------------------- /vasppy/data/PBE_54_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ag: 11 3 | Ag_GW: 11 4 | Ag_pv: 17 5 | Ag_sv_GW: 19 6 | Al: 3 7 | Al_GW: 3 8 | Al_sv_GW: 11 9 | Am: 17 10 | Ar: 8 11 | Ar_GW: 8 12 | As: 5 13 | As_GW: 5 14 | As_d: 15 15 | As_sv_GW: 23 16 | At: 7 17 | At_d_GW: 17 18 | At_sv_GW: 25 19 | Au: 11 20 | Au_GW: 11 21 | Au_sv_GW: 19 22 | B: 3 23 | B_GW: 3 24 | B_h: 3 25 | B_s: 3 26 | Ba_sv: 10 27 | Ba_sv_GW: 10 28 | Be: 2 29 | Be_GW: 2 30 | Be_sv: 4 31 | Be_sv_GW: 4 32 | Bi: 5 33 | Bi_GW: 5 34 | Bi_d: 15 35 | Bi_d_GW: 17 36 | Bi_sv_GW: 23 37 | Br: 7 38 | Br_GW: 7 39 | Br_sv_GW: 25 40 | C: 4 41 | C_GW: 4 42 | C_GW_new: 4 43 | C_h: 4 44 | C_h_GW: 4 45 | C_s: 4 46 | Ca_pv: 8 47 | Ca_sv: 10 48 | Ca_sv_GW: 10 49 | Cd: 12 50 | Cd_GW: 12 51 | Cd_sv_GW: 20 52 | Ce: 12 53 | Ce_3: 11 54 | Ce_GW: 12 55 | Ce_h: 12 56 | Cf: 20 57 | Cl: 7 58 | Cl_GW: 7 59 | Cl_h: 7 60 | Cm: 18 61 | Co: 9 62 | Co_GW: 9 63 | Co_pv: 15 64 | Co_sv: 17 65 | Co_sv_GW: 17 66 | Cr: 6 67 | Cr_pv: 12 68 | Cr_sv: 14 69 | Cr_sv_GW: 14 70 | Cs_sv: 9 71 | Cs_sv_GW: 9 72 | Cu: 11 73 | Cu_GW: 11 74 | Cu_pv: 17 75 | Cu_sv_GW: 19 76 | Dy: 20 77 | Dy_3: 9 78 | Er: 22 79 | Er_2: 8 80 | Er_3: 9 81 | Eu: 17 82 | Eu_2: 8 83 | Eu_3: 9 84 | F: 7 85 | F_GW: 7 86 | F_GW_new: 7 87 | F_h: 7 88 | F_h_GW: 7 89 | F_s: 7 90 | Fe: 8 91 | Fe_GW: 8 92 | Fe_pv: 14 93 | Fe_sv: 16 94 | Fe_sv_GW: 16 95 | Fr_sv: 9 96 | Ga: 3 97 | Ga_GW: 3 98 | Ga_d: 13 99 | Ga_d_GW: 13 100 | Ga_h: 13 101 | Ga_sv_GW: 21 102 | Gd: 18 103 | Gd_3: 9 104 | Ge: 4 105 | Ge_GW: 4 106 | Ge_d: 14 107 | Ge_d_GW: 14 108 | Ge_h: 14 109 | Ge_sv_GW: 22 110 | H: 1 111 | H.25: 0 112 | H.33: 0 113 | H.42: 0 114 | H.5: 0 115 | H.58: 0 116 | H.66: 0 117 | H.75: 0 118 | H1.25: 1 119 | H1.33: 1 120 | H1.5: 1 121 | H1.66: 1 122 | H1.75: 1 123 | H_AE: 1 124 | H_GW: 1 125 | H_h: 1 126 | H_h_GW: 1 127 | H_s: 1 128 | He: 2 129 | He_AE: 2 130 | He_GW: 2 131 | Hf: 4 132 | Hf_pv: 10 133 | Hf_sv: 12 134 | Hf_sv_GW: 12 135 | Hg: 12 136 | Hg_sv_GW: 20 137 | Ho: 21 138 | Ho_3: 9 139 | I: 7 140 | I_GW: 7 141 | I_sv_GW: 25 142 | In: 3 143 | In_d: 13 144 | In_d_GW: 13 145 | In_sv_GW: 21 146 | Ir: 9 147 | Ir_sv_GW: 17 148 | K_pv: 7 149 | K_sv: 9 150 | K_sv_GW: 9 151 | Kr: 8 152 | Kr_GW: 8 153 | La: 11 154 | La_GW: 11 155 | La_s: 9 156 | Li: 1 157 | Li_AE_GW: 3 158 | Li_GW: 1 159 | Li_sv: 3 160 | Li_sv_GW: 3 161 | Lu: 25 162 | Lu_3: 9 163 | Mg: 2 164 | Mg_GW: 2 165 | Mg_pv: 8 166 | Mg_pv_GW: 8 167 | Mg_sv: 10 168 | Mg_sv_GW: 10 169 | Mn: 7 170 | Mn_GW: 7 171 | Mn_pv: 13 172 | Mn_sv: 15 173 | Mn_sv_GW: 15 174 | Mo: 6 175 | Mo_pv: 12 176 | Mo_sv: 14 177 | Mo_sv_GW: 14 178 | N: 5 179 | N_GW: 5 180 | N_GW_new: 5 181 | N_h: 5 182 | N_h_GW: 5 183 | N_s: 5 184 | N_s_GW: 5 185 | Na: 1 186 | Na_pv: 7 187 | Na_sv: 9 188 | Na_sv_GW: 9 189 | Nb_pv: 11 190 | Nb_sv: 13 191 | Nb_sv_GW: 13 192 | Nd: 14 193 | Nd_3: 11 194 | Ne: 8 195 | Ne_GW: 8 196 | Ne_s_GW: 8 197 | Ni: 10 198 | Ni_GW: 10 199 | Ni_pv: 16 200 | Ni_sv_GW: 18 201 | Np: 15 202 | Np_s: 15 203 | O: 6 204 | O_GW: 6 205 | O_GW_new: 6 206 | O_h: 6 207 | O_h_GW: 6 208 | O_s: 6 209 | O_s_GW: 6 210 | Os: 8 211 | Os_pv: 14 212 | Os_sv_GW: 16 213 | P: 5 214 | P_GW: 5 215 | P_h: 5 216 | Pa: 13 217 | Pa_s: 11 218 | Pb: 4 219 | Pb_d: 14 220 | Pb_d_GW: 16 221 | Pb_sv_GW: 22 222 | Pd: 10 223 | Pd_GW: 10 224 | Pd_pv: 16 225 | Pd_sv_GW: 18 226 | Pm: 15 227 | Pm_3: 11 228 | Po: 6 229 | Po_d: 16 230 | Po_d_GW: 18 231 | Po_sv_GW: 24 232 | Pr: 13 233 | Pr_3: 11 234 | Pt: 10 235 | Pt_GW: 10 236 | Pt_pv: 16 237 | Pt_sv_GW: 18 238 | Pu: 16 239 | Pu_s: 16 240 | Ra_sv: 10 241 | Rb_pv: 7 242 | Rb_sv: 9 243 | Rb_sv_GW: 9 244 | Re: 7 245 | Re_pv: 13 246 | Re_sv_GW: 15 247 | Rh: 9 248 | Rh_GW: 9 249 | Rh_pv: 15 250 | Rh_sv_GW: 17 251 | Rn: 8 252 | Rn_d_GW: 18 253 | Rn_sv_GW: 26 254 | Ru: 8 255 | Ru_pv: 14 256 | Ru_sv: 16 257 | Ru_sv_GW: 16 258 | S: 6 259 | S_GW: 6 260 | S_h: 6 261 | Sb: 5 262 | Sb_GW: 5 263 | Sb_d_GW: 15 264 | Sb_sv_GW: 23 265 | Sc: 3 266 | Sc_sv: 11 267 | Sc_sv_GW: 11 268 | Se: 6 269 | Se_GW: 6 270 | Se_sv_GW: 24 271 | Si: 4 272 | Si_GW: 4 273 | Si_sv_GW: 12 274 | Sm: 16 275 | Sm_3: 11 276 | Sn: 4 277 | Sn_d: 14 278 | Sn_d_GW: 14 279 | Sn_sv_GW: 22 280 | Sr_sv: 10 281 | Sr_sv_GW: 10 282 | Ta: 5 283 | Ta_pv: 11 284 | Ta_sv_GW: 13 285 | Tb: 19 286 | Tb_3: 9 287 | Tc: 7 288 | Tc_pv: 13 289 | Tc_sv: 15 290 | Tc_sv_GW: 15 291 | Te: 6 292 | Te_GW: 6 293 | Te_sv_GW: 24 294 | Th: 12 295 | Th_s: 10 296 | Ti: 4 297 | Ti_pv: 10 298 | Ti_sv: 12 299 | Ti_sv_GW: 12 300 | Tl: 3 301 | Tl_d: 13 302 | Tl_d_GW: 15 303 | Tl_sv_GW: 21 304 | Tm: 23 305 | Tm_3: 9 306 | U: 14 307 | U_s: 14 308 | V: 5 309 | V_pv: 11 310 | V_sv: 13 311 | V_sv_GW: 13 312 | W: 6 313 | W_sv: 14 314 | W_sv_GW: 14 315 | Xe: 8 316 | Xe_GW: 8 317 | Xe_sv_GW: 26 318 | Y_sv: 11 319 | Y_sv_GW: 11 320 | Yb: 24 321 | Yb_2: 8 322 | Yb_3: 9 323 | Zn: 12 324 | Zn_GW: 12 325 | Zn_sv_GW: 20 326 | Zr_sv: 12 327 | Zr_sv_GW: 12 328 | -------------------------------------------------------------------------------- /vasppy/data/PBE_54r_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ag: 11 3 | Ag_GW: 11 4 | Ag_pv: 17 5 | Ag_sv_GW: 19 6 | Al: 3 7 | Al_GW: 3 8 | Al_sv_GW: 11 9 | Am: 17 10 | Ar: 8 11 | Ar_GW: 8 12 | As: 5 13 | As_GW: 5 14 | As_d: 15 15 | As_sv_GW: 23 16 | At: 7 17 | At_d_GW: 17 18 | At_sv_GW: 25 19 | Au: 11 20 | Au_GW: 11 21 | Au_sv_GW: 19 22 | B: 3 23 | B_GW: 3 24 | B_h: 3 25 | B_s: 3 26 | Ba_sv: 10 27 | Ba_sv_GW: 10 28 | Be: 2 29 | Be_GW: 2 30 | Be_sv: 4 31 | Be_sv_GW: 4 32 | Bi: 5 33 | Bi_GW: 5 34 | Bi_d: 15 35 | Bi_d_GW: 17 36 | Bi_sv_GW: 23 37 | Br: 7 38 | Br_GW: 7 39 | Br_sv_GW: 25 40 | C: 4 41 | C_GW: 4 42 | C_GW_new: 4 43 | C_h: 4 44 | C_h_GW: 4 45 | C_s: 4 46 | Ca_pv: 8 47 | Ca_sv: 10 48 | Ca_sv_GW: 10 49 | Cd: 12 50 | Cd_GW: 12 51 | Cd_sv_GW: 20 52 | Ce: 12 53 | Ce_3: 11 54 | Ce_GW: 12 55 | Ce_h: 12 56 | Cf: 20 57 | Cl: 7 58 | Cl_GW: 7 59 | Cl_h: 7 60 | Cm: 18 61 | Co: 9 62 | Co_GW: 9 63 | Co_pv: 15 64 | Co_sv: 17 65 | Co_sv_GW: 17 66 | Cr: 6 67 | Cr_pv: 12 68 | Cr_sv: 14 69 | Cr_sv_GW: 14 70 | Cs_sv: 9 71 | Cs_sv_GW: 9 72 | Cu: 11 73 | Cu_GW: 11 74 | Cu_pv: 17 75 | Cu_sv_GW: 19 76 | Dy: 20 77 | Dy_3: 9 78 | Er: 22 79 | Er_2: 8 80 | Er_3: 9 81 | Eu: 17 82 | Eu_2: 8 83 | Eu_3: 9 84 | F: 7 85 | F_GW: 7 86 | F_GW_new: 7 87 | F_h: 7 88 | F_h_GW: 7 89 | F_s: 7 90 | Fe: 8 91 | Fe_GW: 8 92 | Fe_pv: 14 93 | Fe_sv: 16 94 | Fe_sv_GW: 16 95 | Fr_sv: 9 96 | Ga: 3 97 | Ga_GW: 3 98 | Ga_d: 13 99 | Ga_d_GW: 13 100 | Ga_h: 13 101 | Ga_sv_GW: 21 102 | Gd: 18 103 | Gd_3: 9 104 | Ge: 4 105 | Ge_GW: 4 106 | Ge_d: 14 107 | Ge_d_GW: 14 108 | Ge_h: 14 109 | Ge_sv_GW: 22 110 | H: 1 111 | H.25: 0 112 | H.33: 0 113 | H.42: 0 114 | H.5: 0 115 | H.58: 0 116 | H.66: 0 117 | H.75: 0 118 | H1.25: 1 119 | H1.33: 1 120 | H1.5: 1 121 | H1.66: 1 122 | H1.75: 1 123 | H_AE: 1 124 | H_GW: 1 125 | H_h: 1 126 | H_h_GW: 1 127 | H_s: 1 128 | He: 2 129 | He_AE: 2 130 | He_GW: 2 131 | Hf: 4 132 | Hf_pv: 10 133 | Hf_sv: 12 134 | Hf_sv_GW: 12 135 | Hg: 12 136 | Hg_sv_GW: 20 137 | Ho: 21 138 | Ho_3: 9 139 | I: 7 140 | I_GW: 7 141 | I_sv_GW: 25 142 | In: 3 143 | In_d: 13 144 | In_d_GW: 13 145 | In_sv_GW: 21 146 | Ir: 9 147 | Ir_sv_GW: 17 148 | K_pv: 7 149 | K_sv: 9 150 | K_sv_GW: 9 151 | Kr: 8 152 | Kr_GW: 8 153 | La: 11 154 | La_GW: 11 155 | La_s: 9 156 | Li: 1 157 | Li_AE_GW: 3 158 | Li_GW: 1 159 | Li_sv: 3 160 | Li_sv_GW: 3 161 | Lu: 25 162 | Lu_3: 9 163 | Mg: 2 164 | Mg_GW: 2 165 | Mg_pv: 8 166 | Mg_pv_GW: 8 167 | Mg_sv: 10 168 | Mg_sv_GW: 10 169 | Mn: 7 170 | Mn_GW: 7 171 | Mn_pv: 13 172 | Mn_sv: 15 173 | Mn_sv_GW: 15 174 | Mo: 6 175 | Mo_pv: 12 176 | Mo_sv: 14 177 | Mo_sv_GW: 14 178 | N: 5 179 | N_GW: 5 180 | N_GW_new: 5 181 | N_h: 5 182 | N_h_GW: 5 183 | N_s: 5 184 | N_s_GW: 5 185 | Na: 1 186 | Na_pv: 7 187 | Na_sv: 9 188 | Na_sv_GW: 9 189 | Nb_pv: 11 190 | Nb_sv: 13 191 | Nb_sv_GW: 13 192 | Nd: 14 193 | Nd_3: 11 194 | Ne: 8 195 | Ne_GW: 8 196 | Ne_s_GW: 8 197 | Ni: 10 198 | Ni_GW: 10 199 | Ni_pv: 16 200 | Ni_sv_GW: 18 201 | Np: 15 202 | Np_s: 15 203 | O: 6 204 | O_GW: 6 205 | O_GW_new: 6 206 | O_h: 6 207 | O_h_GW: 6 208 | O_s: 6 209 | O_s_GW: 6 210 | Os: 8 211 | Os_pv: 14 212 | Os_sv_GW: 16 213 | P: 5 214 | P_GW: 5 215 | P_h: 5 216 | Pa: 13 217 | Pa_s: 11 218 | Pb: 4 219 | Pb_d: 14 220 | Pb_d_GW: 16 221 | Pb_sv_GW: 22 222 | Pd: 10 223 | Pd_GW: 10 224 | Pd_pv: 16 225 | Pd_sv_GW: 18 226 | Pm: 15 227 | Pm_3: 11 228 | Po: 6 229 | Po_d: 16 230 | Po_d_GW: 18 231 | Po_sv_GW: 24 232 | Pr: 13 233 | Pr_3: 11 234 | Pt: 10 235 | Pt_GW: 10 236 | Pt_pv: 16 237 | Pt_sv_GW: 18 238 | Pu: 16 239 | Pu_s: 16 240 | Ra_sv: 10 241 | Rb_pv: 7 242 | Rb_sv: 9 243 | Rb_sv_GW: 9 244 | Re: 7 245 | Re_pv: 13 246 | Re_sv_GW: 15 247 | Rh: 9 248 | Rh_GW: 9 249 | Rh_pv: 15 250 | Rh_sv_GW: 17 251 | Rn: 8 252 | Rn_d_GW: 18 253 | Rn_sv_GW: 26 254 | Ru: 8 255 | Ru_pv: 14 256 | Ru_sv: 16 257 | Ru_sv_GW: 16 258 | S: 6 259 | S_GW: 6 260 | S_h: 6 261 | Sb: 5 262 | Sb_GW: 5 263 | Sb_d_GW: 15 264 | Sb_sv_GW: 23 265 | Sc: 3 266 | Sc_sv: 11 267 | Sc_sv_GW: 11 268 | Se: 6 269 | Se_GW: 6 270 | Se_sv_GW: 24 271 | Si: 4 272 | Si_GW: 4 273 | Si_sv_GW: 12 274 | Sm: 16 275 | Sm_3: 11 276 | Sn: 4 277 | Sn_d: 14 278 | Sn_d_GW: 14 279 | Sn_sv_GW: 22 280 | Sr_sv: 10 281 | Sr_sv_GW: 10 282 | Ta: 5 283 | Ta_pv: 11 284 | Ta_sv_GW: 13 285 | Tb: 19 286 | Tb_3: 9 287 | Tc: 7 288 | Tc_pv: 13 289 | Tc_sv: 15 290 | Tc_sv_GW: 15 291 | Te: 6 292 | Te_GW: 6 293 | Te_sv_GW: 24 294 | Th: 12 295 | Th_s: 10 296 | Ti: 4 297 | Ti_pv: 10 298 | Ti_sv: 12 299 | Ti_sv_GW: 12 300 | Tl: 3 301 | Tl_d: 13 302 | Tl_d_GW: 15 303 | Tl_sv_GW: 21 304 | Tm: 23 305 | Tm_3: 9 306 | U: 14 307 | U_s: 14 308 | V: 5 309 | V_pv: 11 310 | V_sv: 13 311 | V_sv_GW: 13 312 | W: 6 313 | W_sv: 14 314 | W_sv_GW: 14 315 | Xe: 8 316 | Xe_GW: 8 317 | Xe_sv_GW: 26 318 | Y_sv: 11 319 | Y_sv_GW: 11 320 | Yb: 24 321 | Yb_2: 8 322 | Yb_3: 9 323 | Zn: 12 324 | Zn_GW: 12 325 | Zn_sv_GW: 20 326 | Zr_sv: 12 327 | Zr_sv_GW: 12 328 | -------------------------------------------------------------------------------- /vasppy/data/PBE_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ac: 11 2 | Ag: 11 3 | Ag_new: 11 4 | Ag_pv: 17 5 | Al: 3 6 | Am: 17 7 | Ar: 8 8 | As: 5 9 | As_GW: 5 10 | As_d: 15 11 | As_d_GW: 15 12 | At: 7 13 | At_d: 17 14 | Au: 11 15 | Au_new: 11 16 | B: 3 17 | B_h: 3 18 | B_s: 3 19 | Ba_sv: 10 20 | Be: 2 21 | Be_sv: 4 22 | Bi: 5 23 | Bi_d: 15 24 | Bi_pv: 21 25 | Br: 7 26 | C: 4 27 | C_GW: 4 28 | C_d: 4 29 | C_h: 4 30 | C_h_nr: 4 31 | C_s: 4 32 | Ca: 2 33 | Ca_pv: 8 34 | Ca_sv: 10 35 | Cd: 12 36 | Ce: 12 37 | Ce_3: 11 38 | Ce_h: 12 39 | Cl: 7 40 | Cl_h: 7 41 | Co: 9 42 | Co_new: 9 43 | Co_sv: 17 44 | Cr: 6 45 | Cr_pv: 12 46 | Cr_pv_new: 12 47 | Cr_sv: 14 48 | Cr_sv_new: 14 49 | Cs_sv: 9 50 | Cu: 11 51 | Cu_f: 11 52 | Cu_new: 11 53 | Cu_pv: 17 54 | Cu_pvf: 17 55 | Dy: 20 56 | Dy_3: 9 57 | Er: 22 58 | Er_2: 8 59 | Er_3: 9 60 | Eu: 17 61 | Eu_2: 8 62 | Eu_3: 9 63 | Eu_GW: 17 64 | F: 7 65 | F_d_GW: 7 66 | F_h: 7 67 | F_s: 7 68 | Fe: 8 69 | Fe_pv: 14 70 | Fe_pv_new: 14 71 | Fe_sv: 16 72 | Fe_sv_h: 16 73 | Fr_sv: 9 74 | Ga: 3 75 | Ga_d: 13 76 | Ga_d_GW: 13 77 | Ga_h: 13 78 | Ga_s: 3 79 | Ga_sv_GW: 21 80 | Gd: 18 81 | Gd_3: 9 82 | Ge: 4 83 | Ge_d: 14 84 | Ge_d3: 14 85 | Ge_d_GW: 14 86 | Ge_d_GW2: 14 87 | Ge_d_GW_ref: 14 88 | Ge_h: 14 89 | H: 1 90 | H.5: 0 91 | H.75: 0 92 | H1.25: 1 93 | H1.5: 1 94 | H_h: 1 95 | He: 2 96 | Hf: 4 97 | Hf_pv: 10 98 | Hf_sv: 12 99 | Hf_sv_GW: 12 100 | Hg: 12 101 | Ho: 21 102 | Ho_3: 9 103 | I: 7 104 | In: 3 105 | In_d: 13 106 | Ir: 9 107 | K_pv: 7 108 | K_sv: 9 109 | Kr: 8 110 | La: 11 111 | La_s: 9 112 | Li: 1 113 | Li_sv: 3 114 | Li_sv2: 3 115 | Lu: 25 116 | Lu_3: 9 117 | Mg: 2 118 | Mg_new: 2 119 | Mg_pv: 8 120 | Mg_pv.old: 8 121 | Mg_pv_GW: 8 122 | Mg_sv: 10 123 | Mn: 7 124 | Mn_pv: 13 125 | Mn_pv_new: 13 126 | Mn_sv: 15 127 | Mo: 6 128 | Mo_pv: 12 129 | Mo_pv_new: 12 130 | Mo_sv: 14 131 | N: 5 132 | N_h: 5 133 | N_s: 5 134 | N_s_GW: 5 135 | N_vs: 5 136 | Na: 1 137 | Na_pv: 7 138 | Na_sv: 9 139 | Nb_pv: 11 140 | Nb_sv: 13 141 | Nb_sv_new: 13 142 | Nd: 14 143 | Nd_3: 11 144 | Ne: 8 145 | Ni: 10 146 | Ni_new: 10 147 | Ni_pv: 16 148 | Np: 15 149 | Np_s: 15 150 | O: 6 151 | O_GW: 6 152 | O_h: 6 153 | O_s: 6 154 | O_s_GW: 6 155 | O_sv: 8 156 | Os: 8 157 | Os_pv: 14 158 | P: 5 159 | P_h: 5 160 | Pa: 13 161 | Pa_s: 11 162 | Pb: 4 163 | Pb_d: 14 164 | Pb_d_rel: 14 165 | Pb_d_rel2: 14 166 | Pd: 10 167 | Pd_new: 10 168 | Pd_pv: 16 169 | Pd_pv_new: 16 170 | Pd_vnew: 10 171 | Pm: 15 172 | Pm_3: 11 173 | Po: 6 174 | Po_d: 16 175 | Pr: 13 176 | Pr_3: 11 177 | Pt: 10 178 | Pt_ZORA: 10 179 | Pt_new: 10 180 | Pt_pv: 16 181 | Pt_pv_ZORA: 16 182 | Pu: 16 183 | Pu_h: 16 184 | Pu_s: 16 185 | Ra_sv: 10 186 | Rb_pv: 7 187 | Rb_sv: 9 188 | Re: 7 189 | Re_pv: 13 190 | Rh: 9 191 | Rh_new: 9 192 | Rh_pv: 15 193 | Rh_pv_new: 15 194 | Rn: 8 195 | Ru: 8 196 | Ru_new: 8 197 | Ru_pv: 14 198 | Ru_pv_new: 14 199 | Ru_sv: 16 200 | S: 6 201 | S_h: 6 202 | Sb: 5 203 | Sc: 3 204 | Sc_sv: 11 205 | Sc_sv_h: 11 206 | Se: 6 207 | Se_GW: 6 208 | Si: 4 209 | Si_d_GW: 4 210 | Si_d_GW_nr: 4 211 | Si_h: 4 212 | Si_h_old: 4 213 | Si_nopc: 4 214 | Si_pv_GW: 10 215 | Si_sv_GW: 12 216 | Si_sv_GW_nr: 12 217 | Sm: 16 218 | Sm_3: 11 219 | Sn: 4 220 | Sn_GW: 4 221 | Sn_d: 14 222 | Sr_sv: 10 223 | Ta: 5 224 | Ta_pv: 11 225 | Tb: 19 226 | Tb_3: 9 227 | Tc: 7 228 | Tc_new: 7 229 | Tc_pv: 13 230 | Tc_pv_new: 13 231 | Te: 6 232 | Te_rel: 6 233 | Th: 12 234 | Th_s: 10 235 | Ti: 4 236 | Ti_pv: 10 237 | Ti_sv: 12 238 | Ti_sv_GW: 12 239 | Ti_sv_h: 12 240 | Ti_sv_new: 12 241 | Ti_sv_new2: 12 242 | Tl: 3 243 | Tl_d: 13 244 | Tm: 23 245 | Tm_3: 9 246 | U: 14 247 | U_s: 14 248 | V: 5 249 | V_pv: 11 250 | V_sv: 13 251 | V_sv_h: 13 252 | V_sv_new: 13 253 | W: 6 254 | W_pv: 12 255 | W_pv_new: 12 256 | Xe: 8 257 | Y_sv: 11 258 | Yb: 24 259 | Yb_2: 8 260 | Yb_2_n: 10 261 | Zn: 12 262 | Zn_pv: 18 263 | Zr: 4 264 | Zr_sv: 12 265 | Zr_sv_GW: 12 266 | Zr_sv_new: 12 267 | -------------------------------------------------------------------------------- /vasppy/data/USPP_GGA_md5.yaml: -------------------------------------------------------------------------------- 1 | Ag: d60cd4929088c040581084b40e4b2f94 2 | Al: a16763a52da5e43988f178ae2a694d8c 3 | Al_h: 8e890ddab90203faaa023df6aed7a1fa 4 | Ar: c27e8f5c6074c3f05bd6dfaecac84af9 5 | As: 8d9e5cf6e9ee4da39c329da581efa904 6 | Au: 56247e2fa6201a9dc922c32d1eca5853 7 | B: b666b1abe48066ba926ed1c9d8b2c0c8 8 | B_s: 9c1e415ed408abc7b4a9130c3b271e34 9 | Ba_pv: b9306a9c86d23844a060e5a1d2ef1aa9 10 | Be: 471b9403e0964e264c8d284656158821 11 | Bi: 020b5eff92bebba8759bd6031116b71b 12 | Br: ffed832faf9b791bbf5432532d4d5db9 13 | C: f65131829cbfb8be4b5a0aa72cd47486 14 | C_s: d6587584adfde24ff0164b5a7159ed24 15 | Ca: 918969eac46329d28cc77c9c90766b1d 16 | Ca_pv: e5e22945fb7173c023b43ef158bb8896 17 | Cd: 8b3cf01d5cf305e51a375218e1f63152 18 | Cl: bb96d4f310401d743007ccf57be3a6de 19 | Co: 29d84db0baa8b74e4b365eb41b398926 20 | Cr: 5b8d3fdf2095158732a4f118e62ad5ad 21 | Cs: d202b727b89edfb437ba8dae24c28e72 22 | Cs_pv: 5c6d68c09c7fd9b8b20b6a7060fc0dfc 23 | Cu: a6421c4d1dd4706526424b8aab7875cf 24 | F: 62cbfa5f1291bc1dfaf7a710c96f2952 25 | F_s: 8fdf35cd7e0d8c6c1b9ecb8848e87499 26 | Fe: 78b9c24e72a8f7b691f63f7f3d3e82b3 27 | Ga: cf52c5a41016c598d3a535a949d6245d 28 | Ga_d: f3bde34eb0363f885ef401a7d56c2ac3 29 | Ge: 60df1a19bf0f6c7e237d393fe6b21c0c 30 | H_200eV: 9484e4d2f27072e1d53487ba58e1421c 31 | H_soft: 49b344701d738d9372888f29b8e0d105 32 | Hf: 142c010699d14efb38173f692cf6e8f4 33 | Hg: 9cb5c078d34933144ece763122850172 34 | I: 2a13ac6c3894ad9d7f128d50d0eb41a7 35 | In: 62bd74bc1386f1abff0dee22907964d7 36 | In_d: df02b0d0b14fea4ae46bd8f9f666df64 37 | Ir: 5e6f57ac4035a68567e687bb3f5616a3 38 | K: c329e24fe3fe36a8a418cb40e3669f17 39 | K_pv: 981903b398cfbf64dc67dabe6fd45a29 40 | Kr: 0c33e83039365a1ddb7783b14f5c82a7 41 | Li: 774d82eaed8247f0cb9701cdaada92ad 42 | Li_h: 1dcfe2e618da404f09d5a54edcb6fc34 43 | Li_pv: 1dcfe2e618da404f09d5a54edcb6fc34 44 | Mg: 257f0f928ca725a948399f7ac36cb36a 45 | Mg_h: 16fef70d5b4d76a2e76a2cabc12265d1 46 | Mg_pv: fc26d5d6e47791127d2b48b5d6465ed7 47 | Mn: 24c6b3a1074d3ca066b7ddc4dae6541f 48 | Mo: e9381a1e6ed5c83a1f8835d662c621db 49 | Mo_pv: 427741efdc40518322fd314805e9ccd5 50 | N: b86eeda16c14379b5cf740db3bb4995f 51 | N_s: 80b1d8e093926a90a843e38d9970dfc5 52 | Na: d9070f25d81ddeb0759e58e93f15d5e2 53 | Na_h: 56bced9681d4b7afd52f3056278b8673 54 | Na_pv: bdfcc56631dac0a7bb06414f89f8e1a6 55 | Nb: 698d98bdd24cfe9fcfea521e047808a1 56 | Nb_pv: 31a5caa5656458e2b29574702d2705a2 57 | Ne: 6eee0f00a3df3188935982741549abe4 58 | Ni: cf98288758f8e0df76e7729faa5359be 59 | O: 70b688bdb1a9750c4e77f5fac3f702e1 60 | O_s: 07f7e14aeb982d675ce9765dc2ecfd06 61 | Os: 129f04d303f6692a42fb802f4e2068f3 62 | P: 1cf0505abc03ffb7b1a9d96a53435ba3 63 | Pb: 938cdfed4297995b7e1e59bdfeaeed32 64 | Pb_d: 22e99ce6d298bdcbd7ed939e5555998a 65 | Pd: aacd1ea5645e766bc578d70946f986fd 66 | Pt: fd17cf003dad0484f3aca9edc3b2a101 67 | Rb: 65ec19884d5ee3b370180b309a97bbc5 68 | Rb_pv: 66173067710aca5aa8c2e7b6db5fc6d0 69 | Re: 25a93745d878eaad63b45a5f12db614e 70 | Rh: eb4afbedfdb76bb415e5d05abc4df5ea 71 | Ru: a2610236af6e4ae645302ab61d240016 72 | S: 11bbaa304ba6cfdc9136d5bbf84ae3bd 73 | Sb: 12beb615acd4ef47911327f438ba6b29 74 | Sc: d99accd9c53d1479c25e557607ddd8cd 75 | Sc_pv: da13cbdce5b5b2fe9ce7f6f1a916ab0c 76 | Se: 43948e27685e956f5267da507585b401 77 | Si: e47cce7a32dc0bcf13a9a2dce87dde3f 78 | Si_h: 38488b2348665c18772812598978da8e 79 | Sn: 01d87027573c1dc64788aa4bc6312cae 80 | Sn_d: 2f98b98ae1bdbb3cfd4fb19d534721ff 81 | Sr: ea581c251e33259a24ce67b3e1b06e48 82 | Sr_pv: 922ed29ba450819965a499d37f2585a4 83 | Ta: e6f6f719eb624ef80ed9ba4517b6059e 84 | Tc: eca73a9770d88c4d4b59dffa91916acf 85 | Te: 1fa179e40d92f746ef940927af58242a 86 | Ti: cff918cd115f38cd9c8cabe0aba14006 87 | Ti_pv: 7f1010facd8517edab0414b61766674d 88 | Tl_d: 1391ddaaa9434fab4a3dac58aff7c741 89 | V: 40e3f7db26a0a3e082d0601d15098696 90 | V_pv: 36e14505556e2ff991b199280175464b 91 | W: 98b90e789a1477f248c758e9308b28bf 92 | Xe: 1b28a4cb2512434998d4ea3007a8484a 93 | Y: d6e9daa9c03a6524f47424bbee3758cd 94 | Y_pv: ec40634146e9f436bfc044b4713a5b5a 95 | Zn: 84221b8c6489d29220c2e08b13d9a119 96 | Zr: 458ab765213fcfa725dc495a3f67d6da 97 | Zr_pv: bbce40b0a1f47ad690a3899f11f5cacf 98 | -------------------------------------------------------------------------------- /vasppy/data/USPP_GGA_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ag: 11 2 | Al: 3 3 | Al_h: 3 4 | Ar: 8 5 | As: 5 6 | Au: 11 7 | B: 3 8 | B_s: 3 9 | Ba_pv: 8 10 | Be: 2 11 | Bi: 5 12 | Br: 7 13 | C: 4 14 | C_s: 4 15 | Ca: 2 16 | Ca_pv: 8 17 | Cd: 12 18 | Cl: 7 19 | Co: 9 20 | Cr: 6 21 | Cs: 1 22 | Cs_pv: 7 23 | Cu: 11 24 | F: 7 25 | F_s: 7 26 | Fe: 8 27 | Ga: 3 28 | Ga_d: 13 29 | Ge: 4 30 | H_200eV: 1 31 | H_soft: 1 32 | Hf: 4 33 | Hg: 12 34 | I: 7 35 | In: 3 36 | In_d: 13 37 | Ir: 9 38 | K: 1 39 | K_pv: 7 40 | Kr: 8 41 | Li: 1 42 | Li_h: 1 43 | Li_pv: 1 44 | Mg: 2 45 | Mg_h: 2 46 | Mg_pv: 8 47 | Mn: 7 48 | Mo: 6 49 | Mo_pv: 12 50 | N: 5 51 | N_s: 5 52 | Na: 1 53 | Na_h: 1 54 | Na_pv: 7 55 | Nb: 5 56 | Nb_pv: 11 57 | Ne: 8 58 | Ni: 10 59 | O: 6 60 | O_s: 6 61 | Os: 8 62 | P: 5 63 | Pb: 4 64 | Pb_d: 14 65 | Pd: 10 66 | Pt: 10 67 | Rb: 1 68 | Rb_pv: 7 69 | Re: 7 70 | Rh: 9 71 | Ru: 8 72 | S: 6 73 | Sb: 5 74 | Sc: 3 75 | Sc_pv: 9 76 | Se: 6 77 | Si: 4 78 | Si_h: 4 79 | Sn: 4 80 | Sn_d: 14 81 | Sr: 2 82 | Sr_pv: 8 83 | Ta: 5 84 | Tc: 7 85 | Te: 6 86 | Ti: 4 87 | Ti_pv: 10 88 | Tl_d: 13 89 | V: 5 90 | V_pv: 11 91 | W: 6 92 | Xe: 8 93 | Y: 3 94 | Y_pv: 9 95 | Zn: 12 96 | Zr: 4 97 | Zr_pv: 10 98 | -------------------------------------------------------------------------------- /vasppy/data/USPP_LDA_md5.yaml: -------------------------------------------------------------------------------- 1 | Ag: ca44407f75bbe28536ccbd54aab2903d 2 | Al: 16fca2830916c80aa11e4bf5aaec1451 3 | Al_h: 818ca57898ecbf6e51cad96a4eac8c79 4 | Ar: caa40f6e4bc306ea5f8716dd732760e9 5 | As: b51408115da65215ae682248d4a081e2 6 | Au: ba0e3abdc1fd77626ec6c8e68002d270 7 | B: b142eca3c528753dd51be9cb575d2cd3 8 | B_s: 98a91673fe236e0f3df468522714c45d 9 | Ba_pv: dd93238fae8f388cabb9694524c7780d 10 | Be: 225dec5456377fb027b46083426c573d 11 | Bi: 81e3cc8bc2d01fb0da970c6235f5f379 12 | Bi_d: c0ff3df7c5050ec2f5063c5ac404e95c 13 | Br: 89b2c34274c20f8efa8c68328a3470ce 14 | C: 63c5ec5bc26ee833756991c994bf3971 15 | C_s: 965ad21d4f1c880467a855733eaf6ec8 16 | Ca: 29c2427987fcd5f041f6c471fc0f337b 17 | Ca_pv: 1136d4843b98ae91d7fcfbac234cdc24 18 | Cd: bfcd5b09a5e80617e2d16e80b14046cf 19 | Cl: 2f00025ec1baa4a8c6d37c979919623a 20 | Co: 4a9742c340a6be9ab07e4ec2c0aba71a 21 | Cr: 704092fa305750c20280b1c8b1f57381 22 | Cs: fa5d137683d6da32cc92bfb205824e56 23 | Cs_pv: dfada2d074c371c592d0e52e38fc39c2 24 | Cu: f3cf3dd83f64133a5b544a62ca3be702 25 | F: 326de96574483922f1bf3888fab704bd 26 | F_s: 906a045f14450b5a37478ad1a0553513 27 | Fe: b61ee289bd85cad88bd9481c70bf0cce 28 | Ga: 1eaf48a036c7e2e65629320da4d98407 29 | Ga_d: eb970f596dec3d1bda47a37b8c30d054 30 | Ge: 99cb9eeb0ca7e512d6ea5c4105beb8bf 31 | H.75: b504aec00befd1bf8dd84e088e4f3d32 32 | H1.25: a5dd7ce269e71e62ce153bcd24e99e00 33 | H_200eV: 5f0ae8064899d63c6481246907d06e8e 34 | H_soft: eb925ad8f8292b2aed331bd3fe366259 35 | Hf: 860d3b62205a12b49525a1d715e1ea3e 36 | Hg: 3aaa62d8be49be2021e8c756c1dde17f 37 | I: 8e7515805abe1eb98abcea7688b6e9ba 38 | In: 33ba2a7bc2fbaa3e0e9830d30a9b3072 39 | In_d: 476aa320d08f591e0bed065f8d5a56af 40 | Ir: becde349adf12aec562c13a70ddbe499 41 | K: 473fc75393c4ee6ac6817cd0d9465e7c 42 | K_pv: 21ff2e0252657efb7a70447c361ae6f3 43 | K_s: 2bcf0db4612986a5f0741705f8e8823d 44 | Kr: 0c33e83039365a1ddb7783b14f5c82a7 45 | Li: 7f480fd59f9bde50da079df658742ee8 46 | Li_h: 4c74f0df2aab6681c6744b8eaf850f28 47 | Li_pv: 4c74f0df2aab6681c6744b8eaf850f28 48 | Mg: f03c8d6d3159a2550ccc76e24e054885 49 | Mg_h: c264097e2def1de94691fe6626062f02 50 | Mg_pv: 82aba8531d839cebc92d493c25f9e26b 51 | Mn: ffe37780b855cb0c6bedd8abf94dd04a 52 | Mn_pv: 81246d71b94d4dcc4af806fa43e6f9d8 53 | Mo: 954369c75ae104b150736115e37d3fa1 54 | Mo_pv: c3e4d496c16e4ff400d66822d3634cb7 55 | N: ea7c6f6f527a5fca95fd7e04c52e0a8b 56 | N_s: 4e404139009f542d53bdf22c02c8a531 57 | Na: 3f674ff12db279ad04fd349216804fc9 58 | Na_h: 00dc21593b6617acfecd8501c979b5b1 59 | Na_pv: 38c7cc867fdb4b3ae2074b1d672d8af7 60 | Nb: bce7365c904e63bee656efe9374cf890 61 | Nb_pv: 2f3c182389c4645a84ba4583df4d0e65 62 | Ne: ebc64bf8b887fb144558f18d067bbda3 63 | Ni: 90ea5f80a94706d35a7b00017f2eea48 64 | O: ea3fd13db24585836db99a6aeeed0931 65 | O_s: 13f339e581b350b337ba9cd617babfec 66 | Os: de797260e88311fdc7adc0788fda7507 67 | P: d591131ae60516d08ccbc0689707f22a 68 | Pb: 369a0b5aebda5a1692589bd394bf4239 69 | Pb_d: 25020e2faceab7f1a7b4030f7989cec4 70 | Pd: 985650fa5bdfa09a60335928a55cbe8c 71 | Pt: d6a342d830c75bc5ebc63a0f3980b823 72 | Rb: a947821e5d1ac7e12a8421bdeaef7f32 73 | Rb_pv: c3f8a7f74bb04ec0b606684a264614a3 74 | Rb_s: 71f96df79cd09e9db3aeb8c1ea5760e3 75 | Re: 8a68fe927b627c198536c6412e14bb44 76 | Rh: 5d722d70c79ceb79aaf17557c0c146a0 77 | Ru: ff3f1a0dc666902913217fff463f1117 78 | S: dfa02f15ca6284def141cdd5b79b6043 79 | Sb: b484cc8cbb354783d88aaded3ec07814 80 | Sc: ce8f88fa03f78a93f9ca918561e45822 81 | Sc_pv: c5cf4ef5ccb3b6f02f82c929540cb3fd 82 | Se: 480b2eaaf75332e764c806dd21733774 83 | Si: d99ccf54210409148cb7bc76a515a192 84 | Si_h: 62a17b18a346b0e1165ed9e1e1ecdfa3 85 | Sn: 6143f182786cfed76473941a501b245f 86 | Sn_d: 502225bfd1433683ec16cb034b571c79 87 | Sr: 350a048490f7de0b7319cbe4b61f8732 88 | Sr_pv: 3b06e61b53c19d6260ddacf80e512e24 89 | Tc: 1c0878637a54be3402087aed5ea1f957 90 | Te: 9fe9dcea0481d0e374ab8a244e321fdf 91 | Ti: d8d89f6c619cab23e5cec5439dfcf9da 92 | Ti_pv: 20fd79c679ca800665c253449e2aaff2 93 | Tl_d: 2d5a818a22f145d6d1b17400177fa591 94 | V: 640dfdb08c0a059fce4c22eef69dd3ed 95 | V_pv: 1125e888772e40c79d7285cede56f17e 96 | W: a9b59cee55b6aae721c20a9647427926 97 | Xe: 1b28a4cb2512434998d4ea3007a8484a 98 | Y: 97a5f2021445786ae2da27f1760f1347 99 | Y_pv: db3c69701f52c55e1fb6ed941ba40979 100 | Zn: 941725ce35406aa8f4ca40df9adefa74 101 | Zr: bfe48d8236b250a56f85cc2f393481b1 102 | Zr_pv: 08dd343372e1aa9c267979765596f3a6 103 | -------------------------------------------------------------------------------- /vasppy/data/USPP_LDA_nelect.yaml: -------------------------------------------------------------------------------- 1 | Ag: 11 2 | Al: 3 3 | Al_h: 3 4 | Ar: 8 5 | As: 5 6 | Au: 11 7 | B: 3 8 | B_s: 3 9 | Ba_pv: 8 10 | Be: 2 11 | Bi: 5 12 | Bi_d: 15 13 | Br: 7 14 | C: 4 15 | C_s: 4 16 | Ca: 2 17 | Ca_pv: 8 18 | Cd: 12 19 | Cl: 7 20 | Co: 9 21 | Cr: 6 22 | Cs: 1 23 | Cs_pv: 7 24 | Cu: 11 25 | F: 7 26 | F_s: 7 27 | Fe: 8 28 | Ga: 3 29 | Ga_d: 13 30 | Ge: 4 31 | H.75: 0 32 | H1.25: 1 33 | H_200eV: 1 34 | H_soft: 1 35 | Hf: 4 36 | Hg: 12 37 | I: 7 38 | In: 3 39 | In_d: 13 40 | Ir: 9 41 | K: 1 42 | K_pv: 7 43 | K_s: 1 44 | Kr: 8 45 | Li: 1 46 | Li_h: 1 47 | Li_pv: 1 48 | Mg: 2 49 | Mg_h: 2 50 | Mg_pv: 8 51 | Mn: 7 52 | Mn_pv: 13 53 | Mo: 6 54 | Mo_pv: 12 55 | N: 5 56 | N_s: 5 57 | Na: 1 58 | Na_h: 1 59 | Na_pv: 7 60 | Nb: 5 61 | Nb_pv: 11 62 | Ne: 8 63 | Ni: 10 64 | O: 6 65 | O_s: 6 66 | Os: 8 67 | P: 5 68 | Pb: 4 69 | Pb_d: 14 70 | Pd: 10 71 | Pt: 10 72 | Rb: 1 73 | Rb_pv: 7 74 | Rb_s: 1 75 | Re: 7 76 | Rh: 9 77 | Ru: 8 78 | S: 6 79 | Sb: 5 80 | Sc: 3 81 | Sc_pv: 9 82 | Se: 6 83 | Si: 4 84 | Si_h: 4 85 | Sn: 4 86 | Sn_d: 14 87 | Sr: 2 88 | Sr_pv: 8 89 | Tc: 7 90 | Te: 6 91 | Ti: 4 92 | Ti_pv: 10 93 | Tl_d: 13 94 | V: 5 95 | V_pv: 11 96 | W: 6 97 | Xe: 8 98 | Y: 3 99 | Y_pv: 9 100 | Zn: 12 101 | Zr: 4 102 | Zr_pv: 10 103 | -------------------------------------------------------------------------------- /vasppy/data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmorgan/vasppy/f913b1bd034e4b106bb83e13c0f4c5a0e09151b7/vasppy/data/__init__.py -------------------------------------------------------------------------------- /vasppy/data/potcar_data.py: -------------------------------------------------------------------------------- 1 | import os 2 | import yaml # type: ignore 3 | 4 | my_path = os.path.dirname(__file__) 5 | 6 | potcar_md5sum_data = {} 7 | potcar_nelect = {} 8 | 9 | potcar_sets = [ 10 | "PBE", 11 | "PBE_52", 12 | "PBE_54", 13 | "PBE_54r", 14 | "LDA_54r", 15 | "GGA", 16 | "USPP_GGA", 17 | "LDA", 18 | "LDA_52", 19 | "LDA_54", 20 | "USPP_LDA", 21 | ] 22 | 23 | for potcar_set in potcar_sets: 24 | with open(f"{os.path.join(my_path, potcar_set)}_md5.yaml", "r") as stream: 25 | potcar_md5sum_data[potcar_set] = yaml.load(stream, Loader=yaml.SafeLoader) 26 | 27 | for potcar_set in potcar_sets: 28 | with open(f"{os.path.join(my_path, potcar_set)}_nelect.yaml", "r") as stream: 29 | potcar_nelect[potcar_set] = yaml.load(stream, Loader=yaml.SafeLoader) 30 | -------------------------------------------------------------------------------- /vasppy/grid.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import sys 3 | import math 4 | from vasppy import poscar, cell 5 | 6 | 7 | def interpolate(i, j, x): 8 | return (i * (1.0 - x)) + (j * x) 9 | 10 | 11 | def trilinear_interpolation(cube, r): 12 | return interpolate( 13 | interpolate( 14 | interpolate( 15 | cube[0, 0, 0], cube[1, 0, 0], r[0] 16 | ), # trilinear interpolation => http://en.wikipedia.org/wiki/Trilinear_interpolation 17 | interpolate(cube[0, 1, 0], cube[1, 1, 0], r[0]), 18 | r[1], 19 | ), 20 | interpolate( 21 | interpolate(cube[0, 0, 1], cube[1, 0, 1], r[0]), 22 | interpolate(cube[0, 1, 1], cube[1, 1, 1], r[0]), 23 | r[1], 24 | ), 25 | r[2], 26 | ) 27 | 28 | 29 | class Grid: 30 | projections = {"x": 0, "y": 1, "z": 2} 31 | 32 | def __init__(self, dimensions=(1, 1, 1)): 33 | self.filename = None 34 | self.poscar = poscar.Poscar() 35 | self.number_of_header_lines = 0 36 | self.dimensions = list(dimensions) 37 | self.spacing = np.array( 38 | [1.0 / number_of_points for number_of_points in self.dimensions] 39 | ) 40 | self.grid = np.zeros(self.dimensions) 41 | 42 | def read_from_filename(self, filename): 43 | self.filename = filename 44 | self.poscar = poscar.Poscar() 45 | self.poscar.read_from(self.filename) 46 | self.number_of_header_lines = ( 47 | sum(self.poscar.atom_numbers) + poscar.Poscar.lines_offset 48 | ) 49 | self.read_dimensions() 50 | self.read_grid() 51 | return self 52 | 53 | def write_to_filename(self, filename): 54 | with open(filename, "w") as file_out: 55 | sys.stdout = file_out 56 | self.poscar.output() 57 | self.write_dimensions() 58 | sys.stdout.flush() 59 | self.write_grid() 60 | 61 | def read_dimensions(self): 62 | with open(self.filename, "r") as file_in: 63 | for i, line in enumerate(file_in): 64 | if i == self.number_of_header_lines: 65 | self.dimensions = [int(i) for i in line.split()] 66 | break 67 | 68 | def write_dimensions(self): 69 | print("\n" + " ".join([str(i) for i in self.dimensions])) 70 | 71 | def read_grid(self): 72 | grid_data = [] 73 | grid_data_lines = math.ceil( 74 | (self.dimensions[0] * self.dimensions[1] * self.dimensions[2]) / 5 75 | ) 76 | with open(self.filename) as file_in: 77 | for i, line in enumerate(file_in): 78 | if (i > self.number_of_header_lines) and ( 79 | i <= self.number_of_header_lines + grid_data_lines 80 | ): 81 | grid_data.append(line.strip()) 82 | grid_data = np.array([float(s) for s in " ".join(grid_data).split()]) 83 | self.grid = np.reshape(grid_data, tuple(self.dimensions), order="F") 84 | 85 | def write_grid(self): 86 | np.savetxt( 87 | sys.stdout.buffer, np.swapaxes(self.grid, 0, 2).reshape(-1, 5), fmt="%.11E" 88 | ) 89 | 90 | def average(self, normal_axis_label): 91 | axes = [0, 1, 2] 92 | axes.remove(Grid.projections[normal_axis_label]) 93 | return np.sum(np.sum(self.grid, axis=axes[1]), axis=axes[0]) / ( 94 | self.dimensions[0] * self.dimensions[1] 95 | ) 96 | 97 | def by_index(self, index): 98 | return self.grid[index[0], index[1], index[2]] 99 | 100 | def fractional_coordinate_at_index(self, index): 101 | return np.multiply(self.spacing, index) 102 | 103 | def cartesian_coordinate_at_index(self, index): 104 | return self.fractional_coordinate_at_index(index).dot(self.poscar.cell.matrix) 105 | 106 | def cube_slice(self, x0, y0, z0): 107 | x1 = (x0 + 1) % self.dimensions[0] 108 | y1 = (y0 + 1) % self.dimensions[1] 109 | z1 = (z0 + 1) % self.dimensions[2] 110 | cube = np.array( 111 | [ 112 | self.grid[x0, y0, z0], 113 | self.grid[x0, y0, z1], 114 | self.grid[x0, y1, z0], 115 | self.grid[x0, y1, z1], 116 | self.grid[x1, y0, z0], 117 | self.grid[x1, y0, z1], 118 | self.grid[x1, y1, z0], 119 | self.grid[x1, y1, z1], 120 | ] 121 | ).reshape((2, 2, 2)) 122 | return cube 123 | 124 | def interpolated_value_at_fractional_coordinate(self, coord): 125 | point = np.multiply( 126 | np.array(self.dimensions), coord 127 | ) # point contains the (fractional) index of the coordinate coord. 128 | origin = [ 129 | int(f) for f in point 130 | ] # origin contains the 3D index of the lowest-index point in the cube surrounding point (i,j,k) 131 | delta = [ 132 | p - o for p, o in zip(point, origin) 133 | ] # delta contains the *fractional* offset of "point" from "origin" 134 | cube = self.cube_slice( 135 | *origin 136 | ) # cube contains the data values at the 8 bounding grid points 137 | return trilinear_interpolation(cube, delta) 138 | 139 | def interpolate_to_orthorhombic_grid( 140 | self, dimensions 141 | ): # warning. This may need a more robust minimim image function in Cell.py for highly non-orthorhombic cells 142 | old_grid = self 143 | old_cell = old_grid.poscar.cell 144 | new_grid = Grid(dimensions=dimensions) 145 | new_grid.poscar.cell = cell.Cell(np.diag(np.diag(self.poscar.cell.matrix))) 146 | index_grid = np.array( 147 | [[i, j, k] for (i, j, k), value in np.ndenumerate(new_grid.grid)] 148 | ) 149 | cart_coord_grid = np.array( 150 | [new_grid.cartesian_coordinate_at_index(index) for index in index_grid] 151 | ) 152 | init_frac_coord_grid = np.array( 153 | [old_cell.cartesian_to_fractional_coordinates(r) for r in cart_coord_grid] 154 | ) 155 | frac_coord_grid = np.array( 156 | [old_cell.inside_cell(r) for r in init_frac_coord_grid] 157 | ) 158 | new_grid_data = np.array( 159 | [ 160 | old_grid.interpolated_value_at_fractional_coordinate(r) 161 | for r in frac_coord_grid 162 | ] 163 | ) 164 | new_grid.grid = new_grid_data.reshape(new_grid.dimensions) 165 | return new_grid 166 | -------------------------------------------------------------------------------- /vasppy/kpoints.py: -------------------------------------------------------------------------------- 1 | import numpy as np # type: ignore 2 | from typing import Optional 3 | 4 | class AutoKPoints: 5 | """Class for automatic k-point generation data in KPOINTS.""" 6 | 7 | def __init__( 8 | self, 9 | title: str, 10 | subdivisions: np.ndarray, 11 | grid_centering: Optional[str] = "G", 12 | shift: Optional[np.ndarray] = None, 13 | ) -> None: 14 | """Initialise an AutoKPoints object. 15 | 16 | Args: 17 | title (str): The first line of the file, treated as a comment by VASP. 18 | subdivisions: (np.ndarray(int, int, int)): 19 | Numbers of subdivisions along each reciprocal lattice vector. 20 | grid_centering (str, optional): 21 | Specify gamma-centered (G) or the original Monkhorst-Pack scheme (MP). 22 | Default is 'G'. 23 | shift: (np.ndarray(float, float, float), optional): 24 | Optional shift of the mesh (s_1, s_2, s_3). Default is ( [ 0., 0., 0. ] ). 25 | 26 | Returns: 27 | None 28 | 29 | Raises: 30 | ValueError: If an unrecognised grid-centering option is passed in. 31 | 32 | """ 33 | accepted_grid_centerings = ["G", "MP"] 34 | if grid_centering not in accepted_grid_centerings: 35 | raise ValueError 36 | self.title = title 37 | self.grid_centering = grid_centering 38 | self.subdivisions = subdivisions 39 | if shift is None: 40 | self.shift = np.array([0.0, 0.0, 0.0]) 41 | else: 42 | self.shift = shift 43 | 44 | def get_subdivisions_from_kspacing(kspacing: float, 45 | reciprocal_lattice_vectors: np.ndarray) -> tuple[int, ...]: 46 | """Calculate subdivisions along reciprocal lattice vectors from the miniumum allowed distance between k-points (KSPACING). 47 | 48 | Args: 49 | kspacing (float): The minimum allowed distance between k-points. 50 | reciprocal_lattice_vectors (np.ndarray): The reciprocal lattice vectors. These can be retrieved from ASE as atoms.cell.reciprocal() or from Pymatgen as 51 | structure.lattice.reciprocal_lattice_crystallographic.matrix. 52 | 53 | Returns: 54 | tuple[int, ...]: The subdivisions along each reciprocal lattice vector. 55 | """ 56 | subdivisions = [] 57 | for row in reciprocal_lattice_vectors: 58 | magnitude = np.linalg.norm(row) 59 | subdivision = np.max([1, np.ceil((magnitude * 2 * np.pi) / kspacing)]) 60 | 61 | subdivisions.append(int(subdivision)) 62 | 63 | return tuple(subdivisions) 64 | 65 | def get_convergence_testing_kspacing(reciprocal_lattice_vectors: np.ndarray, 66 | kspacing_range: tuple[float, float]=(0.1, 0.8), 67 | step: float=0.02) -> tuple[float, ...]: 68 | """Generate a range of minimum allowed distances between k-points (KSPACING) for convergence testing. This function ensures that no two values of KSPACING 69 | are generated that correspond to the same k-point mesh. 70 | 71 | Args: 72 | reciprocal_lattice_vectors (np.ndarray): The reciprocal lattice vectors. These can be retrieved from ASE as atoms.cell.reciprocal() or from Pymatgen as 73 | structure.lattice.reciprocal_lattice_crystallographic.matrix. 74 | kspacing_range (tuple[float, float]): The minimum and maximum KSPACING values. Defaults to (0.1, 0.8). 75 | step (float): The interval between KSPACING values to be tested. Defaults to 0.02. 76 | 77 | Returns: 78 | tuple[float, ...]: A range of KSPACING values which all correspond to distinct k-point grids. 79 | """ 80 | allowed_kspacing = [] 81 | highest_total = 0.0 82 | kspacing_min, kspacing_max = kspacing_range 83 | for kspacing in np.arange(kspacing_min, kspacing_max + step, step): 84 | subdivisions = get_subdivisions_from_kspacing(kspacing, reciprocal_lattice_vectors) 85 | total = 1 / sum(subdivisions) 86 | 87 | if total > highest_total: 88 | allowed_kspacing.append(round(kspacing, 3)) 89 | highest_total = total 90 | 91 | return tuple(allowed_kspacing) 92 | -------------------------------------------------------------------------------- /vasppy/neighbour_list.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pymatgen.core import Structure # type: ignore 4 | from vasppy.utils import dr_ij 5 | from typing import Type 6 | import numpy as np 7 | 8 | """ 9 | This module provides a NeighbourList class following the scheme in 10 | Rabani et al. J. Chem. Phys. 1997 11 | doi: https://doi.org/10.1063/1.474927 12 | """ 13 | 14 | 15 | class NeighbourList(object): 16 | """ 17 | Class for computing a set of neighbour lists. 18 | 19 | Attributes: 20 | vectors (np.ndarray): An array of M neighbour lists, with each list a 1D 21 | vector over N potential neighbours, stored as a M x N numpy array. 22 | Each neighbour list is constructed following the scheme in 23 | Rabani et al. J. Chem. Phys. 1997 24 | doi: https://doi.org/10.1063/1.474927 25 | 26 | """ 27 | 28 | def __init__( 29 | self, 30 | structure: Structure, 31 | indices_i: list[int], 32 | indices_j: list[int], 33 | r_cut: float, 34 | ) -> None: 35 | """ 36 | Initialise a NeighbourList instance. 37 | 38 | Args: 39 | structure (pymatgen.Structure): Pymatgen Structure object to parse. 40 | indices_i (list(int)): List of indices of central atoms. 41 | indices_j (list(int)): List of indices of potential neighbour atoms. 42 | r_cut (float): Neighbour cutoff distance. 43 | 44 | """ 45 | all_dr_ij = dr_ij( 46 | structure=structure, 47 | indices_i=indices_i, 48 | indices_j=indices_j, 49 | self_reference=False, 50 | ) 51 | self.vectors = (all_dr_ij <= r_cut).astype(int) 52 | 53 | @property 54 | def coordination_numbers(self) -> np.ndarray: 55 | """ 56 | Return the coordination number of each site i. 57 | 58 | Args: 59 | None 60 | 61 | Returns: 62 | None 63 | 64 | """ 65 | return np.sum(self.vectors, axis=1) 66 | 67 | def __eq__(self, other: object) -> bool: 68 | """Test whether two NeighbourList objects have equal vectors.""" 69 | if not isinstance(other, NeighbourList): 70 | return NotImplemented 71 | return (self.vectors == other.vectors).all() 72 | 73 | @classmethod 74 | def from_species_strings( 75 | cls: Type[NeighbourList], 76 | structure: Structure, 77 | species_i: str, 78 | species_j: str, 79 | r_cut: float, 80 | ) -> NeighbourList: 81 | """ 82 | Initialise a NeighbourList instance by specifying species strings. 83 | 84 | Args: 85 | structure (pymatgen.Structure): A pymatgen Structure. 86 | species_i (str): String for species i, e.g., ``"Na"``. 87 | species_j (str): String for species j, e.g., ``"Cl"``. 88 | r_cut (float): Neighbour cutoff radius. 89 | 90 | Returns: 91 | (NeighbourList) 92 | 93 | """ 94 | indices_i = [ 95 | i for i, site in enumerate(structure) if site.species_string == species_i 96 | ] 97 | indices_j = [ 98 | j for j, site in enumerate(structure) if site.species_string == species_j 99 | ] 100 | return cls( 101 | structure=structure, indices_i=indices_i, indices_j=indices_j, r_cut=r_cut 102 | ) 103 | 104 | 105 | def neighbour_list_correlation( 106 | nlist_i: NeighbourList, nlist_j: NeighbourList 107 | ) -> np.ndarray: 108 | """ 109 | Compute the normalised correlation between two NeighbourList object. 110 | 111 | Args: 112 | nlist_i (NeighbourList): A NeighbourList object. 113 | nlist_j (NeighbourList): A NeighbourList object. 114 | 115 | Returns: 116 | (np.ndarray(float)): A 1D array of normalised correlation terms. 117 | 118 | Raises: 119 | ValueError: If the two NeighbourList objects have different numbers 120 | of lengths of neighbour list vectors. 121 | 122 | Note: 123 | For each neighbour list vector, computes (l_i.l_j)/(l_i.l_i). 124 | See Rabani et al. J. Chem. Phys. 1997 doi:https://doi.org/10.1063/1.474927 125 | Eqn. 7 for details. 126 | 127 | """ 128 | if nlist_i.vectors.shape != nlist_j.vectors.shape: 129 | raise ValueError( 130 | f"NeighbourList vector shapes are not equal: {nlist_i.vectors.shape} != {nlist_j.vectors.shape}" 131 | ) 132 | return np.einsum("ij,ij->i", nlist_i.vectors, nlist_j.vectors) / np.einsum( 133 | "ij,ij->i", nlist_i.vectors, nlist_i.vectors 134 | ) 135 | 136 | 137 | def neighbour_list_n_out(nlist_i: NeighbourList, nlist_j: NeighbourList) -> np.ndarray: 138 | """ 139 | Compute n^out between two NeighbourList object. 140 | 141 | Args: 142 | nlist_i (NeighbourList): A NeighbourList object for neighbour lists at time 0. 143 | nlist_j (NeighbourList): A NeighbourList object for neighbour lists at time t. 144 | 145 | Returns: 146 | (np.ndarray(float)): A 1D array of normalised correlation terms. 147 | 148 | Raises: 149 | ValueError: If the two NeighbourList objects have different numbers 150 | of lengths of neighbour list vectors. 151 | 152 | Note: 153 | For each neighbour list vector, computes (l_i.l_i) - (l_i.l_j). 154 | See Rabani et al. J. Chem. Phys. 1997 doi:https://doi.org/10.1063/1.474927 155 | Eqn. 8 for details. 156 | 157 | """ 158 | if nlist_i.vectors.shape != nlist_j.vectors.shape: 159 | raise ValueError( 160 | f"NeighbourList vector shapes are not equal: {nlist_i.vectors.shape} != {nlist_j.vectors.shape}" 161 | ) 162 | return np.einsum("ij,ij->i", nlist_i.vectors, nlist_i.vectors) - np.einsum( 163 | "ij,ij->i", nlist_i.vectors, nlist_j.vectors 164 | ) 165 | 166 | 167 | def neighbour_list_n_in(nlist_i: NeighbourList, nlist_j: NeighbourList) -> np.ndarray: 168 | """ 169 | Compute n^in between two NeighbourList object. 170 | 171 | Args: 172 | nlist_i (NeighbourList): A NeighbourList object for neighbour lists at time 0. 173 | nlist_j (NeighbourList): A NeighbourList object for neighbour lists at time t. 174 | 175 | Returns: 176 | (np.ndarray(float)): A 1D array of normalised correlation terms. 177 | 178 | Raises: 179 | ValueError: If the two NeighbourList objects have different numbers 180 | of lengths of neighbour list vectors. 181 | 182 | Note: 183 | For each neighbour list vector, computes (l_j.l_j) - (l_i.l_j). 184 | See Rabani et al. J. Chem. Phys. 1997 doi:https://doi.org/10.1063/1.474927 185 | Eqn. 9 for details. 186 | 187 | """ 188 | if nlist_i.vectors.shape != nlist_j.vectors.shape: 189 | raise ValueError( 190 | f"NeighbourList vector shapes are not equal: {nlist_i.vectors.shape} != {nlist_j.vectors.shape}" 191 | ) 192 | return np.einsum("ij,ij->i", nlist_j.vectors, nlist_j.vectors) - np.einsum( 193 | "ij,ij->i", nlist_i.vectors, nlist_j.vectors 194 | ) 195 | -------------------------------------------------------------------------------- /vasppy/optics.py: -------------------------------------------------------------------------------- 1 | """ 2 | functions for working with optical properties from vasprun.xml 3 | """ 4 | 5 | from math import pi 6 | import numpy as np 7 | from scipy.constants import physical_constants, speed_of_light # type: ignore 8 | import matplotlib.pyplot as plt # type: ignore 9 | 10 | eV_to_recip_cm = 1.0 / ( 11 | physical_constants["Planck constant in eV s"][0] * speed_of_light * 1e2 12 | ) 13 | 14 | 15 | def matrix_eigvals(matrix): 16 | """Calculate the eigenvalues of a matrix. 17 | 18 | Args: 19 | matrix (np.array): The matrix to diagonalise. 20 | 21 | Returns: 22 | (np.array): Array of the matrix eigenvalues. 23 | """ 24 | eigvals, eigvecs = np.linalg.eig(matrix) 25 | return eigvals 26 | 27 | 28 | def to_matrix(xx, yy, zz, xy, yz, xz): 29 | """Convert a list of matrix components to a symmetric 3x3 matrix. 30 | 31 | Inputs should be in the order xx, yy, zz, xy, yz, xz. 32 | 33 | Args: 34 | xx (float): xx component of the matrix. 35 | yy (float): yy component of the matrix. 36 | zz (float): zz component of the matrix. 37 | xy (float): xy component of the matrix. 38 | yz (float): yz component of the matrix. 39 | xz (float): xz component of the matrix. 40 | 41 | Returns: 42 | (np.array): The matrix, as a 3x3 numpy array. 43 | """ 44 | matrix = np.array([[xx, xy, xz], [xy, yy, yz], [xz, yz, zz]]) 45 | return matrix 46 | 47 | 48 | def plot_dielectric_functions(dielectric, ax=None): 49 | real_dielectric = parse_dielectric_data(dielectric[1]) 50 | imag_dielectric = parse_dielectric_data(dielectric[2]) 51 | if ax is None: 52 | fig, ax = plt.subplots(1, 1, figsize=(6.0, 3.0)) 53 | else: 54 | fig = None 55 | ax.plot( 56 | dielectric[0], np.mean(real_dielectric, axis=1), "-", zorder=2 57 | ) # better to pass in v.dielectric 58 | ax.plot(dielectric[0], np.mean(imag_dielectric, axis=1), "-", zorder=2) 59 | ax.set_xlim([0, 8]) 60 | ax.set_ylim([0, 5]) 61 | return fig 62 | 63 | 64 | def parse_dielectric_data(data): 65 | """Convert a set of 2D vasprun formatted dielectric data to 66 | the eigenvalues of each corresponding 3x3 symmetric numpy matrices. 67 | 68 | Args: 69 | data (list): length N list of dielectric data. Each entry should be 70 | a list of ``[xx, yy, zz, xy, xz, yz ]`` dielectric 71 | tensor elements. 72 | 73 | Returns: 74 | (np.array): a Nx3 numpy array. Each row contains the eigenvalues 75 | for the corresponding row in `data`. 76 | """ 77 | return np.array([matrix_eigvals(to_matrix(*e)) for e in data]) 78 | 79 | 80 | def absorption_coefficient(dielectric): 81 | """Calculate the optical absorption coefficient from an input set of 82 | pymatgen vasprun dielectric constant data. 83 | 84 | Args: 85 | dielectric (list): A list containing the dielectric response function 86 | in the pymatgen vasprun format. 87 | 88 | | element 0: list of energies 89 | | element 1: real dielectric tensors, in ``[xx, yy, zz, xy, xz, yz]`` format. 90 | | element 2: imaginary dielectric tensors, in ``[xx, yy, zz, xy, xz, yz]`` format. 91 | 92 | Returns: 93 | (np.array): absorption coefficient using eV as frequency units (cm^-1). 94 | 95 | Notes: 96 | The absorption coefficient is calculated as 97 | 98 | .. math:: \\alpha = \\frac{2\\sqrt{2} \\pi}{\\lambda} \\sqrt{-\\epsilon_1+\\sqrt{\\epsilon_1^2+\\epsilon_2^2}} 99 | 100 | """ 101 | energies_in_eV = np.array(dielectric[0]) 102 | real_dielectric = parse_dielectric_data(dielectric[1]) 103 | imag_dielectric = parse_dielectric_data(dielectric[2]) 104 | epsilon_1 = np.mean(real_dielectric, axis=1) 105 | epsilon_2 = np.mean(imag_dielectric, axis=1) 106 | return ( 107 | 2.0 108 | * np.sqrt(2.0) 109 | * pi 110 | * eV_to_recip_cm 111 | * energies_in_eV 112 | * np.sqrt(-epsilon_1 + np.sqrt(epsilon_1**2 + epsilon_2**2)) 113 | ) 114 | -------------------------------------------------------------------------------- /vasppy/outcar.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import re 3 | from pymatgen.io.vasp.outputs import Outcar # type: ignore 4 | 5 | 6 | def reciprocal_lattice_from_outcar( 7 | filename, 8 | ): # from https://github.com/MaterialsDiscovery/PyChemia 9 | """ 10 | Finds and returns the reciprocal lattice vectors, if more than 11 | one set present, it just returns the last one. 12 | Args: 13 | filename (Str): The name of the outcar file to be read 14 | 15 | Returns: 16 | List(Float): The reciprocal lattice vectors. 17 | """ 18 | outcar = open(filename, "r").read() 19 | # just keeping the last component 20 | recLat = re.findall(r"reciprocal\s*lattice\s*vectors\s*([-.\s\d]*)", outcar)[-1] 21 | recLat = recLat.split() 22 | recLat = np.array(recLat, dtype=float) 23 | # up to now I have, both direct and rec. lattices (3+3=6 columns) 24 | recLat.shape = (3, 6) 25 | recLat = recLat[:, 3:] 26 | return recLat 27 | 28 | 29 | def final_energy_from_outcar(filename="OUTCAR"): 30 | """ 31 | Finds and returns the energy from a VASP OUTCAR file, by searching for the last `energy(sigma->0)` entry. 32 | 33 | Args: 34 | filename (Str, optional): OUTCAR filename. Defaults to 'OUTCAR'. 35 | 36 | Returns: 37 | (Float): The last energy read from the OUTCAR file. 38 | """ 39 | with open(filename) as f: 40 | outcar = f.read() 41 | energy_re = re.compile(r"energy\(sigma->0\) =\s+([-\d\.]+)") 42 | energy = float(energy_re.findall(outcar)[-1]) 43 | return energy 44 | 45 | 46 | def vasp_version_from_outcar(filename="OUTCAR"): 47 | """ 48 | Returns the first line from a VASP OUTCAR file, to get the VASP source version string. 49 | 50 | Args: 51 | filename (Str, optional): OUTCAR filename. Defaults to 'OUTCAR'. 52 | 53 | Returns: 54 | (Str): The first line read from the OUTCAR file. 55 | """ 56 | with open(filename) as f: 57 | line = f.readline().strip() 58 | return line 59 | 60 | 61 | def potcar_eatom_list_from_outcar(filename="OUTCAR"): 62 | """ 63 | Returns a list of EATOM values for the pseudopotentials used. 64 | 65 | Args: 66 | filename (Str, optional): OUTCAR filename. Defaults to 'OUTCAR'. 67 | 68 | Returns: 69 | (List(Float)): A list of EATOM values, in the order they appear in the OUTCAR. 70 | """ 71 | with open(filename) as f: 72 | outcar = f.read() 73 | eatom_re = re.compile(r"energy of atom\s+\d+\s+EATOM=\s*([-\d\.]+)") 74 | eatom = [float(e) for e in eatom_re.findall(outcar)] 75 | return eatom 76 | 77 | 78 | def fermi_energy_from_outcar(filename="OUTCAR"): 79 | """Finds and returns the Fermi energy. 80 | 81 | Args: 82 | filename (:obj:'str', optional): the name of the ``OUTCAR`` file to be read. Default is `OUTCAR`. 83 | 84 | Returns: 85 | (Float): The Fermi energy as found in the ``OUTCAR`` file. 86 | 87 | """ 88 | outcar = open(filename, "r").read() 89 | # returns a match object 90 | fermi_energy = re.search(r"E-fermi\s*:\s*([-.\d]*)", outcar) 91 | # take the first group - group(0) contains entire match 92 | fermi_energy = float(fermi_energy.group(1)) 93 | return fermi_energy 94 | 95 | 96 | def forces_from_outcar(filename="OUTCAR"): 97 | """Finds and returns forces from the OUTCAR file. 98 | 99 | Args: 100 | filename (:obj:'str', optional): the name of the ``OUTCAR`` file to be read. Default is `OUTCAR`. 101 | 102 | Returns: 103 | (np.array): The force as found in the ``OUTCAR`` file, as a NSTEPS x NIONS x 3 numpy array. 104 | 105 | """ 106 | outcar = Outcar(filename) 107 | forces = outcar.read_table_pattern( 108 | header_pattern=r"\sPOSITION\s+TOTAL-FORCE \(eV/Angst\)\n\s-+", 109 | row_pattern=r"\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+\s+([+-]?\d+\.\d+)\s+([+-]?\d+\.\d+)\s+([+-]?\d+\.\d+)", 110 | footer_pattern=r"\s--+", 111 | postprocess=lambda x: float(x), 112 | last_one_only=False, 113 | ) 114 | return np.array(forces) 115 | 116 | 117 | def coords_from_outcar(filename="OUTCAR"): 118 | """Finds and returns Cartesian coordinates from the OUTCAR file. 119 | 120 | Args: 121 | filename (:obj:'str', optional): the name of the ``OUTCAR`` file to be read. Default is `OUTCAR`. 122 | 123 | Returns: 124 | (np.array): The Cartesian coordinates as found in the ``OUTCAR`` file, as a NSTEPS x NIONS x 3 numpy array. 125 | 126 | """ 127 | outcar = Outcar(filename) 128 | coords = outcar.read_table_pattern( 129 | header_pattern=r"\sPOSITION\s+TOTAL-FORCE \(eV/Angst\)\n\s-+", 130 | row_pattern=r"\s+[+-]?(\d+\.\d+)\s+[+-]?(\d+\.\d+)\s+[+-]?(\d+\.\d+)\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+", 131 | footer_pattern=r"\s--+", 132 | postprocess=lambda x: float(x), 133 | last_one_only=False, 134 | ) 135 | return np.array(coords) 136 | -------------------------------------------------------------------------------- /vasppy/pimaim.py: -------------------------------------------------------------------------------- 1 | # routines for interacting with PIMAIM data / filetypes 2 | 3 | import numpy as np 4 | from vasppy.poscar import Poscar 5 | from vasppy.cell import Cell 6 | from vasppy.units import angstrom_to_bohr 7 | 8 | 9 | def lines_to_numpy_array(data): 10 | return np.array([[float(s) for s in line.split()] for line in data]) 11 | 12 | 13 | def read_restart_file(filename, number_of_atoms): 14 | with open(filename, "r") as f: 15 | file_data = f.readlines() 16 | 17 | cr_dump_log, vel_dump_log, chg_dump_log, full_dump_log = [ 18 | (line.strip() == "T") for line in file_data[:4] 19 | ] 20 | # this assumes coordinates, velocities, and dipoles are all present. 21 | # not sure what happens if atoms have qudrupoles, etc. 22 | coordinates = ( 23 | lines_to_numpy_array(file_data[4 : 4 + number_of_atoms]) * angstrom_to_bohr 24 | ) 25 | if vel_dump_log: 26 | velocities = lines_to_numpy_array( 27 | file_data[4 + number_of_atoms : 4 + number_of_atoms * 2] 28 | ) 29 | else: 30 | velocities = None 31 | if chg_dump_log: 32 | dipoles = lines_to_numpy_array( 33 | file_data[4 + number_of_atoms * 2 : 4 + number_of_atoms * 3] 34 | ) 35 | else: 36 | dipoles = None 37 | cell_matrix = lines_to_numpy_array(file_data[-6:-3]) 38 | cell_lengths = lines_to_numpy_array(file_data[-3:]) * angstrom_to_bohr 39 | full_cell_matrix = cell_matrix * cell_lengths 40 | 41 | return coordinates, velocities, dipoles, full_cell_matrix, cell_lengths 42 | 43 | 44 | def get_cart_coords_from_pimaim_restart(coordinates, full_cell_matrix, cell_lengths): 45 | return np.dot( 46 | coordinates, np.array([full_cell_matrix[i] / cell_lengths[i] for i in range(3)]) 47 | ) 48 | 49 | 50 | def poscar_from_pimaim_restart(filename, atom_numbers, atom_labels): 51 | number_of_atoms = sum(atom_numbers) 52 | ( 53 | coordinates, 54 | velocities, 55 | dipoles, 56 | full_cell_matrix, 57 | cell_lengths, 58 | ) = read_restart_file(filename, number_of_atoms) 59 | poscar = Poscar() 60 | full_cell_matrix = full_cell_matrix.transpose() 61 | coordinates = get_cart_coords_from_pimaim_restart( 62 | coordinates, full_cell_matrix, cell_lengths 63 | ) 64 | poscar.cell = Cell(full_cell_matrix) 65 | poscar.atoms = atom_labels 66 | poscar.atom_numbers = atom_numbers 67 | poscar.coordinate_type = "Direct" 68 | poscar.coordinates = poscar.cell.cartesian_to_fractional_coordinates(coordinates) 69 | return poscar 70 | -------------------------------------------------------------------------------- /vasppy/polyhedron.py: -------------------------------------------------------------------------------- 1 | class Polyhedron: 2 | def __init__(self, vertices, cell, inside_point, cutoff): 3 | self.vertices = vertices 4 | self.cell = cell 5 | self.inside_point = inside_point 6 | self.vertices = [self.cell.nearest_image(inside_point, p) for p in vertices] 7 | self.inside_point = self.centre() # improved inside_point 8 | 9 | def centre(self): 10 | return sum(self.vertices) / len(self.vertices) 11 | 12 | def print_points(self): 13 | for point in self.vertices: 14 | print(point.dot(self.cell.matrix)) 15 | -------------------------------------------------------------------------------- /vasppy/scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjmorgan/vasppy/f913b1bd034e4b106bb83e13c0f4c5a0e09151b7/vasppy/scripts/__init__.py -------------------------------------------------------------------------------- /vasppy/scripts/check_species.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.poscar import Poscar 4 | from vasppy.summary import potcar_spec, potcar_sets 5 | import argparse 6 | 7 | """ 8 | A command line utility for testing species consistency between a VASP POSCAR and POTCAR pair of files. Species are considered consistent if the species labels used in the POSCAR file match the start of the pseudopotential labels in the POTCAR file, in order. e.g. a POSCAR that contains `Ti O` will match a POTCAR that contains `Ti_pv O`. If any species labels do not match the script raises an AttributeError. 9 | 10 | The `-p` flag will check that all the pseudopotentials in the POTCAR file belong to a specific pseudopotential set. 11 | """ 12 | 13 | 14 | def parse_command_line_arguments(): 15 | parser = argparse.ArgumentParser( 16 | description="Check species consistency between a VASP POSCAR file and a POTCAR file." 17 | ) 18 | parser.add_argument( 19 | "poscar", 20 | help="filename of the VASP POSCAR to be processed", 21 | nargs="?", 22 | default="POSCAR", 23 | ) 24 | parser.add_argument( 25 | "potcar", 26 | help="filename of the VASP POTCAR to be processed", 27 | nargs="?", 28 | default="POTCAR", 29 | ) 30 | parser.add_argument( 31 | "-p", 32 | "--ppset", 33 | help="check whether the POTCAR pseudopotentials belong to a specific pseudopotential set", 34 | choices=potcar_sets, 35 | ) 36 | return parser.parse_args() 37 | 38 | 39 | def main(): 40 | args = parse_command_line_arguments() 41 | poscar = Poscar.from_file(args.poscar) 42 | potcars = potcar_spec(args.potcar) 43 | for i, (species, potcar) in enumerate(zip(poscar.atoms, potcars, strict=True), 1): 44 | matching_potcar = potcar.startswith(species) 45 | if not matching_potcar: 46 | raise AttributeError( 47 | "Species {} mismatch:\nPOSCAR contains {}\nPOTCAR contains {}".format( 48 | i, species, potcar 49 | ) 50 | ) 51 | if args.ppset: 52 | this_ppset = potcars[potcar] 53 | if args.ppset != this_ppset: 54 | raise AttributeError( 55 | "Pseudopotential set mismatch: {}".format(potcars.values()) 56 | ) 57 | 58 | 59 | if __name__ == "__main__": 60 | main() 61 | -------------------------------------------------------------------------------- /vasppy/scripts/checkforce.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import argparse 4 | import re 5 | import numpy as np 6 | from dataclasses import dataclass, field 7 | from typing import Union 8 | 9 | forces_re = re.compile( 10 | r"\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+\s+[+-]?\d+\.\d+\s+([+-]?\d+\.\d+)\s+([+-]?\d+\.\d+)\s+([+-]?\d+\.\d+)" 11 | ) 12 | 13 | 14 | @dataclass 15 | class ForcesData: 16 | forces: Union[list, np.ndarray] = field(repr=False) 17 | convergence: float 18 | number_of_ions: int = field(init=False) 19 | mean_excess_force: float = field(init=False) 20 | max_force: float = field(init=False) 21 | n_not_converged: int = field(init=False) 22 | 23 | def __post_init__(self): 24 | if isinstance(self.forces, list): 25 | self.forces = np.array(self.forces) 26 | self.number_of_ions = self.forces.shape[0] 27 | force_magnitude = np.sqrt(np.sum(self.forces**2, axis=1)) 28 | self.mean_excess_force = ( 29 | np.where( 30 | force_magnitude > self.convergence, 31 | force_magnitude - self.convergence, 32 | 0, 33 | ).sum() 34 | / self.number_of_ions 35 | ) 36 | self.n_not_converged = np.sum(force_magnitude > self.convergence) 37 | self.max_force = force_magnitude.max() 38 | 39 | def print_forces(self): 40 | for theseforces in self.forces: 41 | output_str = [f" {force: .6f}" for force in theseforces] 42 | for force in theseforces: 43 | if abs(force) > self.convergence: 44 | output_str.append(" ****") 45 | else: 46 | output_str.append(" conv") 47 | force_norm = np.linalg.norm(theseforces) 48 | output_str.append(f" {force_norm:.6f}") 49 | if np.linalg.norm(force_norm) > self.convergence: 50 | output_str.append(" ****") 51 | else: 52 | output_str.append(" conv") 53 | print("".join(output_str)) 54 | 55 | 56 | def parse_args(): 57 | parser = argparse.ArgumentParser( 58 | description="Checks for convergence of geometry optimisations in VASP" 59 | ) 60 | parser.add_argument( 61 | "-o", 62 | "--outcar", 63 | type=str, 64 | default="OUTCAR", 65 | help='The filepath of the OUTCAR file to be parsed. Defaule is "OUTCAR")', 66 | ) 67 | parser.add_argument( 68 | "-c", 69 | "--convergence", 70 | type=float, 71 | help="Set force convergence. Default is to read the convergence from the OUTCAR file.", 72 | ) 73 | parser.add_argument( 74 | "-v", 75 | "--verbose", 76 | action="store_true", 77 | help="Verbose output. Show convergence status for all atoms.", 78 | ) 79 | parser.add_argument("-w", "--warn", action="store_true", help="Print warnings.") 80 | args = parser.parse_args() 81 | return args 82 | 83 | 84 | def get_forces_data(outcar_filename="OUTCAR", convergence=None, warn=False): 85 | """Parse an OUTCAR file and return forces data, includig various summary statistics. 86 | 87 | args: 88 | outcar_filename (optional, `str`): OUTCAR filename. Default is "OUTCAR". 89 | convergence (optional, `str`): Optionally set the forces convergence threshold. 90 | Default is to read from the OUTCAR file. 91 | warn (optional, `bool`): Optionally warn if the OUTCAR file appears to be incomplete. 92 | 93 | returns: 94 | ForcesData 95 | 96 | """ 97 | with open(outcar_filename, "r") as f: 98 | outcar = f.read() 99 | 100 | number_of_ions_re = re.compile(r"NIONS = \s+([\d]+)") 101 | try: 102 | number_of_ions = int(number_of_ions_re.findall(outcar)[0]) 103 | except IndexError as exc: 104 | raise ValueError("Unable to read NIONS.") from exc 105 | except: 106 | raise 107 | if not convergence: 108 | convergence_re = re.compile(r"EDIFFG = -([\d\.E-]+)") 109 | try: 110 | convergence = float(convergence_re.findall(outcar)[0]) 111 | except IndexError as exc: 112 | raise ValueError("Unable to read EDIFFG.") from exc 113 | except: 114 | raise 115 | 116 | # find force output block positions 117 | forces_block_start = [] 118 | forces_header_re = re.compile("\sPOSITION\s+TOTAL-FORCE \(eV/Angst\)") 119 | for i, line in enumerate(outcar.split("\n")): 120 | if forces_header_re.search(line): 121 | forces_block_start.append(i) 122 | if not forces_block_start: 123 | raise ValueError("No FORCES blocks found.") 124 | # Ideally we want the most recent complete block of forces data. 125 | most_recent_block_start = forces_block_start[-1] + 2 126 | forces_lines = outcar.split("\n")[ 127 | most_recent_block_start : most_recent_block_start + number_of_ions 128 | ] 129 | if not forces_block_is_well_formed(forces_lines): 130 | # If the most recent forces block is ill-formed, try to parse the previous block. 131 | if warn: 132 | print( 133 | "The last FORCES block is not well-formed. Trying to parse the preceeding block." 134 | ) 135 | next_most_recent_block_start = forces_block_start[-2] + 2 136 | forces_lines = outcar.split("\n")[ 137 | next_most_recent_block_start : next_most_recent_block_start + number_of_ions 138 | ] 139 | if not forces_block_is_well_formed(forces_lines): 140 | # If the last two forces blocks are ill-formed, we assume the input file is mis-formatted. 141 | raise Exception( 142 | "The last two FORCES blocks are not well-formed. Your input might be mis-formatted." 143 | ) 144 | forces = [] 145 | for line in forces_lines: 146 | forces.append([float(s) for s in line.split()[-3:]]) 147 | forces_data = ForcesData(forces=forces, convergence=convergence) 148 | return forces_data 149 | 150 | 151 | def forces_block_is_well_formed(forces_lines): 152 | return all(forces_re.match(line) for line in forces_lines) 153 | 154 | 155 | def main(): 156 | args = parse_args() 157 | forces_data = get_forces_data( 158 | outcar_filename=args.outcar, convergence=args.convergence, warn=args.warn 159 | ) 160 | if args.verbose: 161 | forces_data.print_forces() 162 | print() 163 | print(f"remainder: {forces_data.mean_excess_force:.6f}") 164 | print(f"maximum: {forces_data.max_force:.6f}") 165 | print(f"non-opt: {forces_data.n_not_converged} / {forces_data.number_of_ions}") 166 | 167 | 168 | if __name__ == "__main__": 169 | main() 170 | -------------------------------------------------------------------------------- /vasppy/scripts/convergence_testing.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import numpy as np 4 | from pymatgen.core import Structure # type: ignore 5 | from pymatgen.io.vasp import Incar, Potcar # type: ignore 6 | from vasppy.kpoints import get_convergence_testing_kspacing 7 | 8 | def parse_args() -> argparse.Namespace: 9 | parser = argparse.ArgumentParser(description='Generate a series of VASP inputs for convergence testing. At minimum, this requires a template INCAR and the geometry of the system (a POSCAR).') 10 | parser.add_argument('-i', '--incar', required=True, help='Specify the template INCAR.') 11 | parser.add_argument('-p', '--poscar', required=True, help='Specify the geometry of the system (POSCAR).') 12 | parser.add_argument('-e', '--encut', nargs=3, default=(100, 700, 50), help='Set the upper/lower bounds and step size for the basis set size (ENCUT). Defaults to 100 700 50.') 13 | parser.add_argument('-k', '--kspacing', nargs=3, default=(0.1, 0.8, 0.02), help='Set the upper/lower bounds and step size for the minimum allowed distance between k-points (KSPACING). Defaults to 0.1 0.8 0.02') 14 | parser.add_argument('-d', '--directory', nargs='?', default='./convergence_testing', help='Specify the directory in which to place the generated VASP inputs. Defaults to ./convergence_testing.') 15 | parser.add_argument('--base-encut', nargs='?', default=400, help='Set the value of ENCUT for the KSPACING convergence tests. Defaults to 400.') 16 | parser.add_argument('--base-kspacing', nargs='?', default=0.3, help='Set the value of KSPACING for the ENCUT convergence tests. Defaults to 0.3.') 17 | parser.add_argument('--pseudopotentials', nargs='+', default=None, help='Specify the pseudopotentials (POTCARs) to be used e.g. Li_sv Mn_pv O. Defaults to None i.e. no POTCARs will be written. This functionality requires Pymatgen to be set up for VASP POTCARs.') 18 | args = parser.parse_args() 19 | 20 | return args 21 | 22 | def main() -> None: 23 | args = parse_args() 24 | 25 | structure = Structure.from_file(args.poscar) 26 | reciprocal_lattice_vectors = structure.lattice.reciprocal_lattice_crystallographic.matrix 27 | kspacing_min, kspacing_max, step = args.kspacing 28 | kspacing = get_convergence_testing_kspacing(reciprocal_lattice_vectors, (kspacing_min, kspacing_max), step) 29 | 30 | encut_min, encut_max, step = args.encut 31 | encut = np.arange(encut_min, encut_max + step, step) 32 | 33 | base_incar_params = Incar.from_file(args.incar).as_dict() 34 | 35 | os.mkdir(args.directory) 36 | os.mkdir(args.directory + '/ENCUT') 37 | os.mkdir(args.directory + '/KSPACING') 38 | 39 | if args.pseudopotentials is not None: 40 | potcar = Potcar(args.pseudopotentials) 41 | 42 | for energy_cutoff in encut: 43 | path = args.directory + '/ENCUT' + f'/{energy_cutoff}' 44 | os.mkdir(path) 45 | 46 | incar_params = base_incar_params.copy() 47 | incar_params['ENCUT'] = energy_cutoff 48 | incar_params['KSPACING'] = args.base_kspacing 49 | incar = Incar.from_dict(incar_params) 50 | 51 | incar.write_file(path + '/INCAR') 52 | structure.to(fmt='poscar', filename=path + '/POSCAR') 53 | if args.pseudopotentials is not None: 54 | potcar.write_file(path + '/POTCAR') 55 | 56 | for minimum_distance in kspacing: 57 | path = args.directory + '/KSPACING' + f'/{minimum_distance}' 58 | os.mkdir(path) 59 | 60 | incar_params = base_incar_params.copy() 61 | incar_params['KSPACING'] = minimum_distance 62 | incar_params['ENCUT'] = args.base_encut 63 | incar = Incar.from_dict(incar_params) 64 | 65 | incar.write_file(path + '/INCAR') 66 | structure.to(fmt='poscar', filename=path + '/POSCAR') 67 | if args.pseudopotentials is not None: 68 | potcar.write_file(path + '/POTCAR') 69 | 70 | if __name__ == '__main__': 71 | main() 72 | -------------------------------------------------------------------------------- /vasppy/scripts/effective_mass.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy import procar 4 | from vasppy.outcar import reciprocal_lattice_from_outcar 5 | import argparse 6 | 7 | 8 | def minimum_length(nmin): 9 | class MinimumLength(argparse.Action): 10 | def __call__(self, parser, args, values, option_string=None): 11 | if not nmin <= len(values): 12 | msg = 'argument "{f}" requires at least {nmin} arguments'.format( 13 | f=self.dest, nmin=nmin 14 | ) 15 | raise argparse.ArgumentError(self, msg) 16 | setattr(args, self.dest, values) 17 | 18 | return MinimumLength 19 | 20 | 21 | def main(): 22 | parser = argparse.ArgumentParser( 23 | description="Calculate an effective mass from a VASP PROCAR using a fitted quadratic" 24 | ) 25 | parser.add_argument( 26 | "-k", 27 | "--k-points", 28 | help="index of k-points for calculating effective mass", 29 | nargs="+", 30 | type=int, 31 | required=True, 32 | action=minimum_length(2), 33 | ) 34 | parser.add_argument( 35 | "-b", 36 | "--band-index", 37 | help="index of band for calculating effective mass", 38 | type=int, 39 | required=True, 40 | ) 41 | parser.add_argument( 42 | "-f", 43 | "--procar", 44 | help="PROCAR filename (default PROCAR)", 45 | type=str, 46 | default="PROCAR", 47 | ) 48 | parser.add_argument("-v", "--verbose", help="Verbose output", action="store_true") 49 | parser.add_argument( 50 | "-o", 51 | "--outcar", 52 | help="OUTCAR filename (default OUTCAR)", 53 | type=str, 54 | default="OUTCAR", 55 | ) 56 | parser.add_argument( 57 | "-s", 58 | "--spin", 59 | help="select spin channel (default 1 / non-spin-polarised)", 60 | type=int, 61 | default="1", 62 | ) 63 | args = parser.parse_args() 64 | 65 | reciprocal_lattice = reciprocal_lattice_from_outcar( 66 | "OUTCAR" 67 | ) # Move reading the reciprocal lattice to procar.py 68 | 69 | pcar = procar.Procar() 70 | pcar.read_from_file(args.procar) 71 | effective_mass = pcar.effective_mass_calc( 72 | k_point_indices=args.k_points, 73 | band_index=args.band_index, 74 | reciprocal_lattice=reciprocal_lattice, 75 | spin=args.spin, 76 | printing=args.verbose, 77 | ) 78 | print(effective_mass) 79 | 80 | 81 | if __name__ == "__main__": 82 | main() 83 | -------------------------------------------------------------------------------- /vasppy/scripts/fat_bands.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy import procar 4 | from vasppy.outcar import reciprocal_lattice_from_outcar 5 | import argparse 6 | 7 | # def x_axis( cartesian_k_points ): 8 | # if cartesian_k_points is not None: 9 | # x_axis = [ 0.0 ] 10 | # for i in range( 1, len(cartesian_k_points) ): 11 | # d = cartesian_k_points[i - 1] - cartesian_k_points[i] 12 | # d = np.sqrt( np.dot( d, d) ) 13 | # x_axis.append( d + x_axis[-1] ) 14 | # x_axis = np.array( x_axis ) 15 | # else: 16 | # x_axis = np.arange( len( cartesian_k_points ) ) 17 | # return x_axis 18 | 19 | 20 | def orbitals_with_l(l): 21 | to_return = { 22 | "s": [0], 23 | "p": [1, 2, 3], 24 | "d": [4, 5, 6, 7, 8], 25 | "f": [9, 10, 11, 12, 13], 26 | "all": None, 27 | } 28 | return to_return[l] 29 | 30 | 31 | def main(): 32 | parser = argparse.ArgumentParser() 33 | parser.add_argument( 34 | "-i", 35 | "--ions", 36 | help="ion indices for band projection (default: sum over all ions)", 37 | nargs="+", 38 | type=int, 39 | ) 40 | parser.add_argument( 41 | "-s", 42 | "--spins", 43 | help="spin indices for band projection (default [ 1 ])", 44 | nargs="+", 45 | type=int, 46 | default=[1], 47 | ) 48 | parser.add_argument( 49 | "-o", 50 | "--orbitals", 51 | help="orbital indices for band projection (default: sum over all orbitals)", 52 | nargs="+", 53 | type=int, 54 | ) 55 | parser.add_argument( 56 | "-e", 57 | "--efermi", 58 | help="set fermi energy as reference for energy scale", 59 | type=float, 60 | default=0.0, 61 | ) 62 | parser.add_argument( 63 | "-l", 64 | "--l-angular-momentum", 65 | help="select all orbitals with angular momentum L for band projection. This supercedes the --orbitals option", 66 | choices=["s", "p", "d", "f", "all"], 67 | ) 68 | parser.add_argument( 69 | "-f", 70 | "--procar", 71 | help="PROCAR filename (default PROCAR)", 72 | type=str, 73 | default="PROCAR", 74 | ) 75 | parser.add_argument( 76 | "--scaling", 77 | help="Energy scaling for band widths (default 0.2 eV)", 78 | type=float, 79 | default=0.2, 80 | ) 81 | parser.add_argument( 82 | "-x", 83 | "--xscaling", 84 | help="Automatic scaling of x-axis using reciprocal lattice vectors read from OUTCAR", 85 | action="store_true", 86 | default=False, 87 | ) 88 | args = parser.parse_args() 89 | 90 | if args.l_angular_momentum: 91 | args.orbitals = orbitals_with_l(args.l_angular_momentum) 92 | 93 | if args.xscaling: 94 | reciprocal_lattice = reciprocal_lattice_from_outcar( 95 | "OUTCAR" 96 | ) # Move reading the reciprocal lattice to procar.py 97 | else: 98 | reciprocal_lattice = None 99 | 100 | pcar = procar.Procar() 101 | pcar.read_from_file(args.procar) 102 | pcar.print_weighted_band_structure( 103 | spins=args.spins, 104 | ions=args.ions, 105 | orbitals=args.orbitals, 106 | scaling=args.scaling, 107 | e_fermi=args.efermi, 108 | reciprocal_lattice=reciprocal_lattice, 109 | ) 110 | 111 | 112 | if __name__ == "__main__": 113 | main() 114 | -------------------------------------------------------------------------------- /vasppy/scripts/murnfit.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | # Adapted from http://kitchingroup.cheme.cmu.edu/blog/2013/02/18/Nonlinear-curve-fitting/ 4 | 5 | import numpy as np # type: ignore 6 | import pandas as pd # type: ignore 7 | from scipy.optimize import leastsq # type: ignore 8 | import argparse 9 | import warnings 10 | 11 | from pymatgen.io.vasp import Vasprun # type: ignore 12 | from pymatgen.io.vasp.outputs import UnconvergedVASPWarning # type: ignore 13 | 14 | import matplotlib # type: ignore 15 | import matplotlib.pyplot as plt # type: ignore 16 | 17 | from vasppy.poscar import Poscar 18 | from vasppy.summary import find_vasp_calculations 19 | from vasppy.utils import match_filename 20 | 21 | warnings.filterwarnings("ignore", category=UserWarning, module="pymatgen") 22 | matplotlib.use("agg") 23 | 24 | 25 | def parse_args(): 26 | parser = argparse.ArgumentParser( 27 | description="Perform a Murnaghan equation of state fit across VASP subdirectories" 28 | ) 29 | parser.add_argument( 30 | "-p", "--plot", action="store_true", help="generate murn.pdf plot of fit" 31 | ) 32 | parser.add_argument("-v", "--verbose", action="store_true", help="verbose output") 33 | args = parser.parse_args() 34 | return args 35 | 36 | 37 | def read_vasprun(filename): 38 | return Vasprun( 39 | filename, parse_potcar_file=False, parse_dos=False, parse_eigen=False 40 | ) 41 | 42 | 43 | def read_data(verbose=True): 44 | dir_list = find_vasp_calculations() 45 | if not dir_list: 46 | raise ValueError( 47 | "Did not find any subdirectories containing vasprun.xml or vasprun.xml.gz files" 48 | ) 49 | data = [] 50 | for d in dir_list: 51 | converged = True 52 | try: 53 | with warnings.catch_warnings(record=True) as w: 54 | vasprun = read_vasprun(match_filename(d + "vasprun.xml")) 55 | for warning in w: 56 | if isinstance(warning.message, UnconvergedVASPWarning): 57 | converged = False 58 | else: 59 | print(warning.message) 60 | except Exception: 61 | continue 62 | poscar = Poscar.from_file(d + "POSCAR") 63 | data.append( 64 | [ 65 | poscar.scaling, 66 | vasprun.final_structure.volume, 67 | vasprun.final_energy, 68 | converged, 69 | ] 70 | ) 71 | column_titles = ["scaling", "volume", "energy", "converged"] 72 | df = pd.DataFrame(data, columns=column_titles).sort_values(by="scaling") 73 | df = df.reset_index(drop=True) 74 | df["scaling_factor"] = df.volume / df.scaling**3 75 | scaling_factor_round = 4 76 | if verbose: 77 | print(df.to_string(index=False)) 78 | if len(set(df.scaling_factor.round(scaling_factor_round))) != 1: 79 | raise ValueError("POSCAR scaling factors and volumes are inconsistent") 80 | return df 81 | 82 | 83 | def murnaghan(vol, e0, b0, bp, v0): 84 | """ 85 | Calculate the energy as a function of volume, using the Murnaghan equation of state 86 | [Murnaghan, Proc. Nat. Acad. Sci. 30, 244 (1944)] 87 | https://en.wikipedia.org/wiki/Murnaghan_equation_of_state 88 | cf. Fu and Ho, Phys. Rev. B 28, 5480 (1983). 89 | 90 | Args: 91 | vol (float): this volume. 92 | e0 (float): energy at the minimum-energy volume, E0. 93 | b0 (float): bulk modulus at the minimum-energy volume, B0. 94 | bp (float): pressure-derivative of the bulk modulus at the minimum-energy volume, B0'. 95 | v0 (float): volume at the minimum-energy volume, V0. 96 | 97 | Returns: 98 | (float): The energy at this volume. 99 | """ 100 | energy = ( 101 | e0 + b0 * vol / bp * (((v0 / vol) ** bp) / (bp - 1) + 1) - v0 * b0 / (bp - 1.0) 102 | ) 103 | return energy 104 | 105 | 106 | def objective(pars, x, y): 107 | err = y - murnaghan(x, *pars) 108 | return err 109 | 110 | 111 | def lstsq_fit(volumes, energies): 112 | e_min = energies.min() 113 | v_min = volumes[np.argwhere(energies == e_min)[0][0]] 114 | x0 = [e_min, 2.0, 10.0, v_min] # initial guess of parameters 115 | plsq = leastsq(objective, x0, args=(volumes, energies)) 116 | return plsq 117 | 118 | 119 | def make_plot(df, fit_params): 120 | v_min = df.volume.min() * 0.99 121 | v_max = df.volume.max() * 1.01 122 | v_fitting = np.linspace(v_min, v_max, num=50) 123 | e_fitting = murnaghan(v_fitting, *fit_params) 124 | plt.figure(figsize=(8.0, 6.0)) 125 | # plot converged data points 126 | loc = df.converged 127 | plt.plot(df[loc].volume, df[loc].energy, "o") 128 | # plot unconverged data points 129 | loc = [not b for b in df.converged] 130 | plt.plot(df[loc].volume, df[loc].energy, "o", c="grey") 131 | # plot fitted equation of state curve 132 | plt.plot(v_fitting, e_fitting, "--") 133 | plt.xlabel(r"volume [$\mathrm{\AA}^3$]") 134 | plt.ylabel(r"energy [eV]") 135 | plt.tight_layout() 136 | plt.savefig("murn.pdf") 137 | 138 | 139 | def fit(verbose=False, plot=False): 140 | df = read_data(verbose=verbose) 141 | e0, b0, bp, v0 = lstsq_fit(np.array(df.volume), np.array(df.energy))[0] 142 | if plot: 143 | make_plot(df, (e0, b0, bp, v0)) 144 | print("E0: {:.4f}".format(e0)) 145 | print("V0: {:.4f}".format(v0)) 146 | print("opt. scaling: {:.5f}".format((v0 / df.scaling_factor.mean()) ** (1 / 3))) 147 | 148 | 149 | def main(): 150 | args = parse_args() 151 | fit(verbose=args.verbose, plot=args.plot) 152 | 153 | 154 | if __name__ == "__main__": 155 | main() 156 | -------------------------------------------------------------------------------- /vasppy/scripts/pimaim_to_poscar.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import numpy as np # type: ignore 4 | import argparse 5 | from vasppy.poscar import Poscar 6 | from vasppy.cell import Cell 7 | from vasppy.pimaim import get_cart_coords_from_pimaim_restart 8 | 9 | 10 | def parse_command_line_arguments(): 11 | parser = argparse.ArgumentParser(description="TODO") 12 | parser.add_argument( 13 | "-l", "--labels", nargs="+", help="labels for each species", required=True 14 | ) 15 | parser.add_argument( 16 | "-n", 17 | "--atom-numbers", 18 | nargs="+", 19 | help="atom numbers for each species", 20 | required=True, 21 | type=int, 22 | ) 23 | args = parser.parse_args() 24 | if len(args.labels) != len(args.atom_numbers): 25 | print("'labels' and 'atom-numbers' require matched argument numbers") 26 | exit() 27 | return args 28 | 29 | 30 | def lines_to_numpy_array(data): 31 | return np.array([[float(s) for s in line.split()] for line in data]) 32 | 33 | 34 | def read_pimaim_restart(filename): 35 | with open(filename, "r") as f: 36 | file_data = f.readlines() 37 | cr_dump_log, vel_dump_log, chg_dump_log, full_dump_log = [ 38 | bool(line.strip()) for line in file_data[:4] 39 | ] 40 | # figure out how many atoms are in this calculation 41 | data_per_line = [len(line.split()) for line in file_data] 42 | number_of_atomic_data_lines = next( 43 | index for index, d in enumerate(data_per_line[4:]) if d == 1 44 | ) 45 | number_of_atomic_data_types = sum([cr_dump_log, vel_dump_log, chg_dump_log]) 46 | number_of_atoms = int(number_of_atomic_data_lines / number_of_atomic_data_types) 47 | # this assumes coordinates, velocities, and dipoles are all present. 48 | # not sure what happens if atoms have qudrupoles, etc. 49 | coordinates = lines_to_numpy_array(file_data[4 : 4 + number_of_atoms]) 50 | velocities = lines_to_numpy_array( 51 | file_data[4 + number_of_atoms : 4 + number_of_atoms * 2] 52 | ) 53 | dipoles = lines_to_numpy_array( 54 | file_data[4 + number_of_atoms * 2 : 4 + number_of_atoms * 3] 55 | ) 56 | cell_matrix = lines_to_numpy_array(file_data[-6:-3]) 57 | cell_lengths = lines_to_numpy_array(file_data[-3:]) 58 | full_cell_matrix = cell_matrix * cell_lengths 59 | return (coordinates, velocities, dipoles, full_cell_matrix, cell_lengths) 60 | 61 | 62 | def main(): 63 | filename = "testout.rst" 64 | args = parse_command_line_arguments() 65 | ( 66 | coordinates, 67 | velocities, 68 | dipoles, 69 | full_cell_matrix, 70 | cell_lengths, 71 | ) = read_pimaim_restart(filename) 72 | assert sum(args.atom_numbers) == len(coordinates) 73 | poscar = Poscar() 74 | full_cell_matrix = full_cell_matrix.transpose() 75 | coordinates = get_cart_coords_from_pimaim_restart( 76 | coordinates, full_cell_matrix, cell_lengths 77 | ) 78 | poscar.cell = Cell(full_cell_matrix) 79 | poscar.atoms = args.labels 80 | poscar.atom_numbers = args.atom_numbers 81 | poscar.coordinate_type = "Cartesian" 82 | poscar.coordinates = coordinates 83 | poscar.output() 84 | 85 | 86 | if __name__ == "__main__": 87 | main() 88 | -------------------------------------------------------------------------------- /vasppy/scripts/pimaim_to_xtl.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import argparse 4 | import vasppy.pimaim 5 | 6 | 7 | def parse_command_line_arguments(): 8 | parser = argparse.ArgumentParser(description="TODO") 9 | parser.add_argument("-f", "--filename", help="PIMAIM restart file filename") 10 | parser.add_argument( 11 | "-l", "--labels", nargs="+", help="labels for each species", required=True 12 | ) 13 | parser.add_argument( 14 | "-n", 15 | "--atom-numbers", 16 | nargs="+", 17 | help="atom numbers for each species", 18 | required=True, 19 | type=int, 20 | ) 21 | args = parser.parse_args() 22 | if len(args.labels) != len(args.atom_numbers): 23 | print("'labels' and 'atom-numbers' require matched argument numbers") 24 | exit() 25 | return args 26 | 27 | 28 | def main(): 29 | args = parse_command_line_arguments() 30 | if args.filename is None: 31 | args.filename = "testout.rst" 32 | poscar = vasppy.pimaim.poscar_from_pimaim_restart( 33 | args.filename, args.atom_numbers, args.labels 34 | ) 35 | poscar.output_as_xtl() 36 | 37 | 38 | if __name__ == "__main__": 39 | main() 40 | -------------------------------------------------------------------------------- /vasppy/scripts/poscar_to_cif.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.poscar import Poscar 4 | import argparse 5 | 6 | 7 | def parse_command_line_arguments(): 8 | # command line arguments 9 | parser = argparse.ArgumentParser( 10 | description="Converts a VASP POSCAR file to the .xtl file format" 11 | ) 12 | parser.add_argument("poscar", help="filename of the VASP POSCAR to be processed") 13 | parser.add_argument( 14 | "-s", 15 | "--symprec", 16 | type=float, 17 | help="Symmetry precision for a symmetrised .cif output", 18 | ) 19 | args = parser.parse_args() 20 | return args 21 | 22 | 23 | def main(): 24 | args = parse_command_line_arguments() 25 | # initialise 26 | poscar = Poscar() 27 | # read POSCAR file 28 | poscar.read_from(args.poscar) 29 | poscar.output_as_cif(args.symprec) 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /vasppy/scripts/poscar_to_pimaim.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.poscar import Poscar 4 | import argparse 5 | 6 | 7 | def parse_command_line_arguments(): 8 | # command line arguments 9 | parser = argparse.ArgumentParser( 10 | description="Converts a VASP POSCAR file to the PIMAIM `restart.dat` format" 11 | ) 12 | parser.add_argument("poscar", help="filename of the VASP POSCAR to be processed") 13 | args = parser.parse_args() 14 | return args 15 | 16 | 17 | def main(): 18 | args = parse_command_line_arguments() 19 | # initialise 20 | poscar = Poscar() 21 | # read POSCAR file 22 | poscar.read_from(args.poscar) 23 | poscar.output_as_pimaim() 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /vasppy/scripts/poscar_to_xtl.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.poscar import Poscar 4 | import argparse 5 | 6 | 7 | def parse_command_line_arguments(): 8 | # command line arguments 9 | parser = argparse.ArgumentParser( 10 | description="Converts a VASP POSCAR file to the .xtl file format" 11 | ) 12 | parser.add_argument("poscar", help="filename of the VASP POSCAR to be processed") 13 | args = parser.parse_args() 14 | return args 15 | 16 | 17 | def main(): 18 | args = parse_command_line_arguments() 19 | # initialise 20 | poscar = Poscar() 21 | # read POSCAR file 22 | poscar.read_from(args.poscar) 23 | poscar.output_as_xtl() 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /vasppy/scripts/potcar_spec.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.summary import potcar_spec 4 | import argparse 5 | 6 | 7 | def parse_command_line_arguments(): 8 | parser = argparse.ArgumentParser( 9 | description="Generate POTCAR specification based on hashing individual pseudopotential strings" 10 | ) 11 | parser.add_argument( 12 | "potcar", 13 | help="filename of the VASP POTCAR to be processed", 14 | nargs="?", 15 | default="POTCAR", 16 | ) 17 | parser.add_argument( 18 | "--hash", 19 | help="return the md5 hashes of the individual pseudopotential strings", 20 | action="store_true", 21 | ) 22 | args = parser.parse_args() 23 | return args 24 | 25 | 26 | def main(): 27 | args = parse_command_line_arguments() 28 | if args.hash: 29 | hashes = {} 30 | for p, md5hash in potcar_spec(args.potcar, return_hashes=True).items(): 31 | hashes[p] = md5hash 32 | for p, ps in potcar_spec(args.potcar).items(): 33 | if args.hash: 34 | print(p, ps, hashes[p]) 35 | else: 36 | print(p, ps) 37 | 38 | 39 | if __name__ == "__main__": 40 | main() 41 | -------------------------------------------------------------------------------- /vasppy/scripts/proc_poscar.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.poscar import Poscar 4 | import argparse 5 | 6 | def parse_command_line_arguments(): 7 | # command line arguments 8 | parser = argparse.ArgumentParser(description="Manipulates VASP POSCAR files") 9 | parser.add_argument("poscar", help="filename of the VASP POSCAR to be processed") 10 | parser.add_argument( 11 | "-l", 12 | "--label", 13 | type=int, 14 | choices=[1, 4], 15 | help="label coordinates with atom name at position {1,4}", 16 | ) 17 | parser.add_argument( 18 | "-c", "--coordinates-only", help="only output coordinates", action="store_true" 19 | ) 20 | parser.add_argument( 21 | "-t", 22 | "--coordinate-type", 23 | type=str, 24 | choices=["c", "cartesian", "d", "direct"], 25 | default="direct", 26 | help="specify coordinate type for output {(c)artesian|(d)irect} [default = (d)irect]", 27 | ) 28 | parser.add_argument( 29 | "-g", "--group", help="group atoms within supercell", action="store_true" 30 | ) 31 | parser.add_argument( 32 | "-s", 33 | "--supercell", 34 | type=int, 35 | nargs=3, 36 | metavar=("h", "k", "l"), 37 | help="construct supercell by replicating (h,k,l) times along [a b c]", 38 | ) 39 | parser.add_argument( 40 | "-b", 41 | "--bohr", 42 | action="store_true", 43 | help="assumes the input file is in Angstrom, and converts everything to bohr", 44 | ) 45 | parser.add_argument( 46 | "-n", 47 | "--number-atoms", 48 | action="store_true", 49 | help="label coordinates with atom number", 50 | ) 51 | parser.add_argument( 52 | "-o", 53 | "--orthorhombic", 54 | action="store_true", 55 | help="force orthorhombic cell matrix (set off-diagonal elements to zero)", 56 | ) 57 | parser.add_argument( 58 | "--scale", 59 | action="store_true", 60 | help="scale the lattice parameters by the scaling factor", 61 | ) 62 | parser.add_argument( 63 | "--selective", 64 | choices=["T", "F"], 65 | help="generate Selective Dynamics POSCAR with all values set to T / F", 66 | ) 67 | args = parser.parse_args() 68 | return args 69 | 70 | 71 | def main(): 72 | args = parse_command_line_arguments() 73 | coordinate_types = { 74 | "d": "Direct", 75 | "direct": "Direct", 76 | "c": "Cartesian", 77 | "cartesian": "Cartesian", 78 | } 79 | coordinate_type = coordinate_types[args.coordinate_type] 80 | # initialise 81 | poscar = Poscar() 82 | # read POSCAR file 83 | poscar.read_from(args.poscar) 84 | if args.scale: 85 | poscar.cell.matrix *= poscar.scaling 86 | poscar.scaling = 1.0 87 | if args.supercell: # generate supercell 88 | if args.group: 89 | # check that if grouping is switched on, we are asking for a supercell that allows a "3D-chequerboard" pattern. 90 | for i, _axis in zip(args.supercell, range(3), strict=True): 91 | if i % 2 == 1 and i > 1: 92 | raise Exception( 93 | "odd supercell expansions != 1 are incompatible with automatic grouping" 94 | ) 95 | poscar = poscar.replicate(*args.supercell, group=args.group) 96 | if args.bohr: 97 | poscar = poscar.in_bohr() 98 | # output to stdout 99 | output_opts = { 100 | "label": args.label, 101 | "numbered": args.number_atoms, 102 | "coordinates_only": args.coordinates_only, 103 | "selective": args.selective, 104 | "orthorhombic": args.orthorhombic, 105 | } 106 | poscar.output(coordinate_type=coordinate_type, opts=output_opts) 107 | 108 | 109 | if __name__ == "__main__": 110 | main() 111 | -------------------------------------------------------------------------------- /vasppy/scripts/r2r2_expansion.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.poscar import Poscar 4 | import argparse 5 | import numpy as np 6 | from typing import Literal 7 | 8 | def parse_command_line_arguments(): 9 | # command line arguments 10 | parser = argparse.ArgumentParser(description="Generate a sqrt(2) x sqrt(2) supercell from a VASP POSCAR") 11 | parser.add_argument("poscar", help="filename of the VASP POSCAR to be processed") 12 | parser.add_argument( 13 | "-a", 14 | "--axis", 15 | choices=['x', 'y', 'z'], 16 | type=str, 17 | help="normal vector for sqrt(2) x sqrt(2) expansion", 18 | required=True, 19 | ) 20 | args = parser.parse_args() 21 | return args 22 | 23 | def sqrt2_by_sqrt2_expansion( 24 | poscar: Poscar, 25 | axis: Literal['x', 'y', 'z'] 26 | ) -> Poscar: 27 | axis_vectors = {'x': [1, 0, 0], 28 | 'y': [0, 1, 0], 29 | 'z': [0, 0, 1]} 30 | poscar.cell.rotate(axis=axis_vectors[axis], theta=np.pi/4) 31 | poscar = poscar.replicate(2, 2, 1) 32 | cc = poscar.cartesian_coordinates() 33 | poscar.cell.matrix = np.diag(poscar.cell.matrix.diagonal()) 34 | poscar.coordinates = cc.dot(np.linalg.inv(poscar.cell.matrix)) 35 | return poscar 36 | 37 | def main(): 38 | args = parse_command_line_arguments() 39 | poscar = Poscar.from_file(args.poscar) 40 | sqrt2_by_sqrt2_expansion( 41 | poscar = poscar, 42 | axis = args.axis 43 | ).output() 44 | 45 | if __name__ == '__main__': 46 | main() 47 | 48 | 49 | -------------------------------------------------------------------------------- /vasppy/scripts/rotate_poscar.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.poscar import Poscar 4 | import math 5 | import argparse 6 | 7 | 8 | def parse_command_line_arguments(): 9 | parser = argparse.ArgumentParser( 10 | description="Rotates the cell lattice in VASP POSCAR files" 11 | ) 12 | parser.add_argument("poscar", help="filename of the VASP POSCAR to be processed") 13 | parser.add_argument( 14 | "-a", 15 | "--axis", 16 | nargs=3, 17 | type=float, 18 | help="vector for rotation axis", 19 | required=True, 20 | ) 21 | parser.add_argument( 22 | "-d", "--degrees", type=int, help="rotation angle in degrees", required=True 23 | ) 24 | args = parser.parse_args() 25 | return args 26 | 27 | 28 | def main(): 29 | args = parse_command_line_arguments() 30 | poscar = Poscar() 31 | poscar.read_from(args.poscar) 32 | theta = math.pi * args.degrees / 180.0 33 | poscar.cell.rotate(args.axis, theta) 34 | poscar.output() 35 | 36 | 37 | if __name__ == "__main__": 38 | main() 39 | -------------------------------------------------------------------------------- /vasppy/scripts/spacegroup.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.poscar import Poscar 4 | from pymatgen.symmetry.analyzer import SpacegroupAnalyzer # type: ignore 5 | import argparse 6 | 7 | 8 | def parse_command_line_arguments(): 9 | # command line arguments 10 | parser = argparse.ArgumentParser( 11 | description="Finds the spacegroup for a VASP POSCAR file" 12 | ) 13 | parser.add_argument("poscar", help="filename of the VASP POSCAR to be processed") 14 | parser.add_argument( 15 | "-s", 16 | "--symprec", 17 | type=float, 18 | help="Precision for symmetry analuysis (defalut=1e-3)", 19 | default=1e-3, 20 | ) 21 | args = parser.parse_args() 22 | return args 23 | 24 | 25 | def main(): 26 | args = parse_command_line_arguments() 27 | # initialise 28 | poscar = ( 29 | Poscar() 30 | ) # this doesn't really need vasppy. Could just use pymatgen to read the POSCAR 31 | # read POSCAR file 32 | poscar.read_from(args.poscar) 33 | structure = poscar.to_pymatgen_structure() 34 | symmetry_analyzer = SpacegroupAnalyzer(structure, symprec=args.symprec) 35 | print(symmetry_analyzer.get_space_group_symbol()) 36 | 37 | 38 | if __name__ == "__main__": 39 | main() 40 | -------------------------------------------------------------------------------- /vasppy/scripts/vasp_grid.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy import grid 4 | import argparse 5 | 6 | 7 | def parse_command_line_arguments(): 8 | # command line arguments 9 | parser = argparse.ArgumentParser( 10 | description="z-projection of a VASP (grid format) file" 11 | ) 12 | parser.add_argument( 13 | "gridfile", help="filename of the VASP (grid format) file to be processed" 14 | ) 15 | parser.add_argument( 16 | "-p", 17 | "--projection", 18 | choices=["x", "y", "z"], 19 | help="output averaged projection perpendicular to [x,y,z]", 20 | ) 21 | parser.add_argument( 22 | "-o", 23 | "--orthorhombic", 24 | help="map grid points onto an orthorhombic (non-space filling) grid", 25 | action="store_true", 26 | ) 27 | args = parser.parse_args() 28 | return args 29 | 30 | 31 | def main(): 32 | args = parse_command_line_arguments() 33 | vgrid = grid.Grid() 34 | vgrid.read_from_filename(args.gridfile) 35 | if args.orthorhombic: 36 | vgrid = vgrid.interpolate_to_orthorhombic_grid(vgrid.dimensions) 37 | if args.projection: 38 | index = grid.Grid.projections[args.projection] 39 | grid_spacing = vgrid.poscar.cell_lengths()[index] / vgrid.dimensions[index] 40 | [ 41 | print(i * grid_spacing, av) 42 | for i, av in enumerate(vgrid.average(normal_axis_label=args.projection)) 43 | ] 44 | 45 | 46 | if __name__ == "__main__": 47 | main() 48 | -------------------------------------------------------------------------------- /vasppy/scripts/vasp_summary.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import sys 4 | from pathlib import Path 5 | import yaml # type: ignore 6 | import tqdm # type: ignore 7 | from multiprocessing import Pool 8 | import argparse 9 | from vasppy.summary import Summary, find_vasp_calculations 10 | from vasppy.vaspmeta import VASPMeta 11 | 12 | """Script for collecting information about VASP calculations into YAML format, for further processing. 13 | 14 | Expects a series of directories (listed in `result_dirs`) that each contain: 15 | vasprun.xml 16 | vaspmeta.yaml (additional metadata providing information about each calculation) 17 | """ 18 | 19 | 20 | def get_args(): 21 | parser = argparse.ArgumentParser(description="Summarise a VASP calculation.") 22 | parser.add_argument( 23 | "-r", 24 | "--recursive", 25 | help="Recursively analyse directories.", 26 | action="store_true", 27 | ) 28 | parser.add_argument( 29 | "-l", "--list", help="List supported data flags.", action="store_true" 30 | ) 31 | parser.add_argument("-p", "--print", help="Specify data to parse.", nargs="*") 32 | parser.add_argument("-f", "--file", help="Specify a file to read data flags from.") 33 | parser.add_argument( 34 | "-c", 35 | "--check", 36 | help="Checks whether VASP directories contain vaspmeta.yaml and vasprun.xml files", 37 | action="store_true", 38 | ) 39 | parser.add_argument( 40 | "-b", 41 | "--progress-bar", 42 | help="Show progress bar when parsing vasprun.xml files", 43 | action="store_true", 44 | ) 45 | parser.add_argument( 46 | "-j", 47 | "--maxjobs", 48 | help="Maximum number of calculations to parse in parallel", 49 | type=int, 50 | ) 51 | args = parser.parse_args() 52 | return args 53 | 54 | 55 | def get_summary(p): 56 | return Summary(p) 57 | 58 | 59 | # This should really be set in the vasppy.Summary code, so that it can be tested to be consistent with the supported print methods. 60 | # In fact, ideally the key, print method, and description would all be collected in a single object, which suggests writing this as a simple class. 61 | 62 | 63 | def main(): 64 | supported_flags = Summary.supported_flags 65 | to_print = [ 66 | "title", 67 | "status", 68 | "stoichiometry", 69 | "potcar", 70 | "plus_u", 71 | "energy", 72 | "lreal", 73 | "k-points", 74 | "functional", 75 | "encut", 76 | "ediffg", 77 | "ibrion", 78 | "converged", 79 | "version", 80 | "md5", 81 | "directory", 82 | ] 83 | titles = None 84 | args = get_args() 85 | if args.list: 86 | for ( 87 | k, 88 | v, 89 | ) in supported_flags.items(): 90 | print("{}: {}".format(k.ljust(15), v)) 91 | sys.exit() 92 | if args.file: 93 | with open(args.file, "r") as stream: 94 | settings = yaml.load(stream, Loader=yaml.SafeLoader) 95 | if "to_print" in settings: 96 | to_print = settings["to_print"] 97 | if "titles" in settings: 98 | titles = settings["titles"] 99 | if args.print: 100 | not_supported = [p for p in args.print if p not in supported_flags] 101 | if not_supported: 102 | raise ValueError(not_supported) 103 | else: 104 | to_print = args.print 105 | if args.recursive: 106 | path = sorted(find_vasp_calculations()) 107 | else: 108 | path = ["."] 109 | if args.check: 110 | for p in path: 111 | vaspmeta = Path("{}/vaspmeta.yaml".format(p)) 112 | if not vaspmeta.is_file(): 113 | print("{} is missing vaspmeta.yaml".format(p)) 114 | vasprun = Path("{}/vasprun.xml".format(p)) 115 | if not vasprun.is_file(): 116 | print("{} is missing vasprun.xml".format(p)) 117 | else: 118 | if titles: 119 | # Only parse directories with matching vasp_meta titles 120 | matching_path = [] 121 | for p in path: 122 | vm = VASPMeta.from_file("{}/vaspmeta.yaml".format(p)) 123 | if vm.title in titles: 124 | matching_path.append(p) 125 | path = matching_path 126 | if args.maxjobs: 127 | len(path) 128 | with Pool(args.maxjobs) as p: 129 | if args.progress_bar: 130 | summaries = list( 131 | tqdm.tqdm(p.imap(get_summary, path), total=len(path)) 132 | ) 133 | else: 134 | summaries = p.map(get_summary, path) 135 | else: 136 | if args.progress_bar: 137 | path_iterator = tqdm.tqdm(path, unit="vasprun") 138 | else: 139 | path_iterator = path 140 | summaries = [get_summary(p) for p in path_iterator] 141 | if args.progress_bar: 142 | iterable = tqdm.tqdm(summaries, unit="records") 143 | else: 144 | iterable = summaries 145 | for s in iterable: 146 | s.output(to_print=to_print) 147 | 148 | 149 | if __name__ == "__main__": 150 | main() 151 | -------------------------------------------------------------------------------- /vasppy/scripts/xdatcar_to_disp.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from vasppy.xdatcar import Xdatcar 4 | import argparse 5 | import copy 6 | 7 | 8 | def parse_command_line_arguments(): 9 | # command line arguments 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument("xdatcar") 12 | args = parser.parse_args() 13 | return args 14 | 15 | 16 | def main(): 17 | args = parse_command_line_arguments() 18 | xdatcar = Xdatcar() 19 | xdatcar.read_from(args.xdatcar) 20 | poscar1 = copy.deepcopy(xdatcar.poscar[0]) 21 | for p in xdatcar.poscar[1:]: 22 | poscar2 = p 23 | for i, _c in enumerate(poscar1.coordinates): 24 | print( 25 | " ".join( 26 | [ 27 | str(e) 28 | for e in ( 29 | poscar1.cell.minimum_image( 30 | poscar1.coordinates[i], poscar2.coordinates[i] 31 | ).dot(poscar1.cell.matrix) 32 | ) 33 | ] 34 | ) 35 | ) 36 | poscar1 = copy.deepcopy(p) 37 | 38 | 39 | if __name__ == "__main__": 40 | main() 41 | -------------------------------------------------------------------------------- /vasppy/scripts/xdatcar_to_rdf.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import argparse 4 | from pymatgen.io.vasp import Xdatcar # type: ignore 5 | from vasppy.rdf import RadialDistributionFunction 6 | 7 | # import copy 8 | # import math 9 | # import numpy as np # type: ignore 10 | 11 | 12 | def parse_command_line_arguments(): 13 | """Parse command line arguments. 14 | 15 | Args: 16 | None 17 | 18 | Returns: 19 | dict 20 | 21 | """ 22 | # command line arguments 23 | parser = argparse.ArgumentParser() 24 | parser.add_argument("xdatcar") 25 | parser.add_argument("label", nargs=2) 26 | parser.add_argument("max_r", type=float) 27 | parser.add_argument("n_bins", type=int) 28 | args = parser.parse_args() 29 | return args 30 | 31 | 32 | def main(): 33 | args = parse_command_line_arguments() 34 | max_r = args.max_r 35 | number_of_bins = args.n_bins 36 | species_1 = args.label[0] 37 | species_2 = args.label[1] 38 | xdatcar = Xdatcar(args.xdatcar) 39 | indices_i = [ 40 | i for i, s in enumerate(xdatcar.structures[0]) if s.species_string == species_1 41 | ] 42 | if not indices_i: 43 | raise ValueError(f"No species {species_1} found") 44 | indices_j = [ 45 | i for i, s in enumerate(xdatcar.structures[0]) if s.species_string == species_2 46 | ] 47 | if not indices_j: 48 | raise ValueError(f"No species {species_2} found") 49 | rdf = RadialDistributionFunction( 50 | xdatcar.structures, indices_i, indices_j, number_of_bins, 0.0, max_r 51 | ) 52 | for x, y in zip(rdf.r, rdf.rdf, strict=True): 53 | print(x, y) 54 | 55 | 56 | if __name__ == "__main__": 57 | main() 58 | -------------------------------------------------------------------------------- /vasppy/units.py: -------------------------------------------------------------------------------- 1 | from scipy.constants import physical_constants, angstrom # type: ignore 2 | 3 | angstrom_to_bohr = physical_constants["atomic unit of length"][0] / angstrom 4 | ev_to_hartree = physical_constants["electron volt-hartree relationship"][0] 5 | -------------------------------------------------------------------------------- /vasppy/utils.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | from monty.io import zopen # type: ignore 3 | from pathlib import Path 4 | import os 5 | from contextlib import contextmanager 6 | from pymatgen.core import Structure # type: ignore 7 | from typing import Optional, List 8 | import numpy as np 9 | 10 | 11 | @contextmanager 12 | def cd(path): 13 | old_dir = os.getcwd() 14 | os.chdir(path) 15 | try: 16 | yield 17 | finally: 18 | os.chdir(old_dir) 19 | 20 | 21 | def md5sum(string: str) -> str: 22 | """Generate the md5 checksum for a string 23 | 24 | Args: 25 | string (str: The string to be checksummed. 26 | 27 | Returns: 28 | str: The hex checksum. 29 | 30 | """ 31 | h = hashlib.new("md5") 32 | h.update(string.encode("utf-8")) 33 | return h.hexdigest() 34 | 35 | 36 | def file_md5(filename: str) -> str: 37 | """Generate the md5 checksum for a file 38 | 39 | Args: 40 | filename (str): The file to be checksummed. 41 | 42 | Returns: 43 | (str): The hex checksum 44 | 45 | Notes: 46 | If the file is gzipped, the md5 checksum returned is 47 | for the uncompressed ASCII file. 48 | 49 | """ 50 | with zopen(filename, "r") as f: 51 | file_string = f.read() 52 | try: # attempt to decode byte object 53 | file_string = file_string.decode() 54 | except AttributeError: 55 | pass 56 | return md5sum(file_string) 57 | 58 | 59 | def match_filename(filename: str) -> Optional[str]: 60 | """Checks whether a file exists, either as named, or as a a gzippped file (filename.gz) 61 | 62 | Args: 63 | (str): The root filename. 64 | 65 | Returns: 66 | (str|None): if the file exists (either as the root filename, or gzipped), the return 67 | value will be the actual filename. If no matching filename is found the return 68 | value is set to NoneStr 69 | 70 | """ 71 | f = next( 72 | ( 73 | "{}{}".format(filename, extension) 74 | for extension in ["", ".gz"] 75 | if Path("{}{}".format(filename, extension)).is_file() 76 | ), 77 | None, 78 | ) 79 | return f 80 | 81 | 82 | def validate_checksum(filename, md5sum): 83 | """ 84 | Compares the md5 checksum of a file with an expected value. 85 | If the calculated and expected checksum values are not equal, 86 | ValueError is raised. 87 | If the filename `foo` is not found, will try to read a gzipped file named 88 | `foo.gz`. In this case, the checksum is calculated for the unzipped file. 89 | 90 | Args: 91 | filename (str): Path for the file to be checksummed. 92 | md5sum (str): The expected hex checksum. 93 | 94 | Returns: 95 | None 96 | """ 97 | filename = match_filename(filename) 98 | md5_hash = file_md5(filename=filename) 99 | if md5_hash != md5sum: 100 | raise ValueError("md5 checksums are inconsistent: {}".format(filename)) 101 | 102 | 103 | def dr_ij( 104 | structure: Structure, 105 | indices_i: Optional[List[int]] = None, 106 | indices_j: Optional[List[int]] = None, 107 | self_reference: bool = False, 108 | ) -> np.ndarray: 109 | """ 110 | Calculate all i-j interatomic distances for a single pymatgen Structure. 111 | 112 | Args: 113 | structure (:obj:`pymatgen.Structure`): A pymatgen Structure 114 | indices_i (:obj:`list(int)`, optional): List of indices for species i. 115 | Optional, default is `None`. 116 | If `indices_i` is not specified, then distances will be calculated between 117 | all pairs of atoms. 118 | indices_j (:obj:`list(int)`, optional): List of indices for species j. 119 | Optional, default is `None`. 120 | If `indices_j` is not specified, then `indices_j` will be set equal 121 | to `indices_i`. 122 | self_reference (bool, optional): If computing distances for i==j, whether 123 | to include the i==j dr=0 terms. Optional, default is `False`. 124 | 125 | Returns: 126 | np.array: N_i x N_j numpy array of i-j minimum image distances. 127 | 128 | """ 129 | if indices_i is None: 130 | indices_i = list(range(len(structure))) 131 | if indices_j is None: 132 | indices_j = indices_i 133 | lattice = structure.lattice 134 | i_frac_coords = structure.frac_coords[indices_i] 135 | j_frac_coords = structure.frac_coords[indices_j] 136 | dr_ij = lattice.get_all_distances(i_frac_coords, j_frac_coords) 137 | # If indices_i and indices_j contain common elements AND self_reference == False 138 | # then we want to mask dr_ij to remove the i==j dr=0 terms 139 | if (np.intersect1d(indices_i, indices_j).size > 0) and not self_reference: 140 | mask = np.ones_like(dr_ij, dtype=bool) 141 | for i_loc, i in enumerate(indices_i): 142 | for j_loc, j in enumerate(indices_j): 143 | if i == j: 144 | mask[i_loc, j_loc] = 0 145 | to_return = dr_ij[mask].reshape(len(indices_i), -1) 146 | else: 147 | to_return = dr_ij 148 | return to_return 149 | -------------------------------------------------------------------------------- /vasppy/vaspmeta.py: -------------------------------------------------------------------------------- 1 | import yaml # type: ignore 2 | 3 | 4 | class VASPMeta: 5 | """ 6 | VASPMeta class for storing additional VASP calculation metadata 7 | """ 8 | 9 | def __init__(self, title, description, status, notes=None, type=None, track=None): 10 | """ 11 | Initialise a VASPMeta object. 12 | 13 | Args: 14 | title (Str): The title string for this calculation 15 | description (Str): Long description 16 | status (Str): Current status of the calculation. 17 | Expected strings are (to-run, incomplete, finished, dropped) 18 | notes (:obj:Str, optional): Any additional notes. Defaults to None. 19 | type (:obj:Str, optional): Can be used to describe the calculation type. 20 | Defaults to None. 21 | track (:obj:dict(str: str), optional): An optional dict of pairs of filenames 22 | for files to track. For each key: value pair, the key is the current filename 23 | in the directory. The value is the new filename that list of filenames to calculate md5 hashes 24 | files to calculate hashes for when summarising the calculation output. 25 | Defaults to None. 26 | 27 | Returns: 28 | None 29 | """ 30 | self.title = title 31 | self.description = description 32 | self.notes = notes 33 | expected_status = ["to-run", "incomplete", "finished", "dropped"] 34 | if status not in expected_status: 35 | raise ValueError( 36 | f'Unexpected calculations status: "{status}"' 37 | f" for calculation {title}" 38 | ) 39 | self.status = status 40 | expected_types = ["single-point", "neb"] 41 | if type: 42 | if type not in expected_types: 43 | raise ValueError( 44 | f'Unexpected calculation type: "{type}"' f" for calculation {title}" 45 | ) 46 | self.type = type 47 | else: 48 | self.type = None 49 | self.track = track 50 | 51 | @classmethod 52 | def from_file(cls, filename): 53 | """ 54 | Create a VASPMeta object by reading a `vaspmeta.yaml` file 55 | 56 | Args: 57 | filename (Str): filename to read in. 58 | 59 | Returns: 60 | (vasppy.VASPMeta): the VASPMeta object 61 | """ 62 | with open(filename, "r") as stream: 63 | data = yaml.load(stream, Loader=yaml.SafeLoader) 64 | notes = data.get("notes") 65 | v_type = data.get("type") 66 | track = data.get("track") 67 | xargs = {} 68 | if track: 69 | if isinstance(track, str): 70 | track = [track] 71 | xargs["track"] = track 72 | vaspmeta = VASPMeta( 73 | data["title"], 74 | data["description"], 75 | data["status"], 76 | notes=notes, 77 | type=v_type, 78 | **xargs, 79 | ) 80 | return vaspmeta 81 | -------------------------------------------------------------------------------- /vasppy/version.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.7.1.0" 2 | -------------------------------------------------------------------------------- /vasppy/xdatcar.py: -------------------------------------------------------------------------------- 1 | from vasppy.poscar import Poscar 2 | import re 3 | import copy 4 | import numpy as np 5 | 6 | 7 | class Xdatcar: 8 | """Class for parsing and working with VASP XDATCAR files.""" 9 | 10 | lines_offset = 9 11 | 12 | def __init__(self): 13 | """ 14 | Initialise a Xdatcar object. 15 | 16 | Args: 17 | None 18 | 19 | Returns: 20 | None 21 | """ 22 | self.poscar = [] 23 | self.poscar.append(Poscar()) 24 | 25 | def read_from(self, filename: str) -> None: 26 | """Read XDATCAR data from a VASP XDATCAR file. 27 | 28 | Args: 29 | filename (str): The XDATCAR file to read. 30 | 31 | Returns: 32 | None 33 | 34 | """ 35 | self.poscar[0].read_from(filename) 36 | with open(filename) as f: 37 | lines = f.read() 38 | frame_header = re.compile("\nDirect configuration=\s+\d+\n") 39 | frame_coordinates = [ 40 | frame.split("\n") for frame in frame_header.split(lines)[2:] 41 | ] 42 | for frame in frame_coordinates: 43 | self.poscar.append(copy.deepcopy(self.poscar[0])) 44 | self.poscar[-1].coordinates = np.array( 45 | [ 46 | [float(e) for e in frame.pop(0).split()[0:3]] 47 | for i in range(sum(self.poscar[0].atom_numbers)) 48 | ] 49 | ) 50 | --------------------------------------------------------------------------------