diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a4ff168..ded6faf 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -20,12 +20,12 @@ jobs: pip install -e . - name: Sphinx build run: | - sphinx-build docs docs_build + sphinx-build docs _build - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v3 if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} with: publish_branch: gh-pages github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: docs_build/ + publish_dir: _build/ force_orphan: true diff --git a/_build/.buildinfo b/_build/.buildinfo deleted file mode 100644 index a0d4340..0000000 --- a/_build/.buildinfo +++ /dev/null @@ -1,4 +0,0 @@ -# Sphinx build info version 1 -# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 8f6571ea4f3f01db21cca25e3ed4df0b -tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/_build/.doctrees/CONTRIBUTING.doctree b/_build/.doctrees/CONTRIBUTING.doctree deleted file mode 100644 index 24eae18..0000000 Binary files a/_build/.doctrees/CONTRIBUTING.doctree and /dev/null differ diff --git a/_build/.doctrees/README.doctree b/_build/.doctrees/README.doctree deleted file mode 100644 index 156671c..0000000 Binary files a/_build/.doctrees/README.doctree and /dev/null differ diff --git a/_build/.doctrees/asimplify.doctree b/_build/.doctrees/asimplify.doctree deleted file mode 100644 index 727f6ba..0000000 Binary files a/_build/.doctrees/asimplify.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.benchmarking.doctree b/_build/.doctrees/asimtools.asimmodules.benchmarking.doctree deleted file mode 100644 index fdadf77..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.benchmarking.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.doctree b/_build/.doctrees/asimtools.asimmodules.doctree deleted file mode 100644 index 0ffb84e..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.elastic_constants.doctree b/_build/.doctrees/asimtools.asimmodules.elastic_constants.doctree deleted file mode 100644 index 4250cb4..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.elastic_constants.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.eos.doctree b/_build/.doctrees/asimtools.asimmodules.eos.doctree deleted file mode 100644 index 669de0d..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.eos.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.geometry_optimization.doctree b/_build/.doctrees/asimtools.asimmodules.geometry_optimization.doctree deleted file mode 100644 index 51fbbe2..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.geometry_optimization.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.lammps.doctree b/_build/.doctrees/asimtools.asimmodules.lammps.doctree deleted file mode 100644 index 3fe7d92..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.lammps.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.phonons.doctree b/_build/.doctrees/asimtools.asimmodules.phonons.doctree deleted file mode 100644 index a08a5c5..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.phonons.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.surface_energies.doctree b/_build/.doctrees/asimtools.asimmodules.surface_energies.doctree deleted file mode 100644 index 310f509..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.surface_energies.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.transformations.doctree b/_build/.doctrees/asimtools.asimmodules.transformations.doctree deleted file mode 100644 index ef0eaad..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.transformations.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.vacancy_formation_energy.doctree b/_build/.doctrees/asimtools.asimmodules.vacancy_formation_energy.doctree deleted file mode 100644 index a31921b..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.vacancy_formation_energy.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.asimmodules.workflows.doctree b/_build/.doctrees/asimtools.asimmodules.workflows.doctree deleted file mode 100644 index b385721..0000000 Binary files a/_build/.doctrees/asimtools.asimmodules.workflows.doctree and /dev/null differ diff --git a/_build/.doctrees/asimtools.doctree b/_build/.doctrees/asimtools.doctree deleted file mode 100644 index 943cff2..0000000 Binary files a/_build/.doctrees/asimtools.doctree and /dev/null differ diff --git a/_build/.doctrees/environment.pickle b/_build/.doctrees/environment.pickle deleted file mode 100644 index a166521..0000000 Binary files a/_build/.doctrees/environment.pickle and /dev/null differ diff --git a/_build/.doctrees/include_contributing.doctree b/_build/.doctrees/include_contributing.doctree deleted file mode 100644 index 22b9459..0000000 Binary files a/_build/.doctrees/include_contributing.doctree and /dev/null differ diff --git a/_build/.doctrees/include_readme.doctree b/_build/.doctrees/include_readme.doctree deleted file mode 100644 index a759d77..0000000 Binary files a/_build/.doctrees/include_readme.doctree and /dev/null differ diff --git a/_build/.doctrees/index.doctree b/_build/.doctrees/index.doctree deleted file mode 100644 index 0e7da71..0000000 Binary files a/_build/.doctrees/index.doctree and /dev/null differ diff --git a/_build/.doctrees/modules.doctree b/_build/.doctrees/modules.doctree deleted file mode 100644 index 286b722..0000000 Binary files a/_build/.doctrees/modules.doctree and /dev/null differ diff --git a/_build/.doctrees/usage.doctree b/_build/.doctrees/usage.doctree deleted file mode 100644 index d67d00f..0000000 Binary files a/_build/.doctrees/usage.doctree and /dev/null differ diff --git a/_build/.doctrees/workflows.doctree b/_build/.doctrees/workflows.doctree deleted file mode 100644 index 33d272b..0000000 Binary files a/_build/.doctrees/workflows.doctree and /dev/null differ diff --git a/_build/CONTRIBUTING.html b/_build/CONTRIBUTING.html deleted file mode 100644 index 922e626..0000000 --- a/_build/CONTRIBUTING.html +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - Contributing — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Contributing

-

When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.

-

Please note we have a code of conduct, please follow it in all your interactions with the project.

-

There are two main ways to contribute. One is to make changes to the existing -codes and asimmodules. In this case, please make sure your change passes tests or -submit a test accordinly. The second way to contribute is to add a new asimmodule -to the core set of asimmodules. Reviewers will work with you to make sure your new -asimmodule follows best practice including using utils, syntax highlighting, docs -and tests.

-
-

Pull Request Process

-
    -
  1. Ensure any install or build dependencies are removed before the end of the layer when doing a build.

  2. -
  3. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters.

  4. -
  5. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is SemVer.

  6. -
  7. You may merge the Pull Request in once you have the sign-off of one other developer, or if you do not have permission to do that, you may request the other reviewer to merge it for you.

  8. -
-
-
-

Code of Conduct

-
-

Our Pledge

-

In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation.

-
-
-

Our Standards

-

Examples of behavior that contributes to creating a positive environment -include:

-
    -
  • Using welcoming and inclusive language

  • -
  • Being respectful of differing viewpoints and experiences

  • -
  • Gracefully accepting constructive criticism

  • -
  • Focusing on what is best for the community

  • -
  • Showing empathy towards other community members

  • -
-

Examples of unacceptable behavior by participants include:

-
    -
  • The use of sexualized language or imagery and unwelcome sexual attention or -advances

  • -
  • Trolling, insulting/derogatory comments, and personal or political attacks

  • -
  • Public or private harassment

  • -
  • Publishing others’ private information, such as a physical or electronic -address, without explicit permission

  • -
  • Other conduct which could reasonably be considered inappropriate in a -professional setting

  • -
-
-
-

Our Responsibilities

-

Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior.

-

Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful.

-
-
-

Scope

-

This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers.

-
-
-

Enforcement

-

Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [INSERT EMAIL ADDRESS]. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately.

-

Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project’s leadership.

-
-
-

Attribution

-

This Code of Conduct is adapted from the Contributor Covenant, version 1.4, -available at http://contributor-covenant.org/version/1/4

-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/README.html b/_build/README.html deleted file mode 100644 index 2c67650..0000000 --- a/_build/README.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - Atomic SIMulation Tools — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- - - - - - -

Documentation | GitHub

-
-

Atomic SIMulation Tools

-

This package is a lightweight workflow and simulation manager for reproducible -atomistic simulations that can be transferred across environments, calculators -and structures on Unix systems. By using in-built or user-defined asimmodules -and utilities, users can run/build their own simulation recipes and -automagically scale them locally or on slurm based clusters. The core idea is -to separate the dependence of the atomistic potential/calculator and the -simulations steps thereby allowing the same simulation to be run with multiple -calculators/codes and the same calculator to be used for multiple simulation -parameters without altering simulation code. Input and output files follow a -simple consisten file structure and format so that consistent analysis -pipelines can be used across users. For a concrete example of how ASIMTools -achieves this, see the Developing Custom Asimmodules page

-
-

Developer philosophy

-

The goal of asimtools is to push all the complexity of workflow management, -best-practices, file management etc. into the backend such that the everyday -user only has to handle input files for existing workflows and asimmodule files -for workflows they want to implement.This allows the user to focus on doing the -science and designing experiments. The following are the guiding principles for -how asimtools should work:

-
    -
  • Asimmodules should resemble boilerplate ASE code as much as possible.

  • -
  • Asimmodules should avoid explicitly depending on a calculator

  • -
  • Asimmodules should not explicitly depend on the context/environment in which -they run

  • -
  • It should be easy to debug individual asimmodules/parts in large workflows. -In addition, it should always be possible to debug/resubmit jobs without -using asimtools.

  • -
  • Input file structure and format should be standard across all asimmodules. In -addition all input parameters should match how they would like without -asimtools i.e. do not provide an API!

  • -
  • Job progress tracking must be incorporated for easy debugging

  • -
  • Best practices should be built-in e.g. if multiple jobs of the same slurm -context are submitted simulataneously, it must be a job array.

  • -
-
-
-

Philosophy on User Experience

-

The philosophy is to build “simulations” using building blocks of asimmodules. -Asimmodules are nothing but Python functions that return a dictionary, anything -can be done in the function code. These asimmodules can be as -complicated/efficient as you make them using any external packages you want and -can be optimized with time but can still be run within the framework. This -allows a test friendly way to transition from say a tutorial on the -ASE/pymatgen website to an asimtools asimmodule. So while complicated wrappers -are discouraged, they would still work as long as the asimmodule works. The -benefit out of the box is that you can make your asimmodule independent of -calculator or input structures and submit them easily.

-

We also aim to provide a standard set of robust and efficient simulation -protocols as we develop. You can see all the implemented workflows provided -with the package in the examples directory and modify them to your application -If you have suggestions for improvements in methodology or code, please bring -up an issue on github!

-
-
-

Getting Started

-

These instructions will give you a copy of the project up and running.

-
-

Installing ASIMTools

-

If you prefer to use a conda a environment, you can create and activate one -using:

-
conda create -n asimtools python=3.9
-conda activate asimtools
-
-
-

Then you can install asimtools either using pip or by cloning the source code -from github. Note that the cloned version might have some minor bug fixes that -are not included in the official PyPI release. It is also easier to go through -the examples if you clone the repository.

-

To install the latest asimtools release from PyPI, you can simply use

-
pip install asimtools
-
-
-

To install from source use

-
git clone
-https://gitlab.com/ase/ase.git && cd ase pip install . cd ../
-
-git clone https://github.com/BattModels/asimtools.git
-cd asimtools
-pip install .
-
-
-

You can also choose to use the latest version of ASE since the ones on PyPI and -conda are quite outdated.

-
git clone https://gitlab.com/ase/ase.git
-cd ase
-pip install .
-
-
-

Individual calculators may need external packages for running them. For example -if you want to use Quantum Espresso or CASTEP, you will have to install them. -Similarly some asimmodules e.g. lammps.py might also need external packages -to be used. It is up to the user to make sure those are installed.

-

You will also need to setup some environment variables, these variables point -to global env_input.yaml and calc_input.yaml files with your favorite -configurations since these are commonly shared among simulations. You can also -directly specify them when running asim-execute (See asim-execute -h). You -can also provide a directory for ASIMTools to search for your custom -asimmodules. Examples of these files can be found in the examples.

-

Add the following to your .bashrc

-
export ASIMTOOLS_ENV_INPUT=/path/to/my/global/env_input.yaml
-export ASIMTOOLS_CALC_INPUT=/path/to/my/global/calc_input.yaml
-export ASIMTOOLS_ASIMMODULE_DIR=/path/to/my/asimmodule/dir
-
-
-
-
-
-

Running the tests

-

To run tests for the workflow tools, from the tests directory, call:

-
pytest
-
-
-

To run the test suite on a component component.py , call:

-
pytest test_component.py
-
-
-

To run all tests for the provided asimmodules, cd into the examples directory -and call:

-
source run_all.sh
-
-
-

Or you can run a test for each individual example in its directory using:

-
source run.sh
-
-
-

If no errors are reported, the tests have passed. These tests simply test the -functionality of the code, not the scientific validity of the simulations!

-

To run tests for the provided asimmodules using slurm, you can similarly run -the bash scripts ending with _slurm.sh. This will submit a number of jobs, -none longer than 1 minute.

-
-
-

Contributing

-

Please read CONTRIBUTING.md for details on our code -of conduct, and the process for submitting pull requests to us.

-
-
-

Authors

- -

See also the list of -contributors -who participated in this project.

-
-
-

License

-

This project is licensed under the MIT License

- -
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/benchmarking/parity.html b/_build/_modules/asimtools/asimmodules/benchmarking/parity.html deleted file mode 100644 index dce9d37..0000000 --- a/_build/_modules/asimtools/asimmodules/benchmarking/parity.html +++ /dev/null @@ -1,329 +0,0 @@ - - - - - - asimtools.asimmodules.benchmarking.parity — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.benchmarking.parity

-#!/usr/bin/env python
-'''
-Generates a parity plot and collects evaluation statistics comparing energy
-and/or forces and/or stress to existing values in the provided dataset. This
-asimmodule can work in parallel based on the number of cores specified.
-
-Author: mkphuthi@github.com
-
-'''
-from typing import Dict, List, TypeVar, Sequence
-from functools import partial
-from multiprocessing import Pool
-import numpy as np
-import matplotlib.pyplot as plt
-from asimtools.calculators import load_calc
-from asimtools.utils import (
-    write_csv_from_dict,
-    get_images,
-    parse_slice,
-    get_axis_lims,
-)
-
-Calculator = TypeVar('Calculator')
-
[docs]def calc_parity_data( - subset: List, - calc_id: str, - properties: Sequence = ('energy', 'forces', 'stress'), - force_prob: float = 1.0, -) -> Dict: - """Calculates parity data for each atoms instance in subset - - :param subset: List of atoms instances - :type subset: List - :param calc_id: calc_id specification - :type calc_id: str - :param properties: Properties to evaluate, choose from "energy", \ - "forces" and "stress", defaults to ('energy', 'forces', 'stress') - :type properties: List, optional - :param force_prob: Fraction of forces to consider, may speed up sampling \ - large structures by subsampling forces randomly, defaults to 1.0 - :type force_prob: float, optional - :return: Dictionary with reference and predicted values for each \ - property - :rtype: Dict - """ - - res = {prop: [] for prop in properties} - ervals = [] - epvals = [] - frvals = [] - fpvals = [] - srvals = [] - spvals = [] - for i, atoms in enumerate(subset): - calc = load_calc(calc_id) - n_atoms = len(atoms) - if 'energy' in properties: - prop = 'energy' - ervals = np.hstack( - [ervals, atoms.get_potential_energy()/n_atoms] - ) - epvals = np.hstack( - [epvals, float(calc.get_potential_energy(atoms)/n_atoms)] - ) - - if 'forces' in properties: - if np.random.rand() < force_prob: - prop = 'forces' - frvals = np.hstack( - [frvals, np.array(atoms.get_forces()).flatten()] - ) - - fpvals = np.hstack( - [fpvals, np.array(calc.get_forces(atoms)).flatten()] - ) - - if 'stress' in properties: - prop = 'stress' - srvals = np.hstack( - [srvals, np.array(atoms.get_stress()).flatten()] - ) - - spvals = np.hstack( - [spvals, np.array(calc.get_stress(atoms)).flatten()] - ) - res[prop] = {'ref': srvals, 'pred': spvals} - - if i % 20 == 0: - print(f'Progress {i}/{len(subset)}') - - res['energy'] = {'ref': ervals, 'pred': epvals} - res['forces'] = {'ref': frvals, 'pred': fpvals} - res['stress'] = {'ref': srvals, 'pred': spvals} - return res
- -def _split_data(data: Sequence, chunks: int) -> List: - """Splits data into equal chunks and tosses the remainder - - :param data: Sequence of datapoints - :type data: Sequence - :param chunks: Number of chunks to split the data into - :type nprocs: int - :return: List of split datasets - :rtype: List - """ - subsets = [] - subset_len = int(np.ceil(len(data) // chunks)) - for subset_id in range(chunks): - start = subset_id * subset_len - stop = (subset_id + 1) * subset_len - subsets.append(data[start:stop]) - - return subsets - -
[docs]def rmse(yhat: Sequence, y: Sequence) -> float: - """Calculate Root Mean Square Error between to sequences - - :param yhat: Predicted values - :type yhat: Sequence - :param y: True values - :type y: Sequence - :return: RMSE - :rtype: float - """ - return np.sqrt(np.sum(np.square(yhat - y)) / len(y))
- -
[docs]def parity( - images: Dict, - calc_id: str, - force_prob: float = 1.0, - nprocs: int = 1, - unit: str = 'meV', - index: str = ':', - properties: Sequence = ('energy', 'forces', 'stress'), -) -> Dict: - """Generates a parity plot and collects evaluation statistics comparing energy - and/or forces and/or stress to existing values in the provided dataset - - :param images: Image specification, see :func:`asimtools.utils.get_images` - :type images: Dict - :param calc_id: ID of calculator provided in calc_input or global file - :type calc_id: str - :param force_prob: Fraction of forces to consider in force parity, \ - can be used for speeding up large structures by only subsampling\ - randomly, defaults to 1.0 - :type force_prob: float, optional - :param nprocs: Number of process to parallelize over, must be less than \ - number of datapoints, defaults to 1 - :type nprocs: int, optional - :param unit: Unit to plot, choose from meV, eV or kcal/mol, \ - defaults to 'meV' - :type unit: str, optional - :param index: index of data to use from full dataset, defaults to ':' - :type index: int, optional - :param properties: Properties to evaluate, choose from "energy",\ - "forces" and "stress", defaults to ('energy', 'forces', 'stress') - :type properties: Sequence, optional - :return: Dictionary of results - :rtype: Dict - """ - - index = parse_slice(index) - data = get_images(**images)[index] - assert len(data) > nprocs, \ - f'Too little samples ({len(data)}) for {nprocs}' - - unit_factors = {'meV': 1000, 'eV': 1, 'kcal/mol': 23.0621} - unit_factor = unit_factors[unit] - units = { - 'energy': f'{unit}/atom', - 'forces': f'{unit}'+r'/$\AA$', - 'stress': f'{unit}'+r'/$\AA^3$', - } - - subsets = _split_data(data, nprocs) - reses = [] - with Pool(nprocs) as pool: - reses = pool.map(partial( - calc_parity_data, - calc_id=calc_id, - properties=properties, - force_prob=force_prob, - ), - subsets, - ) - - res = {prop: {'ref': [], 'pred': []} for prop in properties} - results = {} - for prop in properties: - for source in ('ref', 'pred'): - res[prop][source] = np.hstack( - [reses[jj][prop][source] for jj in range(len(reses))] - ) * unit_factor - - write_csv_from_dict( - f'{prop}_parity.csv', - res[prop], - header=f'Units: {unit}', - ) - - rmse_val = rmse(res[prop]['ref'], res[prop]['pred']) - results[f'{prop}_rmse'] = float(rmse_val) - - _, ax = plt.subplots() - lims = np.array(get_axis_lims(res[prop]['ref'], res[prop]['pred'])) - - ax.plot(lims, lims, 'k-') - ax.plot( - res[prop]['ref'], - res[prop]['pred'], - 'ro', - label=f'{prop.capitalize()} RMSE={rmse_val:.3g}{units[prop]}', - ) - ax.set_xticks(np.round(np.linspace(*lims, 5), 1)) - ax.set_yticks(np.round(np.linspace(*lims, 5), 1)) - ax.set_aspect('equal', 'box') - ax.set_xlabel(f'Reference {prop.capitalize()} ({units[prop]})') - ax.set_ylabel(f'Predicted {prop.capitalize()} ({units[prop]})') - ax.legend() - plt.savefig(f'{prop}_parity.png') - - results['Energy unit'] = unit - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/do_nothing.html b/_build/_modules/asimtools/asimmodules/do_nothing.html deleted file mode 100644 index 8561fcf..0000000 --- a/_build/_modules/asimtools/asimmodules/do_nothing.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - asimtools.asimmodules.do_nothing — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.do_nothing

-#!/usr/bin/env python
-'''
-asimmodule for unit tests and debugging, does nothing for specified duration
-'''
-from time import sleep
-from typing import Dict, Optional
-
-
[docs]def do_nothing(duration: Optional[int] = 5) -> Dict: - """Sleep for the specified duration - - :param duration: time in seconds, defaults to 60 - :type duration: int, optional - :return: Dictionary with duration slept for - :rtype: Dict - """ - sleep(duration) - results = {'duration': duration} - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/elastic_constants/cubic_energy_expansion.html b/_build/_modules/asimtools/asimmodules/elastic_constants/cubic_energy_expansion.html deleted file mode 100644 index da2dab0..0000000 --- a/_build/_modules/asimtools/asimmodules/elastic_constants/cubic_energy_expansion.html +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - asimtools.asimmodules.elastic_constants.cubic_energy_expansion — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.elastic_constants.cubic_energy_expansion

-#!/usr/bin/env python
-'''
-Describe the asimmodule briefly here. If this is a asimmodule that runs multiple steps,
-describe it here using reStructuredText to generate autodocs
-
-Cite the papers where the method/asimmodule was first introduced here as well
-
-Author: mkphuthi@github.com
-'''
-
-from typing import Dict, Sequence, Optional
-import logging
-import numpy as np
-from scipy.optimize import curve_fit
-from ase.units import GPa
-from asimtools.calculators import load_calc
-from asimtools.utils import (
-    get_atoms,
-)
-from asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization import (
-    ase_cubic_eos_optimization as eos
-)
-
-
[docs]def get_strained_atoms(atoms, strain: str, delta: float): - """Returns a unit cell with atoms strained according to some useful types - - :param atoms: input atoms - :type atoms: ase.Atoms - :param strain: Type of strain - :type strain: str - :param delta: value of strain - :type delta: float - :return: atoms with strained cell - :rtype: ase.Atoms - """ - strains = { - 'uniform':np.array([ - [1+delta, 0, 0], - [0, 1+delta, 0], - [0, 0, 1+delta], - ]), - - 'c44_vol_cons': np.array([ - [4 / (4 - delta**2), 0, 0], - [0, 1, delta/2], - [0, delta/2, 1], - ]), - 'cprime_vol_cons': np.array([ - [1+delta/2, 0, 0], - [0, 1-delta/2, 0], - [0, 0, 4 / (4 - delta**2)], - ]), - 'orth_vol_cons': np.array([ - [1+delta, 0, 0], - [0, 1-delta, 0], - [0, 0, 1 + delta**2 / (1 - delta**2)], - ]), - 'mono_vol_cons': np.array([ - [1, delta/2, 0], - [delta/2, 1, 0], - [0, 0, 1+delta**2 / (4 - delta**2)], - ]), - } - - if isinstance(strain, str): - try: - strain = strains[strain] - except ValueError: - print(f' Please choose strain from {strains}') - - cell = atoms.get_cell().copy() - new_cell = np.array([ - np.squeeze(np.asarray(np.dot(strain, cell[0]))), - np.squeeze(np.asarray(np.dot(strain, cell[1]))), - np.squeeze(np.asarray(np.dot(strain, cell[2]))) - ]) - - strained_atoms = atoms.copy() - strained_atoms.set_cell(new_cell, scale_atoms=True) - return strained_atoms
- -
[docs]def cubic_energy_expansion( - calc_id: str, - image: Dict, - deltas: Sequence[float] = (-0.01,-0.0075,-0.005,0.00,0.005,0.0075,0.01), - ase_cubic_eos_args: Optional[Dict] = None, -) -> Dict: - """Calculates B (Bulk modulus), C11, C12 and C44 elastic constants of - a structure with cubic symmetry - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param deltas: strains to apply in each direction, defaults to (-0.01,-0.0075,-0.005,0.00,0.005,0.0075,0.01) - :type deltas: Sequence[float], optional - :param ase_cubic_eos_args: Argumenents to pass to :func:`asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization`, defaults to None - :type ase_cubic_eos_args: Optional[Dict], optional - :return: Elastic constant results - :rtype: Dict - """ - calc = load_calc(calc_id) - atoms = get_atoms(**image) - atoms.set_calculator(calc) - - # Start by getting the Bulk modulus and optimized cell from the EOS - logging.info('Calculating EOS') - eos_kwargs = {'image': image, 'calc_id': calc_id} - if ase_cubic_eos_args is not None: - eos_kwargs.update(ase_cubic_eos_args) - eos_results = eos(**eos_kwargs) - B = eos_results['B'] - atoms = get_atoms(image_file='eos_image_output.xyz') - logging.info('Finished calculating EOS and B, moving to other constants') - - # Sequentially apply relevant strains and extract elastic constants by - # fitting stress strain curves - c11min12_ens = [] - c44_ens = [] - for delta in deltas: - logging.info('Calculating for C44 strain, delta = %s', delta) - c44_atoms = get_strained_atoms( - atoms.copy(), 'mono_vol_cons', delta - ) - calc = load_calc(calc_id) - c44_atoms.calc = calc - c44_en = c44_atoms.get_potential_energy() - c44_ens.append(c44_en) - c44_atoms.info['strain'] = 'mono_vol_cons' - c44_atoms.info['delta'] = delta - c44_atoms.write(f's{delta:.4f}_c44.xyz') - - logging.info('Calculating for C11-C12 strain, delta = %s', delta) - c11min12_atoms = get_strained_atoms( - atoms.copy(), 'orth_vol_cons', delta - ) - calc = load_calc(calc_id) - c11min12_atoms.calc = calc - c11min12_en = c11min12_atoms.get_potential_energy() - c11min12_ens.append(c11min12_en) - c11min12_atoms.info['strain'] = 'mono_vol_cons' - c11min12_atoms.info['delta'] = delta - c11min12_atoms.write(f's{delta:.4f}_c11min12.xyz') - - def f(x, a, b, c): - ''' Fitting function for free energy expansion to second order''' - return a*x**2 + b*x + c - - logging.info('Fitting for C44') - popt, pcov = curve_fit(f, deltas, c44_ens) - C44 = 2*popt[0] / atoms.get_volume() - - logging.info('Fitting for C11-C12') - popt, pcov = curve_fit(f, deltas, c11min12_ens) - C11minC12 = popt[0] / atoms.get_volume() - - # Deriving C11 and C12 - C12 = 1/3 * (3 * B - C11minC12) - C11 = C12 + C11minC12 - anis = 2 * C44 / (C11 - C12) - - results = { - 'constants': { - 'B': float(B / GPa), - 'C11minC12': float(C11minC12 / GPa), - 'C11': float(C11 / GPa), - 'C12': float(C12 / GPa), - 'C44': float(C44 / GPa), - 'Anisotropy': float(anis), - 'vol': float(atoms.get_volume()), - }, - } - - return results # Always return a dictionary! Use {} if necessary
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/eos/postprocess.html b/_build/_modules/asimtools/asimmodules/eos/postprocess.html deleted file mode 100644 index 7216b64..0000000 --- a/_build/_modules/asimtools/asimmodules/eos/postprocess.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - asimtools.asimmodules.eos.postprocess — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.eos.postprocess

-'''.Xauthority'''
-
-from typing import Dict, Tuple
-import numpy as np
-import matplotlib.pyplot as plt
-from ase.eos import EquationOfState
-from ase. units import GPa
-# from asimtools.job import load_output_images, load_input_images
-from asimtools.utils import (
-    write_csv_from_dict,
-    get_images,
-    get_atoms,
-)
-
-
[docs]def postprocess( - images: Dict, - initial_image: Dict, -) -> Tuple[None,Dict]: - """Plot an eos given a number of images and the initial image - - :param images: Scaled images specification, see :func:`asimtools.utils.get_images` - :type images: Dict - :param initial_image: Original image specification, see :func:`asimtools.utils.get_atoms` - :type initial_image: Dict - :return: Empty dict - :rtype: Tuple[None,Dict] - """ - images = get_images(**images) - volumes = np.array([at.get_volume() for at in images]) - energies = np.array([at.get_potential_energy() for at in images]) - write_csv_from_dict( - 'eos_output.csv', - {'volumes': volumes, 'energies': energies} - ) - eos_fit = EquationOfState(volumes, energies) - - try: - v0, e0, B = eos_fit.fit() - except ValueError: - print('ERROR: Could not fit EOS, check structures') - v0, e0, B = None, None, None - - fig, ax = plt.subplots() - if v0 is not None: - B_GPa = B / GPa # eV/Ang^3 to GPa - eos_fit.plot(ax=ax) - - # Get equilibrium lattice scaling by interpolation - xs = [atoms.info['scale'] for atoms in images] - vs = [] - atoms = get_atoms(**initial_image) - for x in xs: - samp_atoms = atoms.copy() - samp_atoms.cell = samp_atoms.cell*x - vs.append(samp_atoms.get_volume()) - x0 = np.interp(v0, vs, xs) - - results = { - 'equilibrium_volume': float(v0), - 'equilibrium_energy': float(e0), - 'equilibrium_scale': float(x0), - 'bulk_modulus': float(B_GPa), - 'bulk_modulus_unit': 'GPa', - } - else: - ax.plot(volumes, energies) - results = {} - ax.set_xlabel(r'Volume ($\AA$)') - ax.set_ylabel(r'Energy (eV)') - plt.savefig('eos.png') - plt.close(fig) - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/geometry_optimization/ase_cubic_eos_optimization.html b/_build/_modules/asimtools/asimmodules/geometry_optimization/ase_cubic_eos_optimization.html deleted file mode 100644 index 0d8938b..0000000 --- a/_build/_modules/asimtools/asimmodules/geometry_optimization/ase_cubic_eos_optimization.html +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization

-'''
-Calculate the equation of state, fit it and extract the equilibrium 
-volume, energy and bulk modulus. This script is based on the example provided 
-on the ASE website: https://wiki.fysik.dtu.dk/ase/tutorials/db/db.html
-
-author: mkphuthi@github.com
-'''
-
-from typing import Dict, Optional, Sequence
-import logging
-import matplotlib.pyplot as plt
-import pandas as pd
-from ase.eos import EquationOfState, calculate_eos
-from ase.io import read
-from ase.io.trajectory import Trajectory
-from asimtools.calculators import load_calc
-from asimtools.utils import get_atoms
-
-
[docs]def ase_cubic_eos_optimization( - calc_id: str, - image: Dict, - npoints: Optional[int] = 5, - eos_string: Optional[str] = 'sj', - eps: Optional[float] = 0.04, - scales: Optional[Sequence] = None, - plot: Optional[bool] = True, -) -> Dict: - """Generate the energy-volume equation of state (energy calculations not parallelized) - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param npoints: Number of energy points to calculate, must be >5, defaults to 5 - :type npoints: Optional[int], optional - :param eos_string: eos_string as specified for :func:`ase.eos.calculate_eos`, defaults to 'sj' - :type eos_string: Optional[str], optional - :param eps: eps as sepecified for ase, defaults to 0.04 - :type eps: Optional[float], optional - :param scales: array of values to scale the unit cell by (not volume) - :type eps: Optional[float], optional - :param plot: Whether to plot eos or not, defaults to True - :type plot: Optional[bool], optional - :return: Equilibrium energy, volume, bulk modulus and factor by which to scale lattice parameter to get equilibrium structure - :rtype: Dict - """ - calc = load_calc(calc_id) - atoms = get_atoms(**image) - atoms.calc = calc - v_init = atoms.get_volume() - traj_file = 'eos.traj' - if scales is not None: - traj = Trajectory('eos.traj', 'w') - volumes = [] - energies = [] - images = [] - for scale in scales: - scaled_atoms = atoms.copy() - cell = scaled_atoms.cell - scaled_atoms.set_cell(cell * scale, scale_atoms=True) - scaled_atoms.set_calculator(calc) - volumes.append(scaled_atoms.get_volume()) - energies.append(scaled_atoms.get_potential_energy()) - traj.write(scaled_atoms) - - eos = EquationOfState(volumes, energies) - else: - eos = calculate_eos(atoms, trajectory=traj_file, eps=eps, npoints=npoints) - - - traj = read(traj_file, index=':') - eos_dict = { - 'energies': [], - 'volumes': [], - 'volume_scale_factors': [], - } - for struct in traj: - eos_dict['energies'].append(struct.get_potential_energy()) - eos_dict['volumes'].append(struct.get_volume()) - v_factor = struct.get_volume() / v_init - eos_dict['volume_scale_factors'].append(v_factor) - - eos_df = pd.DataFrame(eos_dict) - eos_df.to_csv('eos.csv') - - eos.eos_string = eos_string - v0, e0, B = eos.fit() # find minimum - - logging.info('Successfully fit EOS') - # Do one more calculation at the minimum and write to disk - new_cell = atoms.cell.copy() - x = (v0 / atoms.get_volume())**(1 / 3) # scale cell by this much - new_cell *= x - atoms.set_cell(new_cell, scale_atoms=True) - atoms.get_potential_energy() - atoms.info['B'] = B - atoms.info['v0'] = v0 - atoms.info['scale'] = x - atoms.write('eos_image_output.xyz') - - if plot: - eos.plot() - plt.savefig('eos.png') - - results = { - 'v0': float(v0), - 'e0': float(e0), - 'B': float(B), - 'x0': float(v0 / v_init) - } - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/geometry_optimization/atom_relax.html b/_build/_modules/asimtools/asimmodules/geometry_optimization/atom_relax.html deleted file mode 100644 index ee93489..0000000 --- a/_build/_modules/asimtools/asimmodules/geometry_optimization/atom_relax.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - asimtools.asimmodules.geometry_optimization.atom_relax — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.geometry_optimization.atom_relax

-#!/usr/bin/env python
-'''
-Relaxes the given atomic structure using ASE's built-in structure
-optimizers
-'''
-
-from typing import Dict, Tuple, Optional
-import numpy as np
-import ase.optimize
-from ase.io.trajectory import Trajectory
-from asimtools.calculators import load_calc
-from asimtools.utils import get_atoms, get_logger
-
-
[docs]def atom_relax( - calc_id: str, - image: Dict, - optimizer: str = 'GPMin', #GPMin is fast in many cases according to ASE docs - properties: Tuple[str] = ('energy', 'forces'), - fmax: float = 0.02, - prefix: Optional[str] = None, -) -> Dict: - """Relaxes the given tomic structure using ASE's built-in structure - optimizers - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param prefix: Prefix of output files, defaults to '' - :type prefix: str, optional - :param optimizer: ASE Optimizer class, defaults to 'GPMin' - :type optimizer: str, optional - :param fmax: Force convergence threshold in optimizer, defaults to 0.02 - :type fmax: float, optional - :return: Dictionary of results - :rtype: Dict - """ - calc = load_calc(calc_id) - atoms = get_atoms(**image) - atoms.set_calculator(calc) - logger = get_logger() - - if prefix is not None: - prefix = prefix + '_' - else: - prefix = '' - - traj_file = prefix + 'atom_relax.traj' - dyn = getattr(ase.optimize, optimizer)(atoms) - traj = Trajectory( - traj_file, - 'a', - atoms, - properties=properties - ) - dyn.attach(traj) - try: - dyn.run(fmax=fmax) - except Exception: - logger.error('Failed to relax atoms') - raise - - image_file = prefix + 'image_output.xyz' - atoms.write(image_file, format='extxyz') - - energy = float(atoms.get_potential_energy()) - final_fmax = float(np.sqrt((atoms.get_forces() ** 2).sum(axis=1).max())) - - results = { - 'energy': energy, - 'final_fmax': final_fmax, - 'files':{ - 'image': image_file, - 'traj': traj_file, - } - } - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/geometry_optimization/cell_relax.html b/_build/_modules/asimtools/asimmodules/geometry_optimization/cell_relax.html deleted file mode 100644 index 68d9abc..0000000 --- a/_build/_modules/asimtools/asimmodules/geometry_optimization/cell_relax.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - asimtools.asimmodules.geometry_optimization.cell_relax — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.geometry_optimization.cell_relax

-#!/usr/bin/env python
-'''
-Relaxes structure using ASE
-
-Author: mkphuthi@github.com
-'''
-
-#pylint: disable=unused-argument
-#pylint: disable=too-many-locals
-#pylint: disable=too-many-arguments
-
-from typing import Dict, Optional, Sequence
-import ase.optimize
-from ase.constraints import StrainFilter
-from ase.io.trajectory import Trajectory
-from asimtools.calculators import load_calc
-from asimtools.utils import get_atoms, join_names
-
-
[docs]def cell_relax( - calc_id: str, - image: Dict, - optimizer: str = 'BFGS', - fmax: float = 0.002, - mask: Optional[Sequence] = None, - prefix: Optional[str] = None, -) -> Dict: - """Relax cell using ASE Optimizer - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param prefix: Prefix to output files, defaults to '' - :type prefix: str, optional - :param optimizer: Optimizer class to use from ase.optimize, defaults to 'BFGS' - :type optimizer: str, optional - :param fmax: Maximum stress in eV/$\AA^3$, defaults to 0.002 - :type fmax: float, optional - :param mask: Mask to constrain cell deformation while relaxing, defaults to None - :type mask: Optional[Sequence], optional - :return: Dictionary of results including, final energy, stress and output files - :rtype: Dict - """ - calc = load_calc(calc_id) - atoms = get_atoms(**image) - atoms.set_calculator(calc) - - if prefix is not None: - prefix = prefix + '_' - else: - prefix = '' - - traj_file = join_names([prefix, 'cell_relax.traj'])[:-2] # Don't include __ - sf = StrainFilter(atoms, mask=mask) - dyn = getattr(ase.optimize, optimizer)(sf) - traj = Trajectory( - traj_file, - 'a', - atoms, - properties=['energy', 'forces', 'stress'], - ) - dyn.attach(traj) - try: - dyn.run(fmax=fmax) - except Exception: - print('Failed to optimize atoms') - raise - - image_file = join_names([prefix, 'image_output.xyz'])[:-2] - atoms.write(image_file, format='extxyz') - - energy = float(atoms.get_potential_energy()) - final_fmax = float(atoms.get_stress().max()) - - results = { - 'energy': energy, - 'final_fmax': final_fmax, - 'files':{ - 'image': image_file, - 'traj': traj_file, - } - } - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/geometry_optimization/optimize.html b/_build/_modules/asimtools/asimmodules/geometry_optimization/optimize.html deleted file mode 100644 index 3dba6a0..0000000 --- a/_build/_modules/asimtools/asimmodules/geometry_optimization/optimize.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - asimtools.asimmodules.geometry_optimization.optimize — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.geometry_optimization.optimize

-#!/usr/bin/env python
-'''
-Relaxes both atoms and cell coordinates simultaneously.
-
-Author: mkphuthi@github.com
-'''
-from typing import Dict, Optional
-import ase.optimize
-from ase.constraints import ExpCellFilter
-from ase.io.trajectory import Trajectory
-from asimtools.calculators import load_calc
-from asimtools.utils import get_atoms
-
-
[docs]def optimize( - calc_id: str, - image: Dict, - optimizer: str = 'BFGS', - fmax: float = 0.003, #Roughly 0.48GPa - optimizer_args: Optional[Dict] = None, - expcellfilter_args: Optional[Dict] = None, -) -> Dict: - """Relaxes cell (and atoms) using ase.constraints.ExpCellFilter while retaining symmetry - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param optimizer: Any optimizer from ase.optimize, defaults to 'BFGS' - :type optimizer: str, optional - :param fmax: fmax in optimizer, defaults to 0.003 which is ~0.48GPa - :type fmax: float, optional - :param expcellfilter_args: arguments for ase.constraints.ExpCellFilter, defaults to None - :type expcellfilter_args: Optional[Dict], optional - :return: Results including relaxed structure energy - :rtype: Dict - """ - if expcellfilter_args is None: - expcellfilter_args = {} - if optimizer_args is None: - optimizer_args = {} - - calc = load_calc(calc_id) - atoms = get_atoms(**image) - atoms.set_calculator(calc) - - ecf = ExpCellFilter(atoms, **expcellfilter_args) - - dyn = getattr(ase.optimize, optimizer)(ecf) - traj_file = 'optimize.traj' - traj = Trajectory( - traj_file, - 'a', # If there are multiple relaxations, we keep all trajectories - atoms, - properties=['energy', 'forces', 'stress'], - ) - dyn.attach(traj) - try: - dyn.run(fmax=fmax) - except Exception: - print('Failed to optimize atoms') - raise - - image_file = 'image_output.xyz' - atoms.write(image_file, format='extxyz') - - energy = float(atoms.get_potential_energy()) - final_fmax = float(atoms.get_stress().max()) - - results = { - 'energy': energy, - 'final_fmax': final_fmax, - 'files':{ - 'image': image_file, - 'traj': traj_file, - } - } - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/geometry_optimization/symmetric_cell_relax.html b/_build/_modules/asimtools/asimmodules/geometry_optimization/symmetric_cell_relax.html deleted file mode 100644 index 97d1499..0000000 --- a/_build/_modules/asimtools/asimmodules/geometry_optimization/symmetric_cell_relax.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - asimtools.asimmodules.geometry_optimization.symmetric_cell_relax — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.geometry_optimization.symmetric_cell_relax

-#!/usr/bin/env python
-'''
-Relaxes structure using ASE while retaining symmetry. Requires ASE>=3.23
-
-Author: mkphuthi@github.com
-'''
-from typing import Dict, Optional
-import ase.optimize
-from ase.constraints import ExpCellFilter
-from ase.spacegroup.symmetrize import FixSymmetry
-from ase.io.trajectory import Trajectory
-from asimtools.calculators import load_calc
-from asimtools.utils import get_atoms
-
-
[docs]def symmetric_cell_relax( - calc_id: str, - image: Dict, - optimizer: str = 'BFGS', - fmax: float = 0.003, #Roughly 0.48GPa - optimizer_args: Optional[Dict] = None, - fixsymmetry_args: Optional[Dict] = None, - expcellfilter_args: Optional[Dict] = None, -) -> Dict: - """Relaxes cell (and atoms) using ase.constraints.ExpCellFilter while retaining symmetry - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param optimizer: Any optimizer from ase.optimize, defaults to 'BFGS' - :type optimizer: str, optional - :param fmax: fmax in optimizer, defaults to 0.003 which is ~0.48GPa - :type fmax: float, optional - :param fixsymmetry_args: arguments for ase.constraints.FixSymmetry, defaults to None - :type fixsymmetry_args: Optional[Dict], optional - :param expcellfilter_args: arguments for ase.constraints.ExpCellFilter, defaults to None - :type expcellfilter_args: Optional[Dict], optional - :return: Results including relaxed structure energy - :rtype: Dict - """ - if fixsymmetry_args is None: - fixsymmetry_args = {} - if expcellfilter_args is None: - expcellfilter_args = {} - if optimizer_args is None: - optimizer_args = {} - - calc = load_calc(calc_id) - atoms = get_atoms(**image) - atoms.set_calculator(calc) - - atoms.set_constraint(FixSymmetry(atoms, **fixsymmetry_args)) - ecf = ExpCellFilter(atoms, **expcellfilter_args) - - dyn = getattr(ase.optimize, optimizer)(ecf) - traj_file = 'cell_relax.traj' - traj = Trajectory( - traj_file, - 'a', - atoms, - properties=['energy', 'forces', 'stress'], - ) - dyn.attach(traj) - try: - dyn.run(fmax=fmax) - except Exception: - print('Failed to optimize atoms') - raise - - image_file = 'image_output.xyz' - atoms.write(image_file, format='extxyz') - - energy = float(atoms.get_potential_energy()) - final_fmax = float(atoms.get_stress().max()) - - results = { - 'energy': energy, - 'final_fmax': final_fmax, - 'files':{ - 'image': image_file, - 'traj': traj_file, - } - } - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/lammps/lammps.html b/_build/_modules/asimtools/asimmodules/lammps/lammps.html deleted file mode 100644 index 8a5ec88..0000000 --- a/_build/_modules/asimtools/asimmodules/lammps/lammps.html +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - asimtools.asimmodules.lammps.lammps — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.lammps.lammps

-#!/usr/bin/env python
-'''
-Runs a user defined lammps script or template 
-
-Author: mkphuthi@github.com
-'''
-from typing import Dict, Optional
-from pathlib import Path
-import subprocess
-import logging
-from asimtools.utils import (
-    get_atoms,
-)
-
-
[docs]def lammps( - template: str, - image: Optional[Dict] = None, - atom_style: str = 'atomic', - variables: Optional[Dict] = None, - lmp_cmd: str = 'lmp', - masses: bool = True, -) -> Dict: - """Runs a lammps script based on a specified template, variables can be - specified as arguments to be defined in the final LAMMPS input file if - placeholders are put in the template - - :param template: path to lammps input template file - :type template: str - :param image: Initial image for MD simulation. Image specification, see :func:`asimtools.utils.get_atoms`, defaults to None - :type image: Dict, optional - :param atom_style: LAMMPS style in which to write image to Lammps data input e.g. full, atomic etc., defaults to 'atomic' - :type atom_style: str, optional - :param variables: Dictionary of variables to be defined into the lammps input, defaults to None - :type variables: Dict, optional - :param lmp_cmd: Command with which to run LAMMPS, defaults to 'lmp' - :type lmp_cmd: str, optional - :param masses: Whether to specify atomic masses in LAMMPS data input, requires ASE>3.23.0, defaults to True - :type masses: bool, optional - :return: LAMMPS out file names - :rtype: Dict - """ ''' - Runs a lammps simulation based on a template lammps input script - ''' - if variables is None: - variables = {} - - # Make sure the provided asimmodule follows standard for reading - # in arbitrary image provided by asimtools - if image is not None: - atoms = get_atoms(**image) - if masses: - atoms.write( - 'image_input.lmpdat', - format='lammps-data', - atom_style=atom_style, - masses=masses, - ) - else: - atoms.write( - 'image_input.lmpdat', - format='lammps-data', - atom_style=atom_style, - ) - variables['IMAGE_FILE'] = 'image_input.lmpdat' - - lmp_txt = '' - for variable, value in variables.items(): - lmp_txt += f'variable {variable} equal {value}\n' - - lmp_txt += '\n' - template = Path(template).resolve() - with open(template, 'r', encoding='utf-8') as f: - lines = f.readlines() - - for line in lines: - lmp_txt += line - - if image is not None: - assert 'read_data ' in lmp_txt, \ - 'Make sure "read_data image_input.lmpdat" command is used \ - (with correct atom style) appropriately in lammps input \ - file if you specify image keyword' - - lmp_inp_file = 'input.lammps' - with open(lmp_inp_file, 'w', encoding='utf-8') as f: - f.write(lmp_txt) - - command = lmp_cmd + f' -i {lmp_inp_file}' - command = command.split(' ') - completed_process = subprocess.run( - command, check=False, capture_output=True, text=True, - ) - - with open('lmp_stdout.txt', 'w', encoding='utf-8') as f: - f.write(completed_process.stdout) - - if completed_process.returncode != 0: - err_txt = f'Failed to run {lmp_inp_file}\n' - err_txt += 'See lmp.stderr.txt for details.' - logging.error(err_txt) - with open('lmp_stderr.txt', 'w', encoding='utf-8') as f: - f.write(completed_process.stderr) - completed_process.check_returncode() - return {} - - results = {'files': { - 'log': 'log.lammps', - 'thermo': 'log.lammps', - }} - - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/phonons/ase_phonons.html b/_build/_modules/asimtools/asimmodules/phonons/ase_phonons.html deleted file mode 100644 index cce8b8e..0000000 --- a/_build/_modules/asimtools/asimmodules/phonons/ase_phonons.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - asimtools.asimmodules.phonons.ase_phonons — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.phonons.ase_phonons

-#!/usr/bin/env python
-'''
-Relaxes the given atomic structure using ASE's built-in structure
-optimizers
-'''
-
-from typing import Dict, Sequence
-import logging
-import json
-import numpy as np
-import matplotlib.pyplot as plt
-from ase.phonons import Phonons
-from asimtools.calculators import load_calc
-from asimtools.utils import get_atoms
-
-
[docs]def ase_phonons( - calc_id: str, - image: Dict, - path: str, - delta: float = 0.01, - kpts: Sequence[int] = (20, 20, 20), - supercell: Sequence[int] = (5,5,5), -) -> Dict: - """Calculates phonon spectrum and DOS using ASE - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param path: Path in BZ for plot - :type path: str - :param delta: delta in ASE phonons, defaults to 0.01 - :type delta: float, optional - :param kpts: kpts in ASE phonons, defaults to (20, 20, 20) - :type kpts: Sequence[int], optional - :param supercell: repeat of image to use as supercell, defaults to (5,5,5) - :type supercell: Sequence[int], optional - :return: Empty dictionary - :rtype: Dict - """ - - atoms = get_atoms(**image) - calc = load_calc(calc_id) - - ph = Phonons(atoms, calc, supercell=supercell, delta=delta) - try: - ph.run() - except ValueError: - logging.error('Failed to run phonon calculation, check calculator') - raise - - ph.read(acoustic=True) - ph.clean() - - npoints = 100 - path = atoms.cell.bandpath(path, npoints=npoints) - bs = ph.get_band_structure(path) - - bs.write('bs.json') - - dos = ph.get_dos(kpts=kpts).sample_grid(npts=100, width=1e-3) - # dos_data = np.transpose( - # np.vstack([dos.get_weights(), dos.get_energies()]) - # ) - - dos_file = 'dos.json' - with open(dos_file, 'w', encoding='utf-8') as f: - json.dump({ - 'weights': dos.get_weights().tolist(), - 'energies': dos.get_energies().tolist(), - }, f, indent=2 - ) - - # Plotting - fig = plt.figure(1, figsize=(7, 4)) - ax = fig.add_axes([.12, .07, .67, .85]) - - emax = np.max(bs.energies) * 1.01 - bs.plot(ax=ax, emin=0.0, emax=emax) - - dosax = fig.add_axes([.8, .07, .17, .85]) - dosax.fill_between( - dos.get_weights(), - dos.get_energies(), - y2=0, - color='grey', - edgecolor='k', - lw=1 - ) - - dosax.set_ylim(0, emax) - dosax.set_yticks([]) - dosax.set_xticks([]) - dosax.set_xlabel("DOS", fontsize=18) - fig.savefig('phonons.png') - plt.close(fig) - - return {}
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/singlepoint.html b/_build/_modules/asimtools/asimmodules/singlepoint.html deleted file mode 100644 index d52e8b0..0000000 --- a/_build/_modules/asimtools/asimmodules/singlepoint.html +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - asimtools.asimmodules.singlepoint — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.singlepoint

-#!/usr/bin/env python
-'''
-Calculates single point energy 
-
-Author: mkphuthi@github.com
-'''
-
-from typing import Tuple, Dict, Optional
-import logging
-from asimtools.calculators import load_calc
-from asimtools.utils import (
-    get_atoms,
-)
-
-
[docs]def singlepoint( - calc_id: str, - image: Dict, - properties: Tuple[str] = ('energy', 'forces'), - prefix: Optional[str] = None, -) -> Dict: - """Evaluates the properties of a single image, currently implemented - properties are energy, forces and stress - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param properties: properties to evaluate, defaults to ('energy', 'forces') - :type properties: Tuple[str], optional - :return: Dictionary of results - :rtype: Dict - """ - calc = load_calc(calc_id) - atoms = get_atoms(**image) - atoms.set_calculator(calc) - - if prefix is not None: - prefix = prefix + '_' - else: - prefix = '' - import time; time.sleep(20) - if 'energy' in properties: - try: - energy = atoms.get_potential_energy() - logging.debug('Calculated energy') - except Exception: - logging.error('Failed to calculate energy') - raise - - if 'forces' in properties: - try: - atoms.get_forces() - logging.debug('Calculated forces') - except Exception: - logging.error('Failed to calculate forces') - raise - - if 'stress' in properties: - try: - atoms.get_stress() - logging.debug('Calculated stress') - except Exception: - logging.error('Failed to calculate stress') - raise - - image_file = prefix + 'image_output.xyz' - atoms.write(image_file, format='extxyz') - - results = { - 'energy': float(energy), - 'files': {'image': image_file} - } - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/surface_energies/surface_energies.html b/_build/_modules/asimtools/asimmodules/surface_energies/surface_energies.html deleted file mode 100644 index 18ae851..0000000 --- a/_build/_modules/asimtools/asimmodules/surface_energies/surface_energies.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - asimtools.asimmodules.surface_energies.surface_energies — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.surface_energies.surface_energies

-#!/usr/bin/env python
-'''
-Calculates surface energies of slabs defined by args specified for
-pymatgen.core.surface.generate_all_slabs()
-
-Author: mkphuthi@github.com
-'''
-
-from typing import Dict, Sequence, Union, Optional
-from copy import copy
-import logging
-import numpy as np
-from pymatgen.core.surface import generate_all_slabs
-from pymatgen.io.ase import AseAtomsAdaptor as AAA
-from asimtools.calculators import load_calc
-from asimtools.asimmodules.geometry_optimization.atom_relax import atom_relax
-from asimtools.utils import (
-    get_atoms,
-)
-
-
[docs]def get_surface_energy(slab, calc, bulk_e_per_atom): - a1 = slab.get_cell()[0] - a2 = slab.get_cell()[1] - area = np.abs(np.cross(a1, a2)[2]) - slab.calc = calc - converged = True - try: - slab_en = slab.get_potential_energy() - except: - converged = False - if converged: - nslab = len(slab) - surf_en = (slab_en - nslab * bulk_e_per_atom) / (2 * area) - else: - surf_en = None - return converged, surf_en, slab_en, area
- -
[docs]def surface_energies( - calc_id: str, - image: Dict, - millers: Union[str,Sequence] = 'all', - atom_relax_args: Optional[Dict] = None, - generate_all_slabs_args: Optional[Dict] = None, -) -> Dict: - """Calculates surface energies of slabs defined by args specified for - pymatgen.core.surface.generate_all_slabs() - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param millers: List of miller indices to consider in the form 'xyz', - defaults to 'all' - :type millers: Union[str,Sequence], optional - :param atom_relax_args: Args to pass to - :func:`asimtools.asimmodules.geometry_optimization.atom_relax.atom_relax`, - defaults to None - :type atom_relax_args: Optional[Dict], optional - :param generate_all_slabs_args: Args to pass to - :func:`pymatgen.core.surface.generate_all_slabs`, defaults to None - :type generate_all_slabs_args: Optional[Dict], optional - :return: _description_ - :rtype: Dict - """ - - calc = load_calc(calc_id) - bulk = get_atoms(**image) - bulk.set_calculator(calc) - - if atom_relax_args is None: - atom_relax_args = {} - - default_pymatgen_kwargs = { - 'max_index': 3, - 'min_slab_size': 14, - 'min_vacuum_size': 10, - 'max_normal_search': True, - 'symmetrize': True, - } - - pymargs = copy(default_pymatgen_kwargs) - pymargs.update(generate_all_slabs_args) - - bulk_struct = AAA.get_structure(bulk) - slabs = generate_all_slabs( - bulk_struct, - **pymargs - ) - - logging.info('Generated %s distinct slabs', len(slabs)) - n_bulk = len(bulk) - bulk_e_per_atom = bulk.get_potential_energy() / n_bulk - bulk.write('bulk.xyz') - - slab_dict = {} - for s, slab in enumerate(slabs): - big_slab = slab.copy() - mindex = slab.miller_index - miller = f'{mindex[0]}{mindex[1]}{mindex[2]}' - if millers == 'all' or miller in millers: - logging.info('Calculating for %s', miller) - atoms = AAA.get_atoms(big_slab) - atoms.write(f'{miller}.xyz') - - relax_results = atom_relax( - calc_id=calc_id, - image={'atoms': atoms}, - optimizer=atom_relax_args.get('optimizer', 'BFGS'), - properties=('energy','forces'), - fmax=atom_relax_args.get('fmax', 0.01), - prefix=f'{miller}_relaxed' - ) - atoms = get_atoms( - image_file = relax_results.get('files', {}).get('image') - ) - - assert np.allclose(atoms.pbc, (True, True, True)), \ - f'Check pbcs for {miller}: {atoms.pbc}' - assert atoms.cell[2][2] > pymargs['min_vacuum_size'] + \ - pymargs['min_slab_size'], \ - f'Check layer number and vacuum for {miller}' - assert miller not in slab_dict, \ - f'Multiple terminations for {miller}' - - slab_dict[miller] = {} - converged, surf_en, slab_en, area = get_surface_energy( - atoms, load_calc(calc_id), bulk_e_per_atom - ) - - if converged: - slab_dict[miller]['surf_energy'] = float(surf_en) - slab_dict[miller]['natoms'] = len(atoms) - slab_dict[miller]['slab_energy'] = float(slab_en) - slab_dict['bulk_energy_per_atom'] = float(bulk_e_per_atom) - slab_dict[miller]['area'] = float(area) - atoms.write(f'{miller}.xyz') - - results = { - 'surface_energies': slab_dict, - } - - return results # Always return a dictionary! Use {} if necessary
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/template.html b/_build/_modules/asimtools/asimmodules/template.html deleted file mode 100644 index df87a41..0000000 --- a/_build/_modules/asimtools/asimmodules/template.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - asimtools.asimmodules.template — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.template

-#!/usr/bin/env python
-'''
-Describe the asimmodule briefly here. If this is a asimmodule that runs multiple steps,
-describe it here using reStructuredText to generate autodocs
-
-Cite the papers where the method/asimmodule was first introduced here as well
-
-Author: mkphuthi@github.com
-'''
-
-from typing import Dict 
-# from asimtools.calculators import load_calc
-# from asimtools.utils import (
-#     get_atoms,
-#     get_images,
-# )
-
-
[docs]def template( - # calc_id: str, - # image: Dict, # Optional: if using a structure - # images: Dict, # Optional: if using multiple structures -) -> Dict: - ''' - asimmodule does xyz - ''' - - # Some useful lines - # calc = load_calc(calc_id) - # atoms = get_atoms(**image) - # images = get_images(**images) - - ############################# - # Do some cool science here # - ############################# - - results = { - 'my_result': 'placeholder_for_my_result', - 'files': {'file_description': 'placeholder_for_output_file'} - } - return results # Always return a dictionary! Use {} if necessary
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/transformations/scale_unit_cells.html b/_build/_modules/asimtools/asimmodules/transformations/scale_unit_cells.html deleted file mode 100644 index 582fcf5..0000000 --- a/_build/_modules/asimtools/asimmodules/transformations/scale_unit_cells.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - - asimtools.asimmodules.transformations.scale_unit_cells — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.transformations.scale_unit_cells

-'''
-Produce a set of images with unit cells scaled compared to the input
-
-author: mkphuthi@github.com
-'''
-
-from typing import Dict, Optional, Sequence
-import numpy as np
-from ase.io import write
-from asimtools.utils import (
-    get_atoms,
-)
-
-
[docs]def apply_scale(old_atoms, scale): - ''' Applies a scaling factor to a unit cell ''' - atoms = old_atoms.copy() - new_cell = atoms.get_cell() * scale - atoms.set_cell(new_cell, scale_atoms=True) - atoms.info['scale'] = f'{scale:.3f}' - return atoms
- -
[docs]def scale_unit_cells( - image: Dict, - scales: Optional[Sequence] = None, - logspace: Optional[Sequence] = None, - linspace: Optional[Sequence] = None, - scale_by: str = 'a', -) -> Dict: - """Produce a set of images with unit cells scaled compared to the input - - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param scales: Scaling values by which to scale cell, defaults to None - :type scales: Optional[Sequence], optional - :param logspace: Parameters to pass to np.logspace for scaling values, - defaults to None - :type logspace: Optional[Sequence], optional - :param linspace: Parameters to pass to np.linspace for scaling values, - defaults to None - :type linspace: Optional[Sequence], optional - :param scale_by: Scale either "volume" or "a" which is lattice parameter, - defaults to 'a' - :type scale_by: str, optional - :raises ValueError: If more than one of scales, linspace, logspace are - provided - :return: Path to xyz file - :rtype: Dict - """ - - assert scale_by in ['volume', 'a'], \ - 'Only scaling by "a" and "volume" allowed' - - if (scales is None and linspace is None and logspace is not None): - scales = np.logspace(*logspace) - elif (scales is None and linspace is not None and logspace is None): - scales = np.linspace(*linspace) - elif (scales is not None and linspace is None and logspace is None): - pass - else: - raise ValueError( - 'Provide only one of factors, factor_logspacem factor_linspace' - ) - - atoms = get_atoms(**image) - - scales = np.array(scales) - if scale_by == 'volume': - scales = scales**(1/3) - - # Make a database of structures with the volumes scaled appropriately - scaled_images = [] - for scale in scales: - new_atoms = apply_scale(atoms, scale) - scaled_images.append(new_atoms) - - scaled_images_file = 'scaled_unitcells_output.xyz' - write(scaled_images_file, scaled_images, format='extxyz') - - return {'files': {'images': scaled_images_file}}
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/vacancy_formation_energy/vacancy_formation_energy.html b/_build/_modules/asimtools/asimmodules/vacancy_formation_energy/vacancy_formation_energy.html deleted file mode 100644 index a0a3d3f..0000000 --- a/_build/_modules/asimtools/asimmodules/vacancy_formation_energy/vacancy_formation_energy.html +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy

-#!/usr/bin/env python
-'''
-Calculates the monovacancy formation energy from a bulk structure
-
-Author: mkphuthi@github.com
-'''
-
-from typing import Dict, Sequence, Optional
-import logging
-from asimtools.calculators import load_calc
-from asimtools.asimmodules.geometry_optimization.atom_relax import atom_relax
-from asimtools.asimmodules.geometry_optimization.optimize import optimize
-from asimtools.utils import (
-    get_atoms,
-)
-
-
[docs]def vacancy_formation_energy( - calc_id: str, - image: Dict, - vacancy_index: int = 0, - atom_relax_args: Optional[Dict] = None, - optimize_args: Optional[Dict] = None, - repeat: Optional[Sequence] = (1,1,1) -) -> Dict: - """Calculates the monovacancy formation energy from a bulk structure - - :param calc_id: calc_id specification - :type calc_id: str - :param image: Image specification, see :func:`asimtools.utils.get_atoms` - :type image: Dict - :param vacancy_index: Index of atom to remove, defaults to 0 - :type vacancy_index: int, optional - :param atom_relax_args: Args to pass to - :func:`asimtools.asimmodules.geometry_optimization.atom_relax.atom_relax`, - this applies if you do not want to optimize the cell at all - defaults to None - :type atom_relax_args: Optional[Dict], optional - :param optimize_args: Args to pass to - :func:`asimtools.asimmodules.geometry_optimization.optimize.optimize`, - this applies if you want to optimize both the cell and positions - defaults to None - :type optimize_args: Optional[Dict], optional - :param repeat: Repeat to apply to image to create supercell, defaults to - None - :type repeat: Optional[Sequence], optional - :return: Empty dictionary - :rtype: Dict - """ - - calc = load_calc(calc_id) - bulk = get_atoms(**image).repeat(repeat) - bulk.set_calculator(calc) - - vacant = bulk.copy() - del vacant[vacancy_index] - - try: - bulk_e = calc.get_potential_energy(bulk) - logging.info('Finished bulk calculation') - except ValueError: - logging.error("Failed to calculate energy of bulk structure, " - "see calculator output") - raise - - bulk.write('bulk_image_output.xyz') - - if atom_relax_args is not None: - try: - relax_results = atom_relax( - calc_id=calc_id, - image={'atoms': vacant}, - optimizer=atom_relax_args.get('optimizer', 'BFGS'), - properties=('energy','forces'), - fmax=atom_relax_args.get('fmax', 0.01), - prefix=f'vacant_relaxed', - ) - logging.info('Relaxed vacant structure') - except ValueError: - logging.error("Failed to calculate energy of bulk structure, " - "see calculator output") - raise - else: - try: - relax_results = optimize( - calc_id=calc_id, - image={'atoms': vacant}, - # optimizer=optimize_args.get('optimizer', 'BFGS'), - # fmax=atom_relax_args.get('fmax', 0.003), - # prefix=f'vacant_optimized', - **optimize_args, - ) - logging.info('Relaxed vacant structure') - except ValueError: - logging.error("Failed to calculate energy of bulk structure, " - "see calculator output") - raise - - vacant_e = relax_results['energy'] - vac_form_e = vacant_e - (len(vacant) / len(bulk) * bulk_e) - - res_dict = {} - res_dict['bulk_e'] = float(bulk_e) - res_dict['vacant_e'] = float(vacant_e) - res_dict['bulk_n'] = len(bulk) - res_dict['vfe'] = float(vac_form_e) - - results = {'vfe': res_dict} - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/workflows/calc_array.html b/_build/_modules/asimtools/asimmodules/workflows/calc_array.html deleted file mode 100644 index cbe479b..0000000 --- a/_build/_modules/asimtools/asimmodules/workflows/calc_array.html +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - asimtools.asimmodules.workflows.calc_array — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.workflows.calc_array

-#!/usr/bin/env python
-'''
-Apply the same asimmodule using multiple calculators
-
-Author: mkphuthi@github.com
-
-'''
-
-from typing import Dict, Sequence, Optional, Union
-from copy import deepcopy
-from asimtools.job import DistributedJob
-from asimtools.utils import (
-    get_calc_input,
-    change_dict_value,
-)
-from asimtools.asimmodules.workflows.utils import prepare_array_vals
-
-
[docs]def calc_array( - subsim_input: Dict, - calc_ids: Sequence[str] = None, - template_calc_id: Optional[str] = None, - key_sequence: Optional[Sequence[str]] = None, - array_values: Optional[Sequence] = None, - file_pattern: Optional[str] = None, - linspace_args: Optional[Sequence] = None, - arange_args: Optional[Sequence] = None, - label_prefix: Optional[str] = None, - env_ids: Optional[Union[Sequence[str],str]] = None, - calc_input: Optional[Dict] = None, - env_input: Optional[Dict] = None, - labels: Optional[Union[Sequence,str]] = 'values', - str_btn_args: Optional[Dict] = None, - secondary_key_sequences: Optional[Sequence] = None, - secondary_array_values: Optional[Sequence] = None, - array_max: Optional[int] = None, -) -> Dict: - """Apply the same asimmodule using different calculators and if necessary - different environments - - :param calc_ids: Iterable with calc_ids, defaults to None - :type calc_ids: Sequence, optional - :param calc_input: Dictionary of calculator inputs - :type calc_input: Dictionary, optional - :param labels: Iterable with custom labels for each calc, defaults to None - :type labels: Sequence, optional - :param array_values: values to be iterated over in each simulation, - defaults to None - :type array_values: Optional[Sequence], optional - :param file_pattern: pattern of files to be iterated over in each - simulation, defaults to None - :type file_pattern: Optional[str], optional - :param linspace_args: arguments to pass to :func:`numpy.linspace` to be - iterated over in each simulation, defaults to None - :type linspace_args: Optional[Sequence], optional - :param arange_args: arguments to pass to :func:`numpy.arange` to be - iterated over in each simulation, defaults to None - :type arange_args: Optional[Sequence], optional - :param label_prefix: Prefix to add before labels which can make extracting - data from file paths easier, defaults to None - :type label_prefix: str, optional - :param env_ids: Environment(s) to be used for each simulation, must either - be a list with as many env_ids as array values or a string with the - env_id to be used by all simulations, defaults to None - :type env_ids: Optional[Union[Sequence[str],str]], optional - :param secondary_key_sequences: list of other keys to iterate over in - tandem with key_sequence to allow changing multiple key-value pairs, - defaults to None - :type secondary_key_sequences: Sequence, optional - :param secondary_array_values: list of other other array_values to iterate - over in tandem with array_values to allow changing multiple key-value - pairs, defaults to None - :type secondary_array_values: Sequence, optional - :return: Dictionary of results - :rtype: Dict - """ - print([ - array_values, linspace_args, arange_args, file_pattern - ]) - using_array_values = key_sequence is not None\ - and template_calc_id is not None\ - and [ - array_values, linspace_args, arange_args, file_pattern - ].count(None) == 3 - err_txt = 'Specify either a sequence of "calc_ids" or all of ' - err_txt += '"key_sequence", "template_calc_id" and one of [' - err_txt += '"array_values", "linspace_args", "arange_args", "file_pattern"' - err_txt += '] to iterate over' - assert calc_ids is not None or using_array_values, err_txt - - if using_array_values: - if calc_input is None: - calc_input = get_calc_input() - calc_params = calc_input[template_calc_id] - new_calc_input = {} - - if calc_ids is not None and labels is None: - labels = calc_ids - - results = prepare_array_vals( - key_sequence=key_sequence, - array_values=array_values, - file_pattern=file_pattern, - linspace_args=linspace_args, - arange_args=arange_args, - env_ids=env_ids, - labels=labels, - label_prefix=label_prefix, - str_btn_args=str_btn_args, - secondary_key_sequences=secondary_key_sequences, - secondary_array_values=secondary_array_values, - ) - array_values = results['array_values'] - labels = results['labels'] - env_ids = results['env_ids'] - secondary_array_values = results['secondary_array_values'] - secondary_key_sequences = results['secondary_key_sequences'] - - for i, val in enumerate(array_values): - new_calc_params = change_dict_value( - d=calc_params, - new_value=val, - key_sequence=key_sequence, - return_copy=True, - ) - if secondary_array_values is not None: - for k, vs in zip(secondary_key_sequences, secondary_array_values): - new_calc_params = change_dict_value( - d=new_calc_params, - new_value=vs[i], - key_sequence=k, - return_copy=False, - ) - - new_calc_input[labels[i]] = new_calc_params - - calc_input = new_calc_input - calc_ids = labels - - elif calc_ids is not None: - assert labels != 'get_str_btn', \ - 'get_str_btn only works when using the key_sequence argument.' - if labels is None or labels == 'values': - labels = calc_ids - - assert len(labels) == len(calc_ids), \ - 'Num. of calc_ids or array_values must match num. of labels' - - if env_ids is not None: - assert len(env_ids) == len(calc_ids) or isinstance(env_ids, str), \ - 'Provide one env_id or as many as there are calc_ids/array_values' - - array_sim_input = {} - - # Make individual sim_inputs for each calc - for i, calc_id in enumerate(calc_ids): - new_subsim_input = deepcopy(subsim_input) - new_subsim_input['args']['calc_id'] = calc_id - array_sim_input[f'{labels[i]}'] = new_subsim_input - - if env_ids is not None: - if isinstance(env_ids, str): - new_subsim_input['env_id'] = env_ids - else: - new_subsim_input['env_id'] = env_ids[i] - - # Create a distributed job object - djob = DistributedJob(array_sim_input, env_input, calc_input) - job_ids = djob.submit(array_max=array_max) - - results = {'job_ids': job_ids} - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/workflows/chained.html b/_build/_modules/asimtools/asimmodules/workflows/chained.html deleted file mode 100644 index c91f3da..0000000 --- a/_build/_modules/asimtools/asimmodules/workflows/chained.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - asimtools.asimmodules.workflows.chained — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.workflows.chained

-#!/usr/bin/env python
-'''
-Submits a chain of asimmodules in the order specified by steps
-in input
-
-Author: mkphuthi@github.com
-
-'''
-
-from typing import Dict, Optional
-from asimtools.job import ChainedJob
-
-
-
[docs]def chained( - steps: Dict, - env_input: Optional[Dict] = None, - calc_input: Optional[Dict] = None, -) -> Dict: - """Run a workflow using the provided sim_input.yaml one after the other, - The jobs will run one after the other, if slurm is used, job dependencies - will be used. Note that if one of the subsim_inputs internally launches another - asimmodule e.g. image_array, calc_array etc, slurm job dependencies will not - work as expected. In those cases, we recommend running the steps one by one - or interactively - - - :param steps: Dictionary where each key is an ID and the value is a \ - standard sim_input - :type steps: Dict - :param env_input: env_input that overrides global file, defaults to None - :type env_input: Optional[Dict], optional - :param calc_input: calc_input that overrides global file, defaults to None - :type calc_input: Optional[Dict], optional - :return: Dictionary of results - :rtype: Dict - """ - cjob = ChainedJob( - sim_input=steps, env_input=env_input, calc_input=calc_input - ) - job_ids = cjob.submit() - - results = cjob.unitjobs[-1].get_output() - results.update({'job_ids': job_ids}) - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/workflows/distributed.html b/_build/_modules/asimtools/asimmodules/workflows/distributed.html deleted file mode 100644 index 4fb3909..0000000 --- a/_build/_modules/asimtools/asimmodules/workflows/distributed.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - asimtools.asimmodules.workflows.distributed — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.workflows.distributed

-#!/usr/bin/env python
-'''
-Distributes a number of simulations at the same time if possible
-
-Author: mkphuthi@github.com
-
-'''
-
-from typing import Dict, Optional
-from asimtools.job import DistributedJob
-
-
[docs]def distributed( - subsim_inputs: Dict, - env_input: Optional[Dict] = None, - calc_input: Optional[Dict] = None, - array_max: Optional[int] = None, -) -> Dict: - """Distributes a set of jobs based on inpout parameter. The scnarios are - as follows: - #. use_slurm: False, interactive: True -> Runs one after the other. - #. use_slurm: True, interactive: False, same env_id -> Launches a job \ - # array. - #. use_slurm: False, interactive: False, different env_ids -> Launches \ - # multiple jobs. - - :param subsim_inputs: Dictionary of asimmodules, each key is an ID and each \ - value is a sim_input file - :type subsim_inputs: Dict - :param env_input: env_input that overrides global file, defaults to None - :type env_input: Optional[Dict], optional - :param calc_input: calc_input that overrides global file, defaults to None - :type calc_input: Optional[Dict], optional - :param array_max: Maximum number of jobs to run in array, defaults to None - :type array_max: Optional[int], optional - :return: Dictionary of results - :rtype: Dict - """ - djob = DistributedJob( - sim_input=subsim_inputs, - env_input=env_input, - calc_input=calc_input - ) - job_ids = djob.submit(array_max=array_max) - - results = {'job_ids': job_ids} - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/workflows/image_array.html b/_build/_modules/asimtools/asimmodules/workflows/image_array.html deleted file mode 100644 index 2435c45..0000000 --- a/_build/_modules/asimtools/asimmodules/workflows/image_array.html +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - asimtools.asimmodules.workflows.image_array — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.workflows.image_array

-#!/usr/bin/env python
-'''
-Apply the same asimmodule on multiple images
-
-Author: mkphuthi@github.com
-
-'''
-
-from typing import Dict, Sequence, Optional, Union
-from copy import deepcopy
-from asimtools.job import DistributedJob
-from asimtools.utils import get_images, change_dict_value
-from asimtools.asimmodules.workflows.utils import prepare_array_vals
-
-
[docs]def image_array( - images: Dict, - subsim_input: Dict, - calc_input: Optional[Dict] = None, - env_input: Optional[Dict] = None, - array_max: Optional[int] = None, - key_sequence: Optional[Sequence[str]] = None, - env_ids: Optional[Union[Sequence[str],str]] = None, - labels: Optional[Union[Sequence,str]] = None, - label_prefix: Optional[str] = None, - str_btn_args: Optional[Dict] = None, - secondary_key_sequences: Optional[Sequence] = None, - secondary_array_values: Optional[Sequence] = None, -) -> Dict: - """Submit the same asimmodule on multiple images and if specified, use - different env_ids - - :param images: Images specification, see :func:`asimtools.utils.get_images` - :type images: Dict - :param subsim_input: sim_input of asimmodule to be run - :type subsim_input: Dict - :param calc_input: calc_input to override global file, defaults to None - :type calc_input: Optional[Dict], optional - :param env_input: env_input to override global file, defaults to None - :type env_input: Optional[Dict], optional - :param array_max: Maximum jobs to run simultanteously in job array, \ - defaults to None - :type array_max: Optional[int], optional - :param labels: Custom labels for each image, defaults to None - :type labels: Sequence[str], optional - :param env_ids: Sequence of envs for each image, must be the same length \ - as the total number of images, defaults to None - :type env_ids: Sequence[str], optional - :param labels: Custom labels to use for each simulation, defaults to \ - None - :param label_prefix: Prefix to add before labels which can make extracting - data from file paths easier, defaults to None - :type label_prefix: str, optional - :param secondary_key_sequences: list of other keys to iterate over in - tandem with key_sequence to allow changing multiple key-value pairs, - defaults to None - :type secondary_key_sequences: Sequence, optional - :param secondary_array_values: list of other other array_values to iterate - over in tandem with images to allow changing multiple key-value - pairs, defaults to None - :type secondary_array_values: Sequence, optional - :return: Dictionary of results - :rtype: Dict - """ - images = get_images(**images) - array_values = images - - if labels is None: - labels = [str(i) for i in range(len(array_values))] - results = prepare_array_vals( - array_values=array_values, - key_sequence=key_sequence, - env_ids=env_ids, - labels=labels, - label_prefix=label_prefix, - str_btn_args=str_btn_args, - secondary_key_sequences=secondary_key_sequences, - secondary_array_values=secondary_array_values, - ) - - if key_sequence is None: - key_sequence = ['args', 'image'] - # For backwards compatibility where we don't have to specify image - subsim_input = deepcopy(subsim_input) - subsim_input['args']['image'] = {} - key_sequence += ['atoms'] - - labels = results['labels'] - env_ids = results['env_ids'] - secondary_array_values = results['secondary_array_values'] - secondary_key_sequences = results['secondary_key_sequences'] - - # Create sim_inputs for each array value and to create input for - # a DistributedJob object - array_sim_input = {} - for i, val in enumerate(array_values): - new_sim_input = change_dict_value( - d=subsim_input, - new_value=val, - key_sequence=key_sequence, - return_copy=True, - ) - - if secondary_array_values is not None: - for k, vs in zip(secondary_key_sequences, secondary_array_values): - new_sim_input = change_dict_value( - d=new_sim_input, - new_value=vs[i], - key_sequence=k, - return_copy=False, - ) - - if env_ids is not None: - new_sim_input['env_id'] = env_ids[i] - - array_sim_input[f'{labels[i]}'] = new_sim_input - - # Create a distributed job object - djob = DistributedJob(array_sim_input, env_input, calc_input) - job_ids = djob.submit(array_max=array_max) - - results = {'job_ids': job_ids} - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/asimmodules/workflows/sim_array.html b/_build/_modules/asimtools/asimmodules/workflows/sim_array.html deleted file mode 100644 index a0a432c..0000000 --- a/_build/_modules/asimtools/asimmodules/workflows/sim_array.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - asimtools.asimmodules.workflows.sim_array — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - - -
  • -
  • -
-
-
-
-
- -

Source code for asimtools.asimmodules.workflows.sim_array

-#!/usr/bin/env python
-'''
-Runs the same asimmodule, iterating over multiple values of a specified
-argument based on a sim_input template provided by the user. The tasks are run
-simultaneously if resources are available
-
-Author: mkphuthi@github.com
-
-'''
-
-from typing import Dict, Sequence, Optional, Union
-from copy import deepcopy
-from asimtools.job import DistributedJob
-from asimtools.utils import change_dict_value
-from asimtools.asimmodules.workflows.utils import prepare_array_vals
-
-
[docs]def sim_array( - template_sim_input: Dict, - key_sequence: Optional[Sequence[str]] = None, - array_values: Optional[Sequence] = None, - file_pattern: Optional[str] = None, - linspace_args: Optional[Sequence] = None, - arange_args: Optional[Sequence] = None, - env_ids: Optional[Union[Sequence[str],str]] = None, - calc_input: Optional[Dict] = None, - env_input: Optional[Dict] = None, - labels: Optional[Union[Sequence,str]] = 'values', - label_prefix: Optional[str] = None, - str_btn_args: Optional[Dict] = None, - secondary_key_sequences: Optional[Sequence] = None, - secondary_array_values: Optional[Sequence] = None, - array_max: Optional[int] = None, -) -> Dict: - """Runs the same asimmodule, iterating over multiple values of a specified - argument based on a sim_input template provided by the user - - :param template_sim_input: sim_input containing all the default parameters - :type template_sim_input: Dict - :param key_sequence: Sequence of keys to access value to be iterated over, - defaults to None - :type key_sequence: Optional[Sequence[str]], optional - :param array_values: values to be iterated over in each simulation, - defaults to None - :type array_values: Optional[Sequence], optional - :param file_pattern: pattern of files to be iterated over in each - simulation, defaults to None - :type file_pattern: Optional[str], optional - :param linspace_args: arguments to pass to :func:`numpy.linspace` to be - iterated over in each simulation, defaults to None - :type linspace_args: Optional[Sequence], optional - :param arange_args: arguments to pass to :func:`numpy.arange` to be - iterated over in each simulation, defaults to None - :type arange_args: Optional[Sequence], optional - :param labels: Custom labels to use for each simulation, defaults to None - :type labels: Sequence, optional - :param label_prefix: Prefix to add before labels which can make extracting - data from file paths easier, defaults to None - :type label_prefix: str, optional - :param env_ids: Environment(s) to be used for each simulation, must either - be a list with as many env_ids as array values or a string with the - env_id to be used by all simulations, defaults to None - :type env_ids: Optional[Union[Sequence[str],str]], optional - :param secondary_key_sequences: list of other keys to iterate over in - tandem with key_sequence to allow changing multiple key-value pairs, - defaults to None - :type secondary_key_sequences: Sequence, optional - :param secondary_array_values: list of other other array_values to iterate - over in tandem with array_values to allow changing multiple key-value - pairs, defaults to None - :type secondary_array_values: Sequence, optional - :param array_max: Number of jobs to run at once in scheduler - :type array_max: int, optional - :param calc_input: calc_input file to use, defaults to None - :type calc_input: Optional[Dict], optional - :param env_input: env_input to use, defaults to None - :type env_input: Optional[Dict], optional - :return: Results - :rtype: Dict - """ - - results = prepare_array_vals( - key_sequence=key_sequence, - array_values=array_values, - file_pattern=file_pattern, - linspace_args=linspace_args, - arange_args=arange_args, - env_ids=env_ids, - labels=labels, - label_prefix=label_prefix, - str_btn_args=str_btn_args, - secondary_key_sequences=secondary_key_sequences, - secondary_array_values=secondary_array_values, - ) - array_values = results['array_values'] - labels = results['labels'] - env_ids = results['env_ids'] - secondary_array_values = results['secondary_array_values'] - secondary_key_sequences = results['secondary_key_sequences'] - - # Create sim_inputs for each array value and to create input for - # a DistributedJob object - sim_inputs = {} - for i, val in enumerate(array_values): - if key_sequence is not None: - new_sim_input = change_dict_value( - d=template_sim_input, - new_value=val, - key_sequence=key_sequence, - return_copy=True, - ) - else: - new_sim_input = deepcopy(template_sim_input) - - if secondary_array_values is not None: - for k, vs in zip(secondary_key_sequences, secondary_array_values): - new_sim_input = change_dict_value( - d=new_sim_input, - new_value=vs[i], - key_sequence=k, - return_copy=False, - ) - - if env_ids is not None: - new_sim_input['env_id'] = env_ids[i] - sim_inputs[labels[i]] = new_sim_input - - # Create a distributed job object - djob = DistributedJob(sim_inputs, env_input, calc_input) - job_ids = djob.submit(array_max=array_max) - - results = {'job_ids': job_ids} - return results
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/calculators.html b/_build/_modules/asimtools/calculators.html deleted file mode 100644 index d55e374..0000000 --- a/_build/_modules/asimtools/calculators.html +++ /dev/null @@ -1,366 +0,0 @@ - - - - - - asimtools.calculators — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -

Source code for asimtools.calculators

-'''
-Tools for loading and returning ASE calculator objects for use in simulations
-'''
-import importlib
-import logging
-from typing import Dict, Optional
-from asimtools.utils import get_calc_input
-
-# pylint: disable=import-outside-toplevel
-# pylint: disable=import-error
-
-
[docs]def load_calc( - calc_id: str = None, - calc_input: Optional[Dict] = None -): - """Loads a calculator using given calc_id or calc_input - - :param calc_id: ID/key to use to load calculator from the supplied/global\ - calc_input file, defaults to None - :type calc_id: str, optional - :param calc_input: calc_input dictionary for a single calculator\ - , defaults to None - :type calc_input: Optional[Dict], optional - :return: ASE calculator instance - :rtype: :class:`ase.calculators.calculators.Calculator` - """ - if calc_id is not None: - if calc_input is None: - calc_input = get_calc_input() - try: - calc_params = calc_input[calc_id] - except KeyError as exc: - msg = f'Calculator with calc_id: {calc_id} not found in' - msg += f'calc_input {calc_input}' - raise KeyError(msg) from exc - except AttributeError as exc: - raise AttributeError('No calc_input found') from exc - name = calc_params.get('name', None) - - if 'module' in calc_params: - loader = load_ase_calc - else: - try: - loader = external_calcs[name] - except KeyError as exc: - msg = 'Provide ASE module for calc or use' - msg += f' one of {external_calcs.keys()}' - raise KeyError(msg) from exc - - calc = loader(calc_params=calc_params) - label = calc_params.get('label', name) - calc.label = label - logging.debug('Loaded calculator %s', calc_id) - return calc
- - -
[docs]def load_nequip(calc_params): - """Load NequIP or Allegro calculator - - https://github.com/mir-group/nequip/tree/main - - :param calc_params: args to pass to loader - :type calc_params: Dict - :return: NequIP ase calculator - :rtype: :class:`nequip.ase.nequip_calculator.NequIPCalculator` - """ - from nequip.ase.nequip_calculator import NequIPCalculator - if calc_params.get('float64', False): - import torch - torch.set_default_dtype(torch.float64) - try: - calc = NequIPCalculator.from_deployed_model(**calc_params.get('args', {})) - except Exception as exc: - msg = f"Failed to load NequIP with parameters:\n {calc_params}" - raise RuntimeError(msg) from exc - - return calc
- - -
[docs]def load_dp(calc_params): - """Load Deep Potential Calculator - - https://docs.deepmodeling.com/projects/deepmd/en/master/ - - :param calc_params: args to pass to loader - :type calc_params: Dict - :return: DP calculator - :rtype: :class:`deepmd.calculator.DP` - """ - from deepmd.calculator import DP - - try: - calc = DP(**calc_params['args']) - except Exception: - logging.error("Failed to load DP with parameters:\n %s", calc_params) - raise - - return calc
- - -
[docs]def load_ase_calc(calc_params): - ''' Load any builtin ASE calculator ''' - module_name = calc_params.get('module', '') - try: - module = importlib.import_module(module_name) - except: - logging.error("Check calc module and stderr") - raise - name = calc_params.get('name', None) - try: - calc_class = getattr(module, name) - except: - logging.error("Check calc name and stderr") - raise - calc_args = calc_params.get('args', {}) - try: - calc = calc_class(**calc_args) - except: - logging.error("Check calc args and stderr") - raise - return calc
- -
[docs]def load_chgnet(calc_params): - """Load CHGNet Calculator - - https://chgnet.lbl.gov/#tutorials-and-docs - - :param calc_params: args to pass to loader - :type calc_params: Dict - :return: CHGNet calculator - :rtype: :class:`chgnet.model.dynamics.CHGNetCalculator` - """ - from chgnet.model.dynamics import CHGNetCalculator - if calc_params['args'].get('from_file', False): - calc_params['args'].pop('from_file') - try: - calc = CHGNetCalculator.from_file(**calc_params['args']) - except Exception: - logging.error("Failed to load CHGNet from file with parameters:\ - \n %s", calc_params) - raise - else: - try: - calc = CHGNetCalculator(**calc_params['args']) - except Exception: - logging.error("Failed to load CHGNet with parameters:\n %s", \ - calc_params) - raise - - return calc
- -
[docs]def load_mace(calc_params): - """Load MACE Calculator - - https://github.com/ACEsuit/mace?tab=readme-ov-file - - :param calc_params: args to pass to loader - :type calc_params: Dict - :return: MACE calculator - :rtype: :class:`mace.calculators.mace_mp` - """ - from mace.calculators import mace_mp - - try: - calc = mace_mp(**calc_params['args']) - except Exception: - logging.error("Failed to load MACE with parameters:\n %s", calc_params) - raise - - return calc
- -
[docs]def load_mace_off(calc_params): - """Load MACE Calculator - - https://github.com/ACEsuit/mace?tab=readme-ov-file - - :param calc_params: args to pass to loader - :type calc_params: Dict - :return: MACE-OFF calculator - :rtype: :class:`mace.calculators.mace_mp` - """ - from mace.calculators import mace_off - - try: - calc = mace_off(**calc_params['args']) - except Exception: - logging.error("Failed to load MACE-OFF with parameters:\n %s", calc_params) - raise - - return calc
- -
[docs]def load_espresso_profile(calc_params): - """Load Qunatum Espresso Calculator for ASE>3.22.1. If using older versions - such as the ones available on PyPI or conda-forge, just load it as an ASE - calculator. Until the new ASE version becomes an official release, we will - have to have both for compatibility. The interface however remains that of - ASE <=3.22.1 within ASIMTools for consistency using the `command` keyword - - https://wiki.fysik.dtu.dk/ase/releasenotes.html - - :param calc_params: args to pass to loader - :type calc_params: Dict - :return: Espresso calculator - :rtype: :class:`ase.calculators.espresso.Espresso` - """ - from ase.calculators.espresso import Espresso, EspressoProfile - - if 'command' in calc_params['args']: - command = calc_params['args'].pop('command') - command = command.split() - progind = command.index('pw.x') - argv = command[:progind+1] - else: - argv = ['pw.x'] - - try: - calc = Espresso( - **calc_params['args'], - profile=EspressoProfile(argv=argv) - ) - except Exception: - logging.error("Failed to load MACE-OFF with parameters:\n %s", calc_params) - raise - - return calc
- - -
[docs]def load_m3gnet(calc_params): - """Load and M3GNet calculator - - :param calc_params: parameters to be passed to matgl.ext.ase.M3GNetCalculator. Must include a key "model" that points to the model used to instantiate the potential - :type calc_params: Dict - :return: M3GNet calculator - :rtype: :class:`matgl.ext.ase.M3GNetCalculator` - """ - from matgl.ext.ase import M3GNetCalculator - import matgl - - model = calc_params.pop("model") - try: - pot = matgl.load_model(model) - calc = M3GNetCalculator( - pot, - **calc_params, - ) - except Exception: - logging.error("Failed to load M3GNet with parameters:\n %s", calc_params) - raise - - return calc
- -external_calcs = { - 'NequIP': load_nequip, - 'Allegro': load_nequip, - 'DeepPotential': load_dp, - 'CHGNet': load_chgnet, - 'MACE': load_mace, - 'EspressoProfile': load_espresso_profile, - 'M3GNet': load_m3gnet, -} -
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/job.html b/_build/_modules/asimtools/job.html deleted file mode 100644 index 05c926a..0000000 --- a/_build/_modules/asimtools/job.html +++ /dev/null @@ -1,1018 +0,0 @@ - - - - - - asimtools.job — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -

Source code for asimtools.job

-'''
-Set of tools for handling jobs in slurm, interactively or in the teminal for
-a specific calculator.
-
-Author: mkphuthi@github.com
-'''
-
-import subprocess
-import os
-import pkgutil
-from pathlib import Path
-from datetime import datetime
-import logging
-from glob import glob
-from typing import List, TypeVar, Dict, Tuple, Union
-from copy import deepcopy
-from colorama import Fore
-import ase.io
-from ase.parallel import paropen
-import numpy as np
-from asimtools.utils import (
-    read_yaml,
-    write_yaml,
-    join_names,
-    get_atoms,
-    get_images,
-    get_env_input,
-    get_calc_input,
-    get_logger,
-    check_if_slurm_job_is_running,
-)
-
-Atoms = TypeVar('Atoms')
-
-START_MESSAGE = '+' * 15 + ' ASIMTOOLS START' + '+' * 15 + '\n'
-STOP_MESSAGE = '+' * 15 + ' ASIMTOOLS STOP' + '+' * 15 + '\n'
-
-
[docs]class Job(): - ''' Abstract class for the job object ''' - # pylint: disable=too-many-instance-attributes - def __init__( - self, - sim_input: Dict, - env_input: Union[Dict,None] = None, - calc_input: Union[Dict,None] = None, - ) -> None: - if env_input is None: - env_input = get_env_input() - if calc_input is None: - calc_input = get_calc_input() - self.env_input = deepcopy(env_input) - self.calc_input = deepcopy(calc_input) - self.sim_input = deepcopy(sim_input) - self.workdir = Path(sim_input.get('workdir', '.')).resolve() - - # sim_input will be in workdir from now on so set workdir as a relative - # path, but in this class/subclasses, always use self.workdir - # which is the full path to avoid confusion - self.sim_input['workdir'] = './' - self.launchdir = Path(os.getcwd()) - if self.sim_input.get('src_dir', False): - self.sim_input['src_dir'] = self.launchdir - - self.env_id = self.sim_input.get('env_id', None) - if self.env_id is not None: - self.env = self.env_input[self.env_id] - else: - self.env = { - 'mode': { - 'use_slurm': False, - 'interactive': True, - } - } # Default is to run in current console - -
[docs] def mkworkdir(self) -> None: - ''' Creates the work directory if it doesn't exist ''' - if not self.workdir.exists(): - self.workdir.mkdir()
- -
[docs] def update_status(self, status: str) -> None: - ''' Updates job status to specificied value ''' - self.update_output({'status': status})
- -
[docs] def start(self) -> None: - ''' Updates the output to signal that the job was started ''' - self.update_output({ - 'start_time': datetime.now().strftime('%H:%M:%S, %m/%d/%y') - }) - self.update_status('started')
- -
[docs] def complete(self) -> None: - ''' Updates the output to signal that the job was started ''' - self.update_output({ - 'end_time': datetime.now().strftime('%H:%M:%S, %m/%d/%y') - }) - self.update_status('complete')
- -
[docs] def fail(self) -> None: - ''' Updates status to failed ''' - self.update_status('failed')
- -
[docs] def discard(self) -> None: - ''' Updates status to discarded ''' - self.update_status('discard')
- -
[docs] def go_to_workdir(self) -> None: - ''' Go to workdir ''' - if not self.workdir.exists(): - self.mkworkdir() - os.chdir(self.workdir)
- -
[docs] def leave_workdir(self) -> None: - ''' goes to directory from which job was launched ''' - os.chdir(self.launchdir)
- -
[docs] def add_output_files(self, file_dict: Dict) -> None: - ''' Adds a file to the output file list ''' - files = self.get_output().get('files', {}) - files.update(file_dict) - self.update_output({'files': file_dict})
- -
[docs] def get_sim_input(self) -> Dict: - ''' Get simulation input ''' - return deepcopy(self.sim_input)
- -
[docs] def get_calc_input(self) -> Dict: - ''' Get calculator input ''' - return deepcopy(self.calc_input)
- -
[docs] def get_env_input(self) -> Dict: - ''' Get environment input ''' - return deepcopy(self.env_input)
- -
[docs] def get_output_yaml(self) -> Dict: - ''' Get current output file ''' - out_fname = 'output.yaml' - output_yaml = self.workdir / out_fname - return output_yaml
- -
[docs] def get_workdir(self) -> Path: - ''' Get working directory ''' - return self.workdir
- -
[docs] def get_output(self) -> Dict: - ''' Get values in output.yaml ''' - output_yaml = self.get_output_yaml() - if output_yaml.exists(): - return read_yaml(output_yaml) - else: - return {}
- -
[docs] def update_sim_input(self, new_params) -> None: - ''' Update simulation parameters ''' - self.sim_input.update(new_params)
- -
[docs] def update_calc_input(self, new_params) -> None: - ''' Update calculator parameters ''' - self.calc_input.update(new_params)
- -
[docs] def update_env_input(self, new_params) -> None: - ''' Update calculator parameters ''' - self.env_input.update(new_params) - self.env_id = self.sim_input.get('env_id', None) - if self.env_id is not None: - self.env = self.env_input[self.env_id]
- -
[docs] def set_workdir(self, workdir) -> None: - ''' Set working directory both in sim_input and instance ''' - workdir = Path(workdir) - self.sim_input['workdir'] = str(workdir.resolve()) - self.workdir = workdir
- -
[docs] def get_status(self, display=False) -> Tuple[bool,str]: - ''' Check job status ''' - output = self.get_output() - job_id = output.get('job_id', False) - running = False - if job_id: - running = check_if_slurm_job_is_running(job_id) - if running: - status = 'started' - self.update_status(status) - complete = False - else: - status = output.get('status', 'clean') - complete = status == 'complete' - if display: - print(f'Status: {status}') - return complete, status
- -
[docs] def update_output(self, output_update: Dict) -> None: - ''' Update output.yaml if it exists or write a new one ''' - output = self.get_output() - output.update(output_update) - write_yaml(self.get_output_yaml(), output)
- -
[docs] def get_logger(self, logfilename='job.log', level='info'): - ''' Get the logger ''' - assert self.workdir.exists(), 'Work directory does not exist yet' - logger = get_logger(logfile=self.workdir / logfilename, level=level) - return logger
- - def _gen_slurm_batch_preamble( - self, - slurm_params=None, - extra_flags=None - ) -> None: - ''' Generate the txt with job configuration but no run commands ''' - if slurm_params is None: - slurm_params = self.env.get('slurm', {}) - - txt = '#!/usr/bin/sh\n\n' - flags = slurm_params.get('flags', []) - if isinstance(flags, dict): - flag_list = [] - for k, v in flags.items(): - assert k.startswith('-'), \ - 'Slurm flags must start with "-" or "--"' - if k.startswith('--'): - delim = '=' - else: - delim = ' ' - - flag_list.append(delim.join([k, str(v)])) - - flags = flag_list - - jobname_flag = '-J ' + str(self.sim_input.get('asimmodule', 'job')) - for i, flag in enumerate(flags): - if flag.strip().startswith('-J') or flag.strip().startswith('--job-name'): - jobname_flag = flags.pop(i) - break - - # Allow naming jobs in sim_input files - job_name = self.sim_input.get('job_name', False) - if job_name: - jobname_flag = f'-J {job_name}' - - flags.append(jobname_flag) - if extra_flags is not None: - # Only supporting list for extraflags, it is an internal variable - flags.extend(extra_flags) - for flag in flags: - txt += f'#SBATCH {flag}\n' - - return txt
- -
[docs]class UnitJob(Job): - ''' - Unit job object with ability to submit a slurm/interactive job. - Unit jobs run in a specific environment and if required, run a - specific calculator. More complex workflows are built up of unit - jobs - ''' - def __init__( - self, - sim_input: Dict, - env_input: Union[Dict,None] = None, - calc_input: Union[Dict,None] = None, - ) -> None: - super().__init__(sim_input, env_input, calc_input) - - # Check if the asimmodule being called uses a calc_id to - # get precommands, postcommands, run_prefixes and run_suffixes - self.calc_id = self.sim_input.get('args', {}).get('calc_id', None) - if self.calc_id is not None: - self.calc_params = self.calc_input[self.calc_id] - else: - self.calc_params = {} - -
[docs] def gen_run_command(self) -> str: - ''' - Generates the command to run the job, independent of slurm - ''' - asimmodule = self.sim_input.get('asimmodule', False) - assert asimmodule, 'Specify a asimmodule in sim_input' - - mode_params = self.env.get('mode', { - 'use_slurm': False, 'interactive': True - }) - env_run_prefix = mode_params.get('run_prefix', '') - env_run_suffix = mode_params.get('run_suffix', '') - - calc_run_prefix = self.calc_params.get('run_prefix', '') - calc_run_suffix = self.calc_params.get('run_suffix', '') - - if self.sim_input.get('debug', False): - debug_flag = ' -d' - else: - debug_flag = '' - - # GPAW requires python asimmodule to be called with gpaw python - # For now this is a work around but perhaps there exists a cleaner way - if self.calc_params.get('name', '') == 'GPAW': - asloader = pkgutil.get_loader('asimtools.scripts.asim_run') - asfile = asloader.get_filename() - alias = f'gpaw python {asfile}' - else: - alias = 'asim-run' - - txt = f'{env_run_prefix} {calc_run_prefix} ' - txt += f'{alias} sim_input.yaml --calc=calc_input.yaml' + debug_flag - txt += f' {env_run_suffix} {calc_run_suffix} ' - return txt
- - def _gen_slurm_script(self, write: bool = True) -> None: - ''' - Generates a slurm job file and if necessary writes it in - the work directory for the job - ''' - slurm_params = self.env.get('slurm', {}) - calc_params = self.calc_params - - txt = self._gen_slurm_batch_preamble() - txt += '\n' - for command in slurm_params.get('precommands', []): - txt += command + '\n' - for command in calc_params.get('precommands', []): - txt += command + '\n' - txt += '\n' - txt += 'echo "Job started on `hostname` at `date`"\n' - txt += self.gen_run_command() + '\n' - for command in slurm_params.get('postcommands', []): - txt += command + '\n' - for command in calc_params.get('postcommands', []): - txt += command + '\n' - txt += 'echo "Job ended at `date`"' - - if write: - slurm_file = self.workdir / 'job.sh' - slurm_file.write_text(txt) - - def _gen_slurm_interactive_txt(self) -> str: - ''' - Generates an srun command to run the job - ''' - slurm_params = self.env.get('slurm', False) - - txt = 'srun --unbuffered ' # unbuffered to avoid IO lag - txt += ' '.join(slurm_params.get('flags')) - txt += self.gen_run_command() - - return txt - -
[docs] def gen_input_files( - self, - write_calc_input: bool = True, - write_env_input: bool = True, - # use_links: bool = True, - write_image: bool = True, - ) -> None: - ''' Write input files to working directory ''' - workdir = self.workdir - - # This is the sim_input that will be written to disk so it will have - # slightly different paths and the image(s) will be image_files - sim_input = deepcopy(self.sim_input) - # The sim_input file will already be in the work directory - sim_input['workdir'] = '.' - # Collect useful variables - mode_params = self.env.get('mode', {}) - use_slurm = mode_params.get('use_slurm', False) - interactive = mode_params.get('interactive', True) - overwrite = self.sim_input.get('overwrite', False) - output_file = workdir / 'output.yaml' - sim_input_file = workdir / 'sim_input.yaml' - - # Check if the job already exists or not and if to overwrite - if not workdir.exists(): - workdir.mkdir() - elif output_file.exists() and sim_input_file.exists(): - complete = read_yaml(output_file).get('end_time', False) - if complete and not overwrite: - txt = f'Skipped writing in {self.workdir}, files/directory ' - txt += 'already exist. Set overwrite=True to overwrite files ' - txt += 'or delete results directory first (recommended)' - self.get_logger().warning(txt) - print(Fore.RED + 'WARNING: ' + txt + Fore.WHITE) - return None - - # If the sim_input uses an image/images, we want to write it in - # the workdir and point to it using a filename. This is so that - # there is a record of the input image for debugging and the input - # method is consistent with complex workflows - image = self.sim_input.get('args', {}).get('image', False) - - # write_image is to account for chains where the image may not have - # been produced yet by a previous step, otherwise always read and write - if image and write_image: - atoms = get_atoms(**image) - input_image_file = 'image_input.xyz' # Relative to workdir - # input_image_file = self.workdir.resolve() / 'image_input.xyz' - atoms.write( - self.workdir / input_image_file, - format='extxyz' - ) - sim_input['args']['image'] = { - 'image_file': str(input_image_file), - # 'image_file': str((self.workdir / input_image_file).resolve()) - } - - images = self.sim_input.get('args', {}).get('images', False) - if images and write_image: - if images.get('images', False) or images.get('image_file', False): - images = get_images(**images) - input_images_file = 'images_input.xyz' # Relative to workdir - ase.io.write( - self.workdir / input_images_file, - images, - format='extxyz', - ) - sim_input['args']['images'] = { - 'image_file': str(input_images_file), - } - - write_yaml(workdir / 'sim_input.yaml', sim_input) - if write_calc_input: - write_yaml(workdir / 'calc_input.yaml', self.calc_input) - if write_env_input: - write_yaml(workdir / 'env_input.yaml', self.env_input) - write_yaml(self.get_output_yaml(), {'status': 'clean'}) - - if use_slurm and not interactive: - self._gen_slurm_script() - return None
- -
[docs] def submit( - self, - dependency: Union[List,None] = None, - write_image: bool = True, - ) -> Union[None,List[str]]: - ''' - Submit a job using slurm, interactively or in the terminal - ''' - - msg = START_MESSAGE - msg += f'asimmodule: {self.sim_input["asimmodule"]}\n' - msg += f'Work directory: {self.workdir}' - logmsg = f'Submitting "{self.sim_input["asimmodule"]}" in "{self.workdir}"' - logging.info(logmsg) - print(msg) # For printing to console - - self.gen_input_files(write_image=write_image) - - logger = self.get_logger() - - _, status = self.get_status(display=True) - if status in ('discard', 'complete'): - txt = f'Current job status in "{self.workdir}" is "{status}", ' - txt += 'skipping submission, set "overwrite=True" to ignore' - logger.warning(txt) - if status in ('complete'): - print('Job already completed, not submitting again') - print(STOP_MESSAGE) - return None - - if not self.sim_input.get('submit', True): - logger.warning('Keyword submit=False, skipping submission in \ - %s', self.workdir) - return None - - cur_dir = Path('.').resolve() - os.chdir(self.workdir) - mode_params = self.env.get('mode', {}) - sim_input = self.sim_input - use_slurm = mode_params.get('use_slurm', False) - interactive = mode_params.get('interactive', True) - - # Case when running batch jobs, handles job dependency - if use_slurm and not interactive: - if dependency is not None: - dependstr = None - for dep in dependency: - if dependstr is None: - dependstr = str(dep) if dep is not None else None - else: - dependstr += f':{dep}' if dep is not None else '' - - command = ['sbatch', '-d', f'afterok:{dependstr}'] - command += ['--kill-on-invalid-dep=yes', 'job.sh'] - else: - command = ['sbatch', 'job.sh'] - - # Interactive jobs launched with srun - elif use_slurm and interactive: - command = self._gen_slurm_interactive_txt().split() - - # Launching the job inline - else: - command = self.gen_run_command().split() - - run_job = False - overwrite = sim_input.get('overwrite', False) - _, status = self.get_status() - if overwrite or status == 'clean': - run_job = True - - if run_job: - completed_process = subprocess.run( - command, check=False, capture_output=True, text=True, - ) - - with paropen('stdout.txt', 'w', encoding='utf-8') as output_file: - output_file.write(completed_process.stdout) - - if completed_process.stderr is not None: - with paropen('stderr.txt', 'w', encoding='utf-8') as err_file: - err_file.write(completed_process.stderr) - - if completed_process.returncode != 0: - err_msg = f'See {self.workdir / "stderr.txt"} for traceback.' - logger.error(err_msg) - completed_process.check_returncode() - - os.chdir(cur_dir) - - # Return job ids for chaining dependencies in batch mode - if use_slurm and not interactive and run_job: - job_ids = [int(completed_process.stdout.split(' ')[-1])] - self.update_output({'job_ids': job_ids}) - return job_ids - - logmsg = f'Submitted "{self.sim_input["asimmodule"]}" in "{self.workdir}"' - msg = 'Successfully submitted\n' - msg += STOP_MESSAGE - logger.info(logmsg) - print(msg) - - return None
- -
[docs]class DistributedJob(Job): - ''' Array job object with ability to submit simultaneous jobs ''' - def __init__( - self, - sim_input: Dict, - env_input: Union[None,Dict] = None, - calc_input: Union[None,Dict] = None, - ) -> None: - super().__init__(sim_input, env_input, calc_input) - # Set a standard for all subdirectories to start - # with "id-{sim_id}" followed by user labels - new_sim_input = {} - njobs = len(sim_input) - num_digits = 4 - assert njobs < 1000, \ - f'ASIMTools id_nums are limited to {num_digits} digits, found \ - {njobs} jobs! Having that many jobs is not very storage efficient.' - - sim_id_changed = False - for i, (sim_id, subsim_input) in enumerate(sim_input.items()): - assert 'asimmodule' in subsim_input, 'Check sim_input format,\ - must have asimmodule and each job with a unique key' - - # We set a fixed number of digits so that the slurm array ID - # matches the directory name for easy resubmission of arrays - prefix = 'id-'+f'{i}'.rjust(num_digits, '0') - if not sim_id.startswith(prefix): - sim_id_changed = True - - if sim_id_changed: - for i, (sim_id, subsim_input) in enumerate(sim_input.items()): - prefix = 'id-'+f'{i}'.rjust(num_digits, '0') - new_sim_id = join_names([prefix,sim_id]) - new_subsim_input = deepcopy(sim_input[sim_id]) - new_subsim_input['distributed_id'] = i - new_sim_input[new_sim_id] = new_subsim_input - sim_input = new_sim_input - unitjobs = [] - for sim_id, subsim_input in sim_input.items(): - assert 'asimmodule' in subsim_input, 'Check sim_input format,\ - must have asimmodule and each job with a unique key' - - subsim_input['workdir'] = sim_id - unitjob = UnitJob(subsim_input, env_input, calc_input) - unitjobs.append(unitjob) - - # If all the jobs have the same config and use slurm, use a job array - env_id = unitjobs[0].env_id - same_env = np.all( - [(uj.env_id == env_id) for uj in unitjobs] - ) - - all_slurm = np.all( - [uj.env['mode'].get('use_slurm', False) for uj in unitjobs] - ) - - if same_env and all_slurm: - self.use_array = True - else: - self.use_array = False - - self.unitjobs = unitjobs - -
[docs] def submit_jobs( - self, - **kwargs, # Necessary for compatibility with job.submit - ) -> Union[None,List[str]]: - ''' - Submits the jobs. If submitting lots of batch jobs, we - recommend using DistributedJob.submit_array - ''' - # It is possible to do an implementation where we limit - # the number of simultaneous jobs like an array using job - # dependencies but that can be implemented later - job_ids = [] - for unitjob in self.unitjobs: - job_id = unitjob.submit() - job_ids.append(job_id) - return job_ids
- -
[docs] def submit_array( - self, - array_max=None, - dependency: Union[List[str],None] = None, - **kwargs, # Necessary for compatibility with job.submit - ) -> Union[None,List[str]]: - ''' - Submits a job array if all the jobs have the same env and use slurm - ''' - self.gen_input_files() - logger = self.get_logger() - - unitjobs = [] # Track jobs that are supposed to be submitted - for unitjob in self.unitjobs: - if unitjob.sim_input.get('submit', True): - unitjobs.append(unitjob) - - njobs = len(unitjobs) - if njobs == 0: - return None - - # For limiting number of jobs launched in array - if array_max is not None: - arr_max_str = f'%{array_max}' - else: - arr_max = unitjobs[0].env['mode'].get('array_max', False) - if arr_max: - arr_max_str = f'%{arr_max}' - else: - arr_max_str = '' - - if dependency is not None: - dependstr = None - for dep in dependency: - if dependstr is None: - dependstr = str(dep) if dep is not None else None - else: - dependstr += f':{dep}' if dep is not None else '' - - command = [ - 'sbatch', - f'--array=[0-{njobs-1}]{arr_max_str}', - '-d', f'afterok:{dependstr}', - 'job_array.sh' - ] - else: - command = [ - 'sbatch', - f'--array=[0-{njobs-1}]{arr_max_str}', - 'job_array.sh' - ] - - completed_process = subprocess.run( - command, check=False, capture_output=True, text=True, - ) - - with paropen('stdout.txt', 'w', encoding='utf-8') as output_file: - output_file.write(completed_process.stdout) - - if completed_process.stderr is not None: - with paropen('stderr.txt', 'w', encoding='utf-8') as err_file: - err_file.write(completed_process.stderr) - - if completed_process.returncode != 0: - err_msg = f'See {self.workdir / "stderr.txt"} for traceback.' - logger.error(err_msg) - completed_process.check_returncode() - - job_ids = [int(completed_process.stdout.split(' ')[-1])] - return job_ids
- - def _gen_array_script(self, write: bool = True) -> None: - ''' - Generates a slurm job array file and if necessary - writes it in the work directory for the job. Only works - if there is one config_id for all jobs - ''' - env_id = self.unitjobs[0].env_id - env = self.env_input[env_id] - - slurm_params = env.get('slurm', {}) - - txt = self._gen_slurm_batch_preamble( - slurm_params=slurm_params, - extra_flags=[ - '-o slurm_stdout.id-%a_j%A', - '-e slurm_stderr.id-%a_j%A', - ] - ) - - txt += '\nif [[ ! -z ${SLURM_ARRAY_TASK_ID} ]]; then\n' - txt += ' fls=( id-* )\n' - txt += ' WORKDIR=${fls[${SLURM_ARRAY_TASK_ID}]}\n' - txt += 'fi\n\n' - txt += 'CUR_DIR=`pwd`\n' - txt += 'cd ${WORKDIR}\n' - txt += '\n' - txt += '\n'.join(slurm_params.get('precommands', [])) - txt += '\n' - txt += '\n'.join(self.unitjobs[0].calc_params.get('precommands', [])) - txt += '\n' - txt += 'echo "LAUNCHDIR: ${CUR_DIR}"\n' - txt += 'echo "WORKDIR: ${WORKDIR}"\n' - txt += 'echo "Job started on `hostname` at `date`"\n' - txt += self.unitjobs[0].gen_run_command() + '\n' - txt += '\n'.join(slurm_params.get('postcommands', [])) - txt += '\n' - txt += 'cd ${CUR_DIR}\n' - txt += 'echo "Job ended at `date`"' - - if write: - slurm_file = self.workdir / 'job_array.sh' - slurm_file.write_text(txt) - -
[docs] def gen_input_files(self) -> None: - ''' Write input files to working directory ''' - - if self.use_array: - self._gen_array_script() - for unitjob in self.unitjobs: - unitjob.gen_input_files()
- -
[docs] def submit(self, **kwargs) -> None: - ''' - Submit a job using slurm, interactively or in the terminal - ''' - - cur_dir = Path('.').resolve() - os.chdir(self.workdir) - job_ids = None - if self.use_array: - job_ids = self.submit_array(**kwargs) - else: - job_ids = self.submit_jobs(**kwargs) - self.update_output({'job_ids': job_ids}) # For chained job - os.chdir(cur_dir) - return job_ids
- -
[docs]class ChainedJob(Job): - ''' - Jobs made of smaller sequential unitjobs. Note that this only works - well with unit jobs. If one of the UnitJobs calls asimmodules, internally, - slurm will fail to build the correct dependencies but the files will be - generated appropriately, you can submit them manually - ''' - def __init__( - self, - sim_input: Dict, - env_input: Union[None,Dict] = None, - calc_input: Union[None,Dict] = None, - ) -> None: - super().__init__(sim_input, env_input, calc_input) - - for key in sim_input: - assert key.startswith('step-'), \ - f'Keys take the form "step-[step_id]" from id=0 not "{key}"' - - # Each key in sim_input should be in the form "step-id" where id - # is replaced by the order in which the commands are run - unitjobs = [] - for i in range(len(sim_input)): - step_id = f'step-{i}' - subsim_input = deepcopy(sim_input[step_id]) - unitjob = UnitJob(subsim_input, env_input, calc_input) - unitjob.set_workdir(step_id) - unitjobs.append(unitjob) - - self.unitjobs = unitjobs - -
[docs] def get_last_output(self) -> Dict: - ''' Returns the output of the last job in the chain ''' - return self.unitjobs[-1].get_output()
- -
[docs] def submit(self, dependency: Union[List,None] = None) -> List: - ''' - Submit a job using slurm, interactively or in the terminal - ''' - cur_dir = Path('.').resolve() - os.chdir(self.workdir) - logger = self.get_logger() - step = 0 #self.get_current_step() TODO: This feature is not used yet - are_interactive_jobs = [ - uj.env['mode'].get('interactive', False) \ - for uj in self.unitjobs - ] - all_interactive = np.all(are_interactive_jobs) - all_not_interactive = np.sum(are_interactive_jobs) == 0 - assert all_interactive or all_not_interactive, \ - 'Jobs in chain must all be interactive=True or interactive=False' - - are_using_slurm = [ - uj.env['mode'].get('use_slurm', False) \ - for uj in self.unitjobs - ] - all_slurm = np.all(are_using_slurm) - all_not_slurm = np.sum(are_using_slurm) == 0 - - assert all_slurm or all_not_slurm, \ - 'Jobs in chain must all have use_slurm=True or use_slurm=False' - - # Only use slurm dependencies if all the jobs are batch jobs - if all_slurm and all_not_interactive: - if step != len(self.unitjobs): - dependency = None - for i, unitjob in enumerate(self.unitjobs[step:]): - cur_step_complete, status = unitjob.get_status() - if not cur_step_complete: - slurm_flags = unitjob.env['slurm']['flags'] - if isinstance(slurm_flags, list): - job_name = unitjob.sim_input.get('job_name',False) - if not job_name: - job_name = f'-J step-{step+i}' - else: - job_name = f'-J step-{step+i}-{job_name}' - unitjob.env['slurm']['flags'].append( - job_name - ) - elif isinstance(slurm_flags, dict): - unitjob.env['slurm']['flags']['-J'] = \ - f'step-{step+i}' - - write_image = False - # Write image first step in chain being run/continued - if i == 0: - write_image = True - dependency = unitjob.submit( - dependency=dependency, - write_image=write_image, - ) - else: - txt = f'Skipping step-{step+i} since ' - txt += f'status is {status}' - logger.warning(txt) - - job_ids = dependency - - # Otherwise just submit them one after the other - # We only write the image if it's the first job, otherwise we refer to - # wherever the image comes from in case it has to come from a previous - # step - else: - for i, unitjob in enumerate(self.unitjobs[step:]): - if i == 0: - write_image = True - else: - write_image = False - - job_ids = unitjob.submit(write_image=write_image) - - os.chdir(cur_dir) - - return job_ids
- - -
[docs]def load_job_from_directory(workdir: str): - ''' Loads a job from a given directory ''' - workdir = Path(workdir) - assert workdir.exists(), f'Work director {workdir} does not exist' - logger = get_logger() - sim_inputs = glob(str(workdir / 'sim_input.yaml')) - if len(sim_inputs) != 1: - logger.error('Multiple or no sim_input.yaml files in %s', {workdir}) - try: - sim_input = read_yaml(glob(str(workdir / 'sim_input.yaml'))[0]) - except IndexError as exc: - logger.error('sim_input.yaml not found in %s', {str(workdir)}) - raise exc - - env_inputs = glob(str(workdir / 'env_input.yaml')) - if len(env_inputs) == 1: - env_input = read_yaml(env_inputs[0]) - else: - env_input = None - - calc_inputs = glob(str(workdir / 'calc_input.yaml')) - if len(calc_inputs) == 1: - calc_input = read_yaml(calc_inputs[0]) - else: - calc_input = None - - job = Job(sim_input, env_input, calc_input) - - # This makes sure that wherever we may be loading the job from, we refer - # to the correct input/output files. As of now, it does not seem necessary - # to also change the workdir in job.sim_input for consistency - job.workdir = Path(workdir) - return job
- -
[docs]def create_unitjob(sim_input, env_input, workdir, calc_input=None): - """Helper for making a generic UnitJob object, mostly for testing""" - env_id = list(env_input.keys())[0] - sim_input['env_id'] = env_id - if calc_input is not None: - calc_id = list(calc_input.keys())[0] - sim_input['calc_id'] = calc_id - sim_input['workdir'] = workdir - unitjob = UnitJob( - sim_input, - env_input, - calc_input - ) - return unitjob
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/asimtools/utils.html b/_build/_modules/asimtools/utils.html deleted file mode 100644 index 02c97a4..0000000 --- a/_build/_modules/asimtools/utils.html +++ /dev/null @@ -1,834 +0,0 @@ - - - - - - asimtools.utils — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -

Source code for asimtools.utils

-'''
-Utilities and helper functions for reading and writing data using set
-standards
-'''
-from typing import (
-    TypeVar, Iterable, Tuple, Union, List, Dict, Sequence, Optional
-)
-from copy import deepcopy
-from glob import glob
-import os
-import logging
-import subprocess
-from pathlib import Path
-import yaml
-import numpy as np
-import pandas as pd
-from ase.io import read
-from ase.parallel import paropen
-import ase.db
-import ase.build
-from pymatgen.core import Structure
-from pymatgen.io.ase import AseAtomsAdaptor
-
-Atoms = TypeVar('Atoms')
-
-
[docs]def read_yaml(yaml_path: str) -> Dict: - """Read a yaml file - - :param yaml_path: Path to yaml file - :type yaml_path: str - :return: Dictionary - :rtype: Dict - """ - with open(yaml_path, 'r', encoding='utf-8') as f: - output = yaml.safe_load(f) - - if output is None: - return {} - return output
- -
[docs]def write_yaml(yaml_path: str, yaml_Dict: Dict) -> None: - """Write a dictionary to a yaml file - - :param yaml_path: Path to write yaml to - :type yaml_path: str - :param yaml_Dict: Dictionary to write - :type yaml_Dict: Dict - """ - # Use paropen so that only the master process is updating outputs - with paropen(yaml_path, 'w', encoding='utf-8') as f: - yaml.dump(yaml_Dict, f)
- -
[docs]def get_axis_lims(x: Sequence, y: Sequence, padding: float=0.1): - """Get an estimate of good limits for a plot axis""" - data_min = np.min([x, y]) - data_max = np.max([x, y]) - diff = data_max - data_min - lims = [data_min - padding * diff, data_max + padding * diff] - return lims
- -
[docs]def write_csv_from_dict( - fname: str, - data: Dict, - columns: Optional[Sequence] = None, - header: str = '', - **kwargs -) -> pd.DataFrame: - """Write a tabulated csv to a file from a dictionary. The keys will - become the columns and the values will be the columns, All columns used - must have the same length. kwargs are passed to - :func:`pandas.Dataframe.to_csv()` - - :param fname: File name to be return to - :type fname: str - :param data: Dictionary to write - :type data: Dict - :param columns: Keys to use as columns of csv, defaults to None - :type columns: Iterable, optional - :return: Pandas dataframe of results - :rtype: pd.DataFrame - """ - if columns is None: - columns = list(data.keys()) - - csv_data = pd.DataFrame(data, columns=columns, **kwargs) - with open(fname, 'w', encoding='utf-8') as f: - f.write('#' + header + '\n') - - csv_data.to_csv(fname, index=False, header=True, mode='a') - return csv_data
- -
[docs]def strip_symbols(substr: str) -> str: - """Helper function to format filenames using standard - - :param substr: substring - :type substr: str - :return: stripped string - :rtype: str - """ - bad_symbols = ['_', '-', '.', ' '] - if len(substr) == 0: - return '' - if substr[0] in bad_symbols or substr[-1] in bad_symbols: - for bad_symbol in bad_symbols: - substr = substr.strip(bad_symbol) - return strip_symbols(substr) - return substr
- -
[docs]def join_names(substrs: Sequence[str]) -> str: - """Join multiple strings using a hyphen neatly - - :param substrs: Sequence of strings to merge - :type substrs: Sequence[str] - :return: Joined strings - :rtype: str - """ - name = '' - new_substrs = [] - for substr in substrs: - new_substrs.append(strip_symbols(substr)) - - final_substrs = [] - for substr in new_substrs: - if len(substr) > 0: - final_substrs.append(substr) - name = '__'.join(final_substrs) + '__' - return name
- -
[docs]def get_atoms( - image_file: Optional[str] = None, - interface: str = 'ase', - builder: Optional[str] = 'bulk', - atoms: Optional[Atoms] = None, - repeat: Optional[Tuple[int, int, int]] = None, - rattle_stdev: Optional[float] = None, - mp_id: Optional[str] = None, - user_api_key: Optional[str] = None, - return_type: str = 'ase', - **kwargs -) -> Union[Atoms, Structure]: - """Return an ASE Atoms or pymatgen Structure object based on specified - config. This is the recommended way to load atoms objects for asimmodules. - - :param image_file: Path to an ASE-readable image file, defaults to None - :type image_file: str, optional - :param interface: Whether to use "ase" or "pymatgen" to create the atoms - object - :type interface: str, optional - :param builder: Builder to use from :mod:`ase.build`, defaults to 'bulk'. \ - Any extra keyword arguments specified are passed to the build - :type builder: str, optional - :param atoms: :class:`ase.Atoms` object, defaults to None - :type atoms: Atoms, optional - :param repeat: Number of times to repeat input to create supercell, \ - defaults to None - :type repeat: Tuple[int, int, int], optional - :param rattle_stdev: `stdev` to be provided to :meth:`ase.Atoms.rattle`, \ - or as `distance` to :meth:`pymatgen.core.structure.Structure.perturb` - defaults to None - :type rattle_stdev: float, optional - :param mp_id: Material Project ID to fetch structure from, defaults to None - :type mp_id: str, optional - :param user_api_key: Material Project API key, must be provided to get - structures from Materials Project, defaults to None - :type user_api_key: str, optional - :param return_type: When set to `ase` returns a :class:`ase.Atoms` object, - when set to `pymatgen` returns a - :class:`pymatgen.core.structure.Structure` object, defaults to 'ase' - :return: One :class:`ase.Atoms` or - :class:`pymatgen.core.structure.Structure` instance - :rtype: Union[Atoms, Structure] - - There are three options one could use to specify and image or an atoms - objects: - - #. image_file + \*\*kwargs - #. builder + \*\*kwargs. - #. atoms - - Examples - -------- - - Some examples using builders from ASE. All ``**kwargs`` are passed to - :func:`ase.build`: - - >>> get_atoms(builder='molecule', name='H2O') - Atoms(symbols='OH2', pbc=False) - >>> get_atoms(builder='bulk', name='Cu') - Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]]) - >>> get_atoms(builder='bulk', name='Ar', crystalstructure='fcc', a=3.4, cubic=True) - Atoms(symbols='Ar4', pbc=True, cell=[3.4, 3.4, 3.4]) - >>> get_atoms(builder='fcc100', symbol='Fe', vacuum=8, size=[4,4, 5]) - Atoms(symbols='Cu80', pbc=[True, True, False], cell=[10.210621920333747, 10.210621920333747, 23.22], tags=...) - - Some examples for reading an image from a file using :func:`ase.io.read` - are given below. All ``**kwargs`` are passed to :func:`ase.io.read` - - >>> h2o = get_atoms(builder='molecule', name='H2O') - >>> h2o.write('h2o.cif') - >>> get_atoms(image_file='h2o.cif') - Atoms(symbols='OH2', pbc=False) - >>> get_atoms(image_file='h2o.cif', format='cif') - Atoms(symbols='OH2', pbc=False) - >>> from ase.io import write - >>> molecules = [get_atoms(builder='molecule', name='H2O'), get_atoms(builder='molecule', name='H2')] - >>> write('molecules.xyz', molecules, format='extxyz') - >>> get_atoms(image_file='molecules.xyz', index=0) # Pick out one structure using indexing - Atoms(symbols='OH2', pbc=False) - - You can also make supercells and rattle the atoms - - >>> li_bulk = get_atoms(name='Li') - >>> li_bulk.write('POSCAR', format='vasp') - >>> get_atoms(image_file='POSCAR', repeat=[3,3,3]) - Atoms(symbols='Li27', pbc=True, cell=[[-5.235, 5.235, 5.235], [5.235, -5.235, 5.235], [5.235, 5.235, -5.235]]) - >>> get_atoms(builder='bulk', name='Li', repeat=[2,2,2], rattle_stdev=0.01) - Atoms(symbols='Li8', pbc=True, cell=[[-3.49, 3.49, 3.49], [3.49, -3.49, 3.49], [3.49, 3.49, -3.49]]) - - Mostly for internal use and use in asimmodules, one can specify atoms - directly - - >>> li_bulk = get_atoms(name='Li') - >>> get_atoms(atoms=li_bulk) - Atoms(symbols='Li', pbc=True, cell=[[-1.745, 1.745, 1.745], [1.745, -1.745, 1.745], [1.745, 1.745, -1.745]]) - - In an asimmodule, the ``image`` argument is always given as a dictionary, - you therefore have to expand it before passing it to ``get_atoms`` - - >>> image = {'name': 'Pt'} - >>> get_atoms(**image) - Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]]) - - To get a pymatgen structure object, set the `return_type` to "pymatgen" - - >>> image = {'name': 'Pt', 'return_type': 'pymatgen'} - >>> get_atoms(**image) - Structure Summary - Lattice - ... - - To download a structure from the Materials Project, you need to provide - an API key, the MP ID of the structure and set the interface to 'pymatgen' - You can also specify whether you want the primitive(default) or - conventional unit cell as a keyword argument - - >>> {'mp_id': 'mp-14', 'interface': 'pymatgen', 'user_api_key': "USER_API_KEY", 'conventional_unit_cell': True}, - >>> get_atoms(**image) - Structure Summary - Lattice - abc : 2.7718585822512662 2.7718585822512662 2.7718585822512662 - ... - """ - if interface == 'ase': - assert image_file is not None or \ - len(kwargs) > 0 or \ - atoms is not None, \ - "Specify atoms, image_file or use ase.build tools if using \ - ASE interface" - if image_file is not None: - assert Path(image_file).exists(), \ - f'The image_file {image_file} does not exist from {os.getcwd()}' - atoms = read(image_file, **kwargs) - elif atoms is None: - builder_func = getattr(ase.build, builder) - try: - atoms = builder_func(**kwargs) - except ValueError: - print('Make sure you choose a valid builder and appropriate\ - arguments matching the functions in ase.build. \n\ - See https://wiki.fysik.dtu.dk/ase/ase/build/build.html') - raise - else: - assert atoms is not None, 'Specify an input structure' - - if interface == 'pymatgen': - if mp_id is not None: - from pymatgen.ext.matproj import MPRester - with MPRester(user_api_key) as mpr: - struct = mpr.get_structure_by_material_id(mp_id, **kwargs) - elif builder is not None: - builder_func = getattr(Structure, builder) - try: - struct = builder_func(**kwargs) - except ValueError: - err_txt = 'Make sure you choose a valid builder and ' - err_txt += 'appropriate arguments matching the functions ' - err_txt += 'from pymatgen.core.structure \n' - err_txt += 'See https://pymatgen.org/pymatgen.core.html' - err_txt += '#module-pymatgen.core.structure' - print(err_txt) - raise - - if repeat is not None: - if interface == 'ase': - atoms = atoms.repeat(repeat) - elif interface == 'pymatgen': - struct = struct.make_supercell(repeat) - - if rattle_stdev is not None and interface == 'ase': - atoms.rattle(stdev=rattle_stdev) - elif rattle_stdev is not None and interface == 'pymatgen': - struct.perturb(distance=rattle_stdev, min_distance=0) - - if return_type == 'ase' and interface == 'ase': - return atoms - elif return_type == 'pymatgen' and interface == 'ase': - return AseAtomsAdaptor.get_structure(atoms) - elif return_type == 'pymatgen' and interface == 'pymatgen': - return struct - elif return_type == 'ase' and interface == 'pymatgen': - return AseAtomsAdaptor.get_atoms(struct, msonable=False)
- -
[docs]def parse_slice(value: str) -> slice: - """Parses a :func:`slice` from string, like `start:stop:step`. - - :param value: Slice string - :type value: str - :return: slice object - :rtype: slice - """ - indices = str(value).split(':') - parts = [] - for index in indices: - if index == '': - parts.append(False) - else: - parts.append(index) - return slice(*[int(p) if p else None for p in parts])
- -
[docs]def get_images( - image_file: str = None, - pattern: str = None, - patterns: List[str] = None, - images: Iterable[Atoms] = None, - index: Union[str, int] = ':', - skip_failed: bool = False, - **kwargs -) -> List[Atoms]: - """Return a list of atoms objects based on the input arguments. Options \ - to specify are: - #. image_file - #. pattern - #. patterns - #. images - - :param image_file: Path to ASE-readable file with one or more images, \ - defaults to None - :type image_file: str, optional - :param pattern: String pattern of paths from which to search for images, \ - defaults to None. This only gets the last image from each file as in \ - :func:`ase.io.read` if an index is not specified. - :type pattern: str, optional - :param patterns: Sequence of string patterns/paths from which to search \ - for images, defaults to None. This only gets one image from each file \ - as in :func:`ase.io.read` without specifying an index - :type pattern: str, optional - :param images: A list of atoms objects, defaults to None - :type images: Iterable[Atoms], optional - :param index: Index to specify when using :func:`ase.io.read`, \ defaults - to ':' - :type index: Union[str, int], optional - :param skip_failed: Whether to raise an IO error if it fails to read any of - the specified images or ignore errors, defaults to False - :type skip_failed: bool, optional - :raises IOError: Failed to read one of the specified images - :return: List of :class:`ase.Atoms` for all images found - :rtype: List[Atoms] - - There are three options one could use to specify and image or an atoms - objects: - - #. image_file + \*\*kwargs for specifying one image file - #. pattern + \*\*kwargs for specifying multiple image files with a wildcard - character - #. patterns + \*\*kwargs for specifying a list of patterns to match, - captures the above two cases - #. images - - Examples - -------- - - Some examples for reading images selectively from an image_file. All - ``**kwargs`` are passed to :func:`ase.io.read`: - - >>> from asimtools.utils import get_atoms - >>> molecules = [] - >>> molecules.append(get_atoms(builder='molecule', name='H2O')) - >>> molecules.append(get_atoms(builder='molecule', name='H2')) - >>> molecules.append(get_atoms(builder='molecule', name='N2')) - >>> write('molecules.xyz', molecules, format='extxyz') - >>> get_images(image_file='molecules.xyz') - [Atoms(symbols='OH2', pbc=False), Atoms(symbols='H2', pbc=False), Atoms(symbols='N2', pbc=False)] - >>> get_images(image_file='molecules.xyz', index=':2') - [Atoms(symbols='OH2', pbc=False), Atoms(symbols='H2', pbc=False)] - - You can also use a wildcard (\*) by specifying the pattern argument. Notice - that the files don't have to be the same format if ASE can guess all the - file formats, otherwise you can specify the format argument which should - apply to all the images. - - >>> cu = get_atoms(name='Cu') - >>> cu.write('bulk_cu.cfg') - >>> fe = get_atoms(name='Fe') - >>> fe.write('bulk_fe.cif') - >>> pt = get_atoms(name='Pt') - >>> pt.write('bulk_pt.cfg') - >>> get_images(pattern='bulk*') - [Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], masses=..., momenta=...), Atoms(symbols='Fe', pbc=True, cell=[[2.48549, 0.0, 0.0], [-0.8284876429214074, 2.3433456351179887, 0.0], [-0.8284876429214074, -1.171653675382785, 2.0294079014797743]], spacegroup_kinds=...), Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]], masses=..., momenta=...)] - Atoms(symbols='OH2', pbc=False) - >>> get_images(pattern='bulk*.cfg', format='cfg') - [Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], masses=..., momenta=...), Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]], masses=..., momenta=...)] - - You can also specify multiple patterns - - >>> get_images(patterns=['bulk*.cfg', 'bulk\*.cif']) - [Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], masses=..., momenta=...), Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]], masses=..., momenta=...), Atoms(symbols='Fe', pbc=True, cell=[[2.48549, 0.0, 0.0], [-0.8284876429214074, 2.3433456351179887, 0.0], [-0.8284876429214074, -1.171653675382785, 2.0294079014797743]], spacegroup_kinds=...)] - - Or you can directly pass a list of Atoms, mostly for internal use - - >>> get_images(images=molecules) - [Atoms(symbols='OH2', pbc=False), Atoms(symbols='H2', pbc=False), Atoms(symbols='N2', pbc=False)] - - In an asimmodule, the ``images`` argument is always given as a dictionary, - you therefore have to expand it before passing it to ``get_images`` - - >>> images = {'pattern': 'bulk*'} - >>> get_images(**images) - [Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], masses=..., momenta=...), Atoms(symbols='Fe', pbc=True, cell=[[2.48549, 0.0, 0.0], [-0.8284876429214074, 2.3433456351179887, 0.0], [-0.8284876429214074, -1.171653675382785, 2.0294079014797743]], spacegroup_kinds=...), Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]], masses=..., momenta=...)] - """ - assert (image_file is not None) or \ - (pattern is not None) or \ - (patterns is not None) or \ - (images is not None), \ - "Please specify file, pattern or iterable" - - if image_file is not None: - image_file = Path(image_file).resolve() - images = read(image_file, index=index, **kwargs) - if not isinstance(images, list): - images = [images] - elif pattern is not None: - image_files = sorted(glob(pattern)) - assert len(image_files) > 0, \ - f'No images matching pattern "{pattern}" from "{os.getcwd()}"' - - images = [] - for image_file in image_files: - image_file = Path(image_file).resolve() - try: - new_images = read( - image_file, - index=index, - **kwargs - ) - except Exception as exc: - if not skip_failed: - raise IOError( - f"Failed to read {image_file} from {os.getcwd()}" - ) from exc - else: - new_images = [] - - # Output of read can either be list of atoms or Atoms, depending on index - if not isinstance(new_images, list): - new_images = [new_images] - images += new_images - - elif patterns is not None: - images = [] - for pattern in patterns: - image_files = sorted(glob(pattern)) - assert len(image_files) > 0, \ - f'Don\'t include pattern "{pattern}" if no files match' - images += get_images( - pattern=pattern, - index=index, - skip_failed=skip_failed, - **kwargs - ) - elif images is not None: - images = images[parse_slice(str(index))] - else: - images = [] - - if not skip_failed: - assert len(images) > 0, 'No images found' - - return images
- -
[docs]def new_db(dbname: str): - """Creates a new ASE database overwriting an old one - - :param dbname: Name for the new database - :type dbname: str - :return: Connection to database - :rtype: :mod:`ase.db` connection - """ - with open(dbname, 'w', encoding='utf-8') as f: - f.write("") - return ase.db.connect(dbname)
- -
[docs]def get_env_input() -> Dict: - """Gets the global env_input from the environment variable, then tries - then ``.asimtools`` dotfile. If an env_input.yaml is present in the - work direcory, it takes precedence. - - :return: env_input dictionary or empty dictionary if not found - :rtype: Dict - """ - if Path('env_input.yaml').exists(): - env_input_file = Path('env_input.yaml').resolve() - else: - env_input_file = os.getenv('ASIMTOOLS_ENV_INPUT', None) - - if env_input_file is None: - dotfile = Path('~/.asimtools') - if dotfile.exists(): - with open(dotfile, 'r', encoding='utf-8') as f: - lines = f.readlines() - for line in lines: - if line.startswith('ENV_INPUT_FILE'): - env_input_file = Path(line.split('=')) - break - if env_input_file.exists(): - try: - env_input = read_yaml(env_input_file) - return env_input - except FileNotFoundError: - print('WARNING: No env_input yaml found') - else: - env_input = read_yaml(env_input_file) - return env_input - return {}
- -
[docs]def get_calc_input(): - """Gets the global calc_input from the environment variable, then tries - then ``.asimtools`` dotfile - - :return: calc_input dictionary or empty dictionary if not found - :rtype: Dict - """ - calc_input_file = os.getenv('ASIMTOOLS_CALC_INPUT') - if calc_input_file is None: - dotfile = Path('~/.asimtools') - if dotfile.exists(): - with open(dotfile, 'r', encoding='utf-8') as f: - lines = f.readlines() - for line in lines: - if line.startswith('CALC_INPUT_FILE'): - calc_input_file = Path(line.split('=')) - break - if calc_input_file.exists(): - try: - calc_input = read_yaml(calc_input_file) - return calc_input - except FileNotFoundError: - print('WARNING: No calc_input yaml found') - else: - calc_input = read_yaml(calc_input_file) - return calc_input - return {}
- -
[docs]def check_if_slurm_job_is_running(slurm_job_id: Union[str,int]): - """Checks if the slurm job with specifying job_id is running - - :param slurm_job_id: Job ID as str or int - :type slurm_job_id: Union[str,int] - :return: Whether job is running or not - :rtype: bool - """ - slurm_job_id = str(slurm_job_id) - completed_process = subprocess.run( - ['squeue', '--job', slurm_job_id], - check=False, - capture_output=True, - text=True, - ) - stdout = completed_process.stdout - if str(' '+slurm_job_id) in stdout: - return True - else: - return False
- -
[docs]def change_dict_value( - d: Dict, - new_value, - key_sequence: Sequence, - return_copy: bool = True -) -> Dict: - """Changes a value in the specified dictionary given by following the - key sequence - - :param d: dictionary to be changed - :type d: Dict - :param new_value: The new value that will replace the old one - :type new_value: _type_ - :param key_sequence: List of keys in the order in which they access the dictionary key - :type key_sequence: Sequence - :param return_copy: Whether to return a copy only or to modify the dictionary in-place as well, defaults to True - :type return_copy: bool, optional - :return: The changed dictionary - :rtype: Dict - """ - if return_copy: - d = deepcopy(d) - if len(key_sequence) == 1: - d[key_sequence[0]] = new_value - return d - else: - new_d = change_dict_value( - d[key_sequence[0]], - new_value, - key_sequence[1:], - return_copy=return_copy - ) - d[key_sequence[0]] = new_d - return d
- -
[docs]def change_dict_values( - d: Dict, - new_values: Sequence, - key_sequences: Sequence, - return_copy: bool = True -) -> Dict: - """Changes values in the specified dictionary given by following the - key sequences. Key-value pairs are set in the given order - - :param d: dictionary to be changed - :type d: Dict - :param new_values: The new values that will replace the old one - :type new_values: Sequence - :param key_sequence: List of list of keys in the order in which they access the dictionary key - :type key_sequence: Sequence - :param return_copy: Whether to return a copy only or to modify the dictionary in-place as well, defaults to True - :type return_copy: bool, optional - :return: The changed dictionary - :rtype: Dict - """ - for key_sequence, new_value in zip(key_sequences, new_values): - d = change_dict_value(d, new_value, key_sequence, return_copy) - - return d
- -
[docs]def get_logger( - logfile='job.log', - fstr='%(asctime)s |%(module)s|%(funcName)s| %(levelname)s: %(message)s', - level='debug', -): - ''' Get the logger ''' - - level_dict = { - 'debug': logging.DEBUG, - 'info': logging.INFO, - 'warning': logging.WARNING, - } - assert level in level_dict, f'level must be one of {level_dict.keys()}' - - logging.basicConfig( - filename=logfile, - level=level_dict[level], - format=fstr, - ) - return logging.getLogger(__name__)
- - -
[docs]def get_str_btn( - s: Union[str,os.PathLike], - s1: str, - s2: str, - occurence: Optional[int] = 0, - start_index: Optional[int] = 0, -): - """Returns the substring between strings s1 and s2 from s - - :param s: string/path from which to extract substring - :type s: str - :param s1: substring before the desired substring, None starts from - the beginning of s - :type s1: str - :param s2: substring after the desired substring, None ends at the - end of the string - :type s2: str - :param occurence: which occurence to return e.g. occurence=1 returns the - second time a substring is encountered, defaults to 0 - :type occurence: int, optional - :param start_index: first index from which to search for substring, - defaults to 0 - :type int: int, optional - :return: substring - :rtype: _type_ - """ - - j = 0 - stop_index = len(s) + 1 - - s = s[start_index:stop_index] - while occurence - j >= 0: - if s1 is not None: - i1 = s.index(s1) + len(s1) - else: - i1 = 0 - if s2 is not None: - i2 = s[i1:].index(s2) + i1 - else: - i2 = len(s) - - if occurence - j == 0: - return s[i1:i2] - - s = s[i1:] - j += 1
- -
[docs]def find_nth(haystack: str, needle: str, n: int) -> int: - ''' Return index of nth occurence of substring in string ''' - start = haystack.find(needle) - while start >= 0 and n > 1: - start = haystack.find(needle, start+len(needle)) - n -= 1 - return start
- -
[docs]def get_nth_label( - s: str, - n: int = 1, -): - ''' Return nth label in a string potentially containing multiple labels, - indexing starts from 0 ''' - start = find_nth(s, '__', n=(n*2+1)) - return get_str_btn(s, '__', '__', start_index=start)
-
- -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/_modules/index.html b/_build/_modules/index.html deleted file mode 100644 index 9772cf7..0000000 --- a/_build/_modules/index.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - Overview: module code — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- - -
-
- - - - \ No newline at end of file diff --git a/_build/_sources/CONTRIBUTING.md.txt b/_build/_sources/CONTRIBUTING.md.txt deleted file mode 100644 index f39ccba..0000000 --- a/_build/_sources/CONTRIBUTING.md.txt +++ /dev/null @@ -1,94 +0,0 @@ -# Contributing - -When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. - -Please note we have a code of conduct, please follow it in all your interactions with the project. - -There are two main ways to contribute. One is to make changes to the existing -codes and asimmodules. In this case, please make sure your change passes tests or -submit a test accordinly. The second way to contribute is to add a new asimmodule -to the core set of asimmodules. Reviewers will work with you to make sure your new -asimmodule follows best practice including using utils, syntax highlighting, docs -and tests. - -## Pull Request Process - -1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. -2. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters. -3. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). -4. You may merge the Pull Request in once you have the sign-off of one other developer, or if you do not have permission to do that, you may request the other reviewer to merge it for you. - -## Code of Conduct - -### Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -### Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -### Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -### Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -### Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [INSERT EMAIL ADDRESS]. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -### Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/_build/_sources/README.md.txt b/_build/_sources/README.md.txt deleted file mode 100644 index 17f0cb8..0000000 --- a/_build/_sources/README.md.txt +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - -[Documentation](https://battmodels.github.io/asimtools/) | [GitHub](https://github.com/BattModels/asimtools) - -# Atomic SIMulation Tools - -This package is a lightweight workflow and simulation manager for reproducible -atomistic simulations that can be transferred across environments, calculators -and structures on Unix systems. By using in-built or user-defined asimmodules -and utilities, users can run/build their own simulation recipes and -automagically scale them locally or on slurm based clusters. The core idea is -to separate the dependence of the atomistic potential/calculator and the -simulations steps thereby allowing the same simulation to be run with multiple -calculators/codes and the same calculator to be used for multiple simulation -parameters without altering simulation code. Input and output files follow a -simple consisten file structure and format so that consistent analysis -pipelines can be used across users. For a concrete example of how ASIMTools -achieves this, see the [Developing Custom Asimmodules](https://eeg.engin.umich.edu/asimtools/asimplify.html) page - -## Developer philosophy -The goal of asimtools is to push all the complexity of workflow management, -best-practices, file management etc. into the backend such that the everyday -user only has to handle input files for existing workflows and asimmodule files -for workflows they want to implement.This allows the user to focus on doing the -science and designing experiments. The following are the guiding principles for -how asimtools should work: - -- Asimmodules should resemble boilerplate ASE code as much as possible. -- Asimmodules should avoid explicitly depending on a calculator -- Asimmodules should not explicitly depend on the context/environment in which - they run -- It should be easy to debug individual asimmodules/parts in large workflows. - In addition, it should always be possible to debug/resubmit jobs without - using asimtools. -- Input file structure and format should be standard across all asimmodules. In - addition all input parameters should match how they would like without - asimtools i.e. do not provide an API! -- Job progress tracking must be incorporated for easy debugging -- Best practices should be built-in e.g. if multiple jobs of the same slurm - context are submitted simulataneously, it must be a job array. - -## Philosophy on User Experience -The philosophy is to build "simulations" using building blocks of asimmodules. -Asimmodules are nothing but Python functions that return a dictionary, anything -can be done in the function code. These asimmodules can be as -complicated/efficient as you make them using any external packages you want and -can be optimized with time but can still be run within the framework. This -allows a test friendly way to transition from say a tutorial on the -ASE/pymatgen website to an asimtools asimmodule. So while complicated wrappers -are discouraged, they would still work as long as the asimmodule works. The -benefit out of the box is that you can make your asimmodule independent of -calculator or input structures and submit them easily. - -We also aim to provide a standard set of robust and efficient simulation -protocols as we develop. You can see all the implemented workflows provided -with the package in the examples directory and modify them to your application -If you have suggestions for improvements in methodology or code, please bring -up an issue on github! - -## Getting Started - -These instructions will give you a copy of the project up and running. - -### Installing ASIMTools - -If you prefer to use a conda a environment, you can create and activate one -using: -``` -conda create -n asimtools python=3.9 -conda activate asimtools -``` - -Then you can install asimtools either using pip or by cloning the source code -from github. Note that the cloned version might have some minor bug fixes that -are not included in the official PyPI release. It is also easier to go through -the examples if you clone the repository. - -To install the latest asimtools release from PyPI, you can simply use - -``` -pip install asimtools -``` - -To install from source use - -``` -git clone -https://gitlab.com/ase/ase.git && cd ase pip install . cd ../ - -git clone https://github.com/BattModels/asimtools.git -cd asimtools -pip install . -``` - -You can also choose to use the latest version of ASE since the ones on PyPI and -conda are quite outdated. - -``` -git clone https://gitlab.com/ase/ase.git -cd ase -pip install . -``` - -Individual calculators may need external packages for running them. For example -if you want to use Quantum Espresso or CASTEP, you will have to install them. -Similarly some asimmodules e.g. `lammps.py` might also need external packages -to be used. It is up to the user to make sure those are installed. - -You will also need to setup some environment variables, these variables point -to global `env_input.yaml` and `calc_input.yaml` files with your favorite -configurations since these are commonly shared among simulations. You can also -directly specify them when running `asim-execute` (See `asim-execute -h`). You -can also provide a directory for ASIMTools to search for your custom -asimmodules. Examples of these files can be found in the examples. - -Add the following to your `.bashrc` -``` -export ASIMTOOLS_ENV_INPUT=/path/to/my/global/env_input.yaml -export ASIMTOOLS_CALC_INPUT=/path/to/my/global/calc_input.yaml -export ASIMTOOLS_ASIMMODULE_DIR=/path/to/my/asimmodule/dir -``` - -## Running the tests - -To run tests for the workflow tools, from the tests directory, call: - - pytest - -To run the test suite on a component `component.py` , call: - - pytest test_component.py - -To run all tests for the provided asimmodules, `cd` into the examples directory -and call: - - source run_all.sh - -Or you can run a test for each individual example in its directory using: - - source run.sh - -If no errors are reported, the tests have passed. These tests simply test the -functionality of the code, not the scientific validity of the simulations! - -To run tests for the provided asimmodules using slurm, you can similarly run -the bash scripts ending with `_slurm.sh`. This will submit a number of jobs, -none longer than 1 minute. - -## Contributing - -Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code -of conduct, and the process for submitting pull requests to us. - -## Authors - - - **Keith Phuthi** - [mkphuthi](https://github.com/mkphuthi) - - **Emil Annevelink** - [emilannevelink](https://github.com/emilannevelink) - -See also the list of -[contributors](https://github.com/BattModels/asimtools.git/contributors) -who participated in this project. - -## License - -This project is licensed under the MIT License - - diff --git a/_build/_sources/asimplify.rst.txt b/_build/_sources/asimplify.rst.txt deleted file mode 100644 index fd01c09..0000000 --- a/_build/_sources/asimplify.rst.txt +++ /dev/null @@ -1,336 +0,0 @@ -Developing Custom Asimmodules -============================= - -This section will guide you through taking your own in-house simulation and -integrating it into asimtools. The process is designed to be as -straight-forward as reasonably possible and with continued user-feedback we -hope to make it more seamless. - -As an example, we will ASIMplify the calculation of equations of state as shown -in ASE. To understand the code, visit the ASE `tutorials page `_. -Ultimately, the ASIMplified code will work with any chemical species, any -supported calculator and any configured computing environment with fully -parallelizable job submission on HPCs in just a few steps! - -The code is given below: - -.. code-block:: - - from ase.build import bulk - from ase.calculators.emt import EMT - from ase.eos import calculate_eos - from ase.db import connect - - db = connect('bulk.db') - for symb in ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']: - atoms = bulk(symb, 'fcc') - atoms.calc = EMT() - eos = calculate_eos(atoms) - v, e, B = eos.fit() # find minimum - # Do one more calculation at the minimum and write to database: - atoms.cell *= (v / atoms.get_volume())**(1 / 3) - atoms.get_potential_energy() - db.write(atoms, bm=B) - -There are a couple of issues here that make it difficult to make this a -high-throughput calculation. First, because we directly setup the calculator in -the code, if we want to change the calculator we have to change the code. The -same applies for the structures and chosen chemical species. In addition, the -current code runs independent calculations one after the other. If each of -these calculations was an expensive calculation, it would be much less -efficient than running them in separate jobs on a HPC with a job scheduler. To -fix any of these issues, we would have to modify the code, job scripts and -perhaps even file structure. We will show how ASIMTools can help with all of -these issues. The end-result will be that any of these changes can made without -touching code or a job script. - -1. Build and test with a cheap calculator ------------------------------------------ -To make things easier, it is best to first replace the -expensive parts of your workflow with toy examples e.g. use an empirical -calculator like EMT instead of DFT, use a smaller/simpler structure, loop -over fewer cases etc. - -The ASE example already uses a simple EMT calculator and simple structures. - -2. Wrap in a function ---------------------- -The workhorse of ASIMTools is the asimmodule, any code -wrapped in a function that returns a dictionary can be run within the -ASIMTools framework. The easiest thing to do would be to take the code and -copy and paste it in a function which is defined inside an asimmodule with the -same name - -.. code-block:: - - from ase.build import bulk - from ase.calculators.emt import EMT - from ase.eos import calculate_eos - from ase.db import connect - - def ase_eos(): - db = connect('bulk.db') - for symb in ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']: - atoms = bulk(symb, 'fcc') - atoms.calc = EMT() - eos = calculate_eos(atoms) - v, e, B = eos.fit() # find minimum - # Do one more calculation at the minimu and write to database: - atoms.cell *= (v / atoms.get_volume())**(1 / 3) - atoms.get_potential_energy() - db.write(atoms, bm=B) - - return {} - -Immediately as it is, this is an asimmodule can be run in ASIMTools. You can -run it with the following sim_input.yaml - -.. code-block:: yaml - - asimmodule: /path/to/ase_eos.py - env_id: inline - workdir: results - -then call - -.. code-block:: console - - asim-execute sim_input.yaml - -Only a little bit more complicated than calling ``python ase_eos.py`` - -3. Make the asimmodule use any calculator ------------------------------------------ -This asimmodule however still depends on specific structures and a specific -calculator. Let's do the easy thing first, let's make the asimmodule work with any -calculator using a simple change. - -.. code-block:: - - from ase.build import bulk - from ase.eos import calculate_eos - from ase.db import connect - from asimtools.calculators import load_calc - - def ase_eos( - calc_id, - ): - calc = load_calc(calc_id) - db = connect('bulk.db') - for symb in ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']: - atoms = bulk(symb, 'fcc') - atoms.calc = calc - eos = calculate_eos(atoms) - v, e, B = eos.fit() # find minimum - # Do one more calculation at the minimu and write to database: - atoms.cell *= (v / atoms.get_volume())**(1 / 3) - atoms.get_potential_energy() - db.write(atoms, bm=B) - - return {} - -Just like that we can now run the asimmodule with any correctly configured -calculator for all the structures! We can even now run ``calc_array`` to -iterate getting the results using different calculators. - -4. Make the asimmodule use any structure ----------------------------------------- -The final change we will make is to parallelize over structures as below - -.. code-block:: - - from ase.build import bulk - from ase.eos import calculate_eos - from ase.db import connect - from asimtools.calculators import load_calc - - def ase_eos( - image, - calc_id, - ): - calc = load_calc(calc_id) - db = connect('bulk.db') - atoms = get_atoms(**image) - atoms.calc = calc - eos = calculate_eos(atoms) - v, e, B = eos.fit() # find minimum - # Do one more calculation at the minimu and write to database: - atoms.cell *= (v / atoms.get_volume())**(1 / 3) - atoms.get_potential_energy() - db.write(atoms, bm=B) - - return {} - -Easy-peasy. We now have an asimmodule that works with arbitrary environment, -arbitrary calculator and arbitrary input structure (Of course the simulation -will fail if we give a bad structure/calculator for example) - -5. Final cleanup ----------------- -We can do some final cleanup of the asimmodule so that it sends outputs to -``output.yaml`` and logs some checkpoints. Additionally, any asimmodules added -to the repository will need clear syntax highlighting and documentation. - -.. code-block:: - - from typing import Dict - import logging - from ase.eos import calculate_eos - from ase.db import connect - from asimtools.calculators import load_calc - from asimtools.utils import get_atoms - - def ase_eos( - image: Dict, - calc_id: str, - db_file: 'bulk.db' - ) -> Dict: - calc = load_calc(calc_id) - db = connect(db_file) - atoms = get_atoms(**image) - atoms.calc = calc - eos = calculate_eos(atoms) - v, e, B = eos.fit() # find minimum - logging.info('Successfully fit EOS') - # Do one more calculation at the minimu and write to database: - atoms.cell *= (v / atoms.get_volume())**(1 / 3) - atoms.get_potential_energy() - db.write(atoms, bm=B) - - results = {'v': float(v), 'e': float(e), 'B': float(B)} - return results - -To run this asimmodule on an arbitrary structure say Argon with say the -LennardJones calculator, in a slurm job we can now use the following input -files. - -sim_input.yaml: - -.. code-block:: yaml - - asimmodule: /path/to/ase_eos.py - env_id: batch - workdir: results - args: - image: - builder: bulk - name: Ar - calc_id: lj_Ar - -calc_input.yaml: - -.. code-block:: yaml - - lj_Ar: - name: LennardJones - module: ase.calculators.lj - args: - sigma: 3.54 - epsilon: 0.00802236 - emt: #This is not used if an LJ calculator is chosen - name: EMT - module: ase.calculators.emt - args: {} - -env_input.yaml: - -.. code-block:: yaml - - batch: - mode: - use_slurm: true - interactive: false - slurm: - flags: - - -n 2 - precommands: - - source ~/.bashrc - - conda activate asimtools - inline: # This is not used if env_id is batch - mode: - use_slurm: false - interactive: true - -6. Running multiple simulations in a workflow ---------------------------------------------- -Going back to the original problem, we wanted to run the simulation of multiple -different elements with the EMT calculator. To achieve that in parallel, we can -nest the ``ase_eos`` asimmodule in a -:func:`asimtools.asimmodules.workflows.sim_array.sim_array` asimmodule as follows - -sim_input.yaml: - -.. code-block:: yaml - - asimmodule: workflows.sim_array - workdir: results - args: - key_sequence: ['args', 'image', 'name'] - array_values: ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au'] - env_ids: 'batch' - template_sim_input: - asimmodule: /path/to/ase_eos.py - args: - calc_id: emt - image: - builder: bulk - crystalstructure: 'fcc' - -To make the asimmodule easier to access without having to use the full path, you -can set the environment variable - -.. code-block:: console - - export ASIMTOOLS_ASIMMODULE_DIR=/path/to/my/asimmodule/dir/ - -You can then move the ``ase_eos.py`` asimmodule to -``/path/to/my/asimmodule/dir/`` i.e. the asimmodule directory. This allows you -to refer to asimmodules prepended with the asimmodule dir as below - -.. code-block:: yaml - - asimmodule: workflows.sim_array - workdir: results - args: - key_sequence: ['args', 'image', 'name'] - array_values: ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au'] - env_ids: 'batch' - template_sim_input: - asimmodule: ase_eos/ase_eos.py - args: - calc_id: emt - image: - builder: bulk - crystalstructure: 'fcc' - -The above example loops over crystals for which ASE already has FCC lattice -parameters, but what if we want to loop over the species and corresponding -lattice parameters? We can either specify a list of ``images`` dictionaries as -``array_values`` or use ``secondary_array_values``. We can also explicitly tell -ASIMTools to include the array_values in the directory names in the standard -format (e.g. ``id-0000__Al__``, ``id-0001__Ni__`` etc.). - -.. code-block:: yaml - - asimmodule: workflows.sim_array - workdir: results - args: - key_sequence: ['args', 'image', 'name'] - array_values: ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au'] - labels: values - secondary_key_sequences: - - ['args', 'image', 'a'] - secondary_array_values: - - [4.0479, 3.524, 3.6149, 3.8907, 4.0853, 3.9242, 4.0782] - env_ids: 'batch' - template_sim_input: - asimmodule: ase_eos/ase_eos.py - args: - calc_id: emt - image: - builder: bulk - crystalstructure: 'fcc' - -This will perform the EOS calculation for each species with the corresponding -lattice parameter. That's 7x5=35 calculations in parallel without touching code -or a job script! diff --git a/_build/_sources/asimtools.asimmodules.benchmarking.rst.txt b/_build/_sources/asimtools.asimmodules.benchmarking.rst.txt deleted file mode 100644 index 1582ba2..0000000 --- a/_build/_sources/asimtools.asimmodules.benchmarking.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -asimtools.asimmodules.benchmarking package -========================================== - - - -asimtools.asimmodules.benchmarking.parity module ------------------------------------------------- - -.. automodule:: asimtools.asimmodules.benchmarking.parity - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.benchmarking - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.elastic_constants.rst.txt b/_build/_sources/asimtools.asimmodules.elastic_constants.rst.txt deleted file mode 100644 index d5619d4..0000000 --- a/_build/_sources/asimtools.asimmodules.elastic_constants.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -asimtools.asimmodules.elastic\_constants package -================================================ - - - -asimtools.asimmodules.elastic\_constants.cubic\_energy\_expansion module ------------------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.elastic_constants.cubic_energy_expansion - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.elastic_constants - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.eos.rst.txt b/_build/_sources/asimtools.asimmodules.eos.rst.txt deleted file mode 100644 index b79c880..0000000 --- a/_build/_sources/asimtools.asimmodules.eos.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -asimtools.asimmodules.eos package -================================= - - - -asimtools.asimmodules.eos.postprocess module --------------------------------------------- - -.. automodule:: asimtools.asimmodules.eos.postprocess - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.eos - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.geometry_optimization.rst.txt b/_build/_sources/asimtools.asimmodules.geometry_optimization.rst.txt deleted file mode 100644 index 2133eb5..0000000 --- a/_build/_sources/asimtools.asimmodules.geometry_optimization.rst.txt +++ /dev/null @@ -1,52 +0,0 @@ -asimtools.asimmodules.geometry\_optimization package -==================================================== - - - -asimtools.asimmodules.geometry\_optimization.ase\_cubic\_eos\_optimization module ---------------------------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.geometry\_optimization.atom\_relax module ---------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.geometry_optimization.atom_relax - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.geometry\_optimization.cell\_relax module ---------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.geometry_optimization.cell_relax - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.geometry\_optimization.optimize module ------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.geometry_optimization.optimize - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.geometry\_optimization.symmetric\_cell\_relax module --------------------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.geometry_optimization.symmetric_cell_relax - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.geometry_optimization - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.lammps.rst.txt b/_build/_sources/asimtools.asimmodules.lammps.rst.txt deleted file mode 100644 index c4c7427..0000000 --- a/_build/_sources/asimtools.asimmodules.lammps.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -asimtools.asimmodules.lammps package -==================================== - - - -asimtools.asimmodules.lammps.lammps module ------------------------------------------- - -.. automodule:: asimtools.asimmodules.lammps.lammps - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.lammps - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.phonons.rst.txt b/_build/_sources/asimtools.asimmodules.phonons.rst.txt deleted file mode 100644 index d7ac070..0000000 --- a/_build/_sources/asimtools.asimmodules.phonons.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -asimtools.asimmodules.phonons package -===================================== - - - -asimtools.asimmodules.phonons.ase\_phonons module -------------------------------------------------- - -.. automodule:: asimtools.asimmodules.phonons.ase_phonons - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.phonons - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.rst.txt b/_build/_sources/asimtools.asimmodules.rst.txt deleted file mode 100644 index 74e4281..0000000 --- a/_build/_sources/asimtools.asimmodules.rst.txt +++ /dev/null @@ -1,52 +0,0 @@ -asimtools.asimmodules package -============================= - - - -.. toctree:: - :maxdepth: 4 - - asimtools.asimmodules.benchmarking - asimtools.asimmodules.elastic_constants - asimtools.asimmodules.eos - asimtools.asimmodules.geometry_optimization - asimtools.asimmodules.lammps - asimtools.asimmodules.phonons - asimtools.asimmodules.surface_energies - asimtools.asimmodules.transformations - asimtools.asimmodules.vacancy_formation_energy - asimtools.asimmodules.workflows - - - -asimtools.asimmodules.do\_nothing module ----------------------------------------- - -.. automodule:: asimtools.asimmodules.do_nothing - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.singlepoint module ----------------------------------------- - -.. automodule:: asimtools.asimmodules.singlepoint - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.template module -------------------------------------- - -.. automodule:: asimtools.asimmodules.template - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.surface_energies.rst.txt b/_build/_sources/asimtools.asimmodules.surface_energies.rst.txt deleted file mode 100644 index 07cdae7..0000000 --- a/_build/_sources/asimtools.asimmodules.surface_energies.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -asimtools.asimmodules.surface\_energies package -=============================================== - - - -asimtools.asimmodules.surface\_energies.surface\_energies module ----------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.surface_energies.surface_energies - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.surface_energies - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.transformations.rst.txt b/_build/_sources/asimtools.asimmodules.transformations.rst.txt deleted file mode 100644 index 52170fb..0000000 --- a/_build/_sources/asimtools.asimmodules.transformations.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -asimtools.asimmodules.transformations package -============================================= - - - -asimtools.asimmodules.transformations.scale\_unit\_cells module ---------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.transformations.scale_unit_cells - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.transformations - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.vacancy_formation_energy.rst.txt b/_build/_sources/asimtools.asimmodules.vacancy_formation_energy.rst.txt deleted file mode 100644 index 30cb7a8..0000000 --- a/_build/_sources/asimtools.asimmodules.vacancy_formation_energy.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -asimtools.asimmodules.vacancy\_formation\_energy package -======================================================== - - - -asimtools.asimmodules.vacancy\_formation\_energy.vacancy\_formation\_energy module ----------------------------------------------------------------------------------- - -.. automodule:: asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.vacancy_formation_energy - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.asimmodules.workflows.rst.txt b/_build/_sources/asimtools.asimmodules.workflows.rst.txt deleted file mode 100644 index 137c318..0000000 --- a/_build/_sources/asimtools.asimmodules.workflows.rst.txt +++ /dev/null @@ -1,52 +0,0 @@ -asimtools.asimmodules.workflows package -======================================= - - - -asimtools.asimmodules.workflows.calc\_array module --------------------------------------------------- - -.. automodule:: asimtools.asimmodules.workflows.calc_array - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.workflows.chained module ----------------------------------------------- - -.. automodule:: asimtools.asimmodules.workflows.chained - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.workflows.distributed module --------------------------------------------------- - -.. automodule:: asimtools.asimmodules.workflows.distributed - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.workflows.image\_array module ---------------------------------------------------- - -.. automodule:: asimtools.asimmodules.workflows.image_array - :members: - :undoc-members: - :show-inheritance: - -asimtools.asimmodules.workflows.sim\_array module -------------------------------------------------- - -.. automodule:: asimtools.asimmodules.workflows.sim_array - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools.asimmodules.workflows - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/asimtools.rst.txt b/_build/_sources/asimtools.rst.txt deleted file mode 100644 index 4e1ba28..0000000 --- a/_build/_sources/asimtools.rst.txt +++ /dev/null @@ -1,43 +0,0 @@ -asimtools package -================= - - - -.. toctree:: - :maxdepth: 4 - - asimtools.asimmodules - - - -asimtools.calculators module ----------------------------- - -.. automodule:: asimtools.calculators - :members: - :undoc-members: - :show-inheritance: - -asimtools.job module --------------------- - -.. automodule:: asimtools.job - :members: - :undoc-members: - :show-inheritance: - -asimtools.utils module ----------------------- - -.. automodule:: asimtools.utils - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: asimtools - :members: - :undoc-members: - :show-inheritance: diff --git a/_build/_sources/include_contributing.rst.txt b/_build/_sources/include_contributing.rst.txt deleted file mode 100644 index 78dbb13..0000000 --- a/_build/_sources/include_contributing.rst.txt +++ /dev/null @@ -1,5 +0,0 @@ -Contributing to ASIMTools -========================= - -.. include:: CONTRIBUTING.md - :parser: myst_parser.sphinx_ diff --git a/_build/_sources/include_readme.rst.txt b/_build/_sources/include_readme.rst.txt deleted file mode 100644 index f2253cd..0000000 --- a/_build/_sources/include_readme.rst.txt +++ /dev/null @@ -1,5 +0,0 @@ -README -====== - -.. include:: README.md - :parser: myst_parser.sphinx_ diff --git a/_build/_sources/index.rst.txt b/_build/_sources/index.rst.txt deleted file mode 100644 index 4e56338..0000000 --- a/_build/_sources/index.rst.txt +++ /dev/null @@ -1,28 +0,0 @@ -.. asimtools documentation master file, created by - sphinx-quickstart on Sat Jul 1 18:22:31 2023. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to asimtools's documentation! -===================================== - -.. toctree:: - :maxdepth: 12 - :caption: Contents: - - README - Running asimmodules - Custom asimmodules - Workflows - API Docs - Contributing - - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/_build/_sources/modules.rst.txt b/_build/_sources/modules.rst.txt deleted file mode 100644 index f4e9fc8..0000000 --- a/_build/_sources/modules.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -asimtools -========= - -.. toctree:: - :maxdepth: 4 - - asimtools diff --git a/_build/_sources/usage.rst.txt b/_build/_sources/usage.rst.txt deleted file mode 100644 index 6b7a632..0000000 --- a/_build/_sources/usage.rst.txt +++ /dev/null @@ -1,527 +0,0 @@ -Running an Existing Asimmodule -============================== - -This section will guide you through running an already existing asimmodule -whether it be one of the asimmodules provided in the main repository, from the -asimmodule repository or a custom asimmodule you have written yourself. - -To run a simulation, all you need to do is run either of the following -commands: - -.. code-block:: console - - asim-execute sim_input.yaml -c calc_input.yaml -e env_input.yaml - -Providing ``calc_input.yaml`` or ``env_input.yaml`` is optional. If not -provided, the globally configured files will be used. See :ref:`envinput`. This -command will automatically run the specified simulation in the correct -directory and environment. - -In rare cases, you can use the following command: - -.. code-block:: console - - asim-run sim_input.yaml -c calc_input.yaml - -This command will run the simulation in the current directory and environment. -For most cases, you will only ever use ``asim-execute``. The differences -between ``asim-execute`` and ``asim-run`` are explained in -:ref:`asimrunvsasimexecute`. - -.. _inputs: - -In summary, the steps you need to take to start using any of the in-built -asimmodules, described in detail below, are the following: - -1. Install ASIMTools in you python environment or add it to your - ``PYTHONPATH``. -2. Setup your global ``env_input.yaml`` and ``calc_input.yaml`` and set the - environment variables pointing to them. -3. Write a ``sim_input.yaml`` based on the examples provided in the repository. - Do not hesitate to submit an issue if you are confused as we are still in a - testing phase -4. asim-execute! - -Input files -*********** - -.. _envinput: - -env_input.yaml --------------- -One can provide an ``env_input.yaml`` file that details the kind -of environments in which asimmodules can be run. This file can be provided with -the asim-execute command using the ``-e`` flag or set globally. An example of -an env_input.yaml file is given below - -.. code-block:: yaml - - # template - env_id: - mode: - use_slurm: true - interactive: false - run_prefix: ... - run_suffix: ... - slurm: - flags: [flag1, flag2, ...] - precommands: [precommand1, precommand2, ...] - postcommands: [postcommand1, postcommand2, ...] - - # Concrete examples below - inline: # Run the asimmodule directly in the console - mode: - use_slurm: false - interactive: true - - batch_job: # Submit a batch job using slurm with 2 tasks - mode: - use_slurm: true - interactive: false - slurm: - flags: - - -n 2 - - --mem-per-cpu=2G - precommands: - - source ~/.bashrc - - conda activate asimtools - postcommands: - - conda deactivate asimtools - # Submit an interactive job using slurm, you can use a dictionary - # for the flags - interactive_job: - mode: - use_slurm: true - interactive: true - slurm: - flags: - -n: 2 - --gres: gpu:2 - precommands: - - module load lammps - -The highest level key is the ``env_id`` which is the one specified in the -``sim_input.yaml``. An ``env_input.yaml`` can have any number of ``env_id`` s. -That way you can specify one global file if you use the same environments -repeatedly. You can configure a global config file by setting -the environment variable. - -.. code-block:: console - - export ASIMTOOLS_ENV_INPUT=/path/to/my/global/env_input.yaml - -If you do not provide an ``env_input.yaml`` and there is no file called -``env_input.yaml`` in the work directory, ASIMTools will look for the -``env_id`` in the global file. - -The parameters, required, shown in the template section are described below - -- **env_id**: (str) unique key for identifying the environment, ``env_id`` in - ``sim_input.yaml`` must match one of the ``env_id`` s defined in the - ``env_input.yaml`` being used. -- **env_id.mode.use_slurm**: (bool) whether or not to request a slurm - allocation to run the asimmodule -- **env_id.mode.interactive**: (bool) whether or not to run the asimmodule - directly in the terminal (using ``salloc``) or to submit a batch job (using - ``sbatch``). -- **env_id.mode.run_prefix**: (str) string to append before running the - asimmodule e.g. if ``run_prefix=mpirun`` the asimmodule will be invoked with - the equivalent of ``mpirun python my_asimmodule.py``. ``run_prefix`` in - ``env_input.yaml`` is always prepended before the one provided by - ``calc_input.yaml``. -- **env_id.mode.run_suffix**: (str) string to append after running the - asimmodule e.g. if ``run_suffix: ' &> out.txt'`` is provided, the asimmodule - will be invoked with the equivalent of ``python my_asimmodule.py &> - out.txt``. ``run_suffix`` in ``env_input.yaml`` is always appended after the - one provided by ``calc_input.yaml``. -- **env_id.slurm.flags**: (list/dict, optional) The slurm flags for the - allocation as a list of flags e.g. ``[-n 4, -N 1]``. One can also specify a - dictionary e.g. ``'{-n': 4, '-N': 1, '--mem':2G}`` -- **env_id.slurm.precommands**: (list, optional) Commands to be run/added to - the job script before running the asimmodule. A common use case is loading - a module or activating an environment. -- **env_id.slurm.postcommands**: (list, optional) Commands to be run/added to - the job asimmodule after running the asimmodule. e.g. for file cleanup or - moving files after the job is complete. - -.. _calcinput: - -calc_input.yaml ---------------- -The ``calc_input.yaml`` is used to configure an ASE calculator. As -above, a global configuration file can be set using - -.. code-block:: console - - export ASIMTOOLS_CALC_INPUT=/path/to/my/global/calc_input.yaml - -or provided to asim-execute at run time. Note that if you launch a chained -workflow with ``asim-run`` instead of ``asim-execute``, asimmodules farther -down the chain will use the global ``calc_input.yaml``, so always use -``asim-execute`` - -.. code-block:: yaml - - # Template - calc_id: - name: ... - module: ... - precommands: [precommand1, ...] - postcommands: [postcommand1, ...] - run_prefix: ... - run_suffix: ... - args: - arg1: value_1 - ... - - # Concrete examples - # Here is a simple LJ potential from ASE - lj: - name: LennardJones - module: ase.calculators.lj - args: - sigma: 3.54 - epsilon: 0.00802236 - - # GPAW needs a run_prefix to work in parallel using mpirun - gpaw: - name: GPAW - module: gpaw.calculator - run_prefix: mpirun - args: - kpts: [2,2,2] - h: 0.1 - xc: PBE - txt: gpaw_output.txt - - # You can install a universal potential like MACE and define it as well, see - # asimtools/calculators.py for implemented external calculators. Submit an - # issue if you want one to be implemented. - MACE32-medium: - name: MACE - args: - model: medium - use_device: cuda - -The parameters for the calculators provided directly in ASE are specified under -the assumption that the calculator will be initiated as follows: - -.. code-block:: - - from module import name - calc = name(**args) - -This works for all calculators defined in ASE v3.22 and below, for newer -versions of ASE, you might need to use the versions that use profiles e.g. use -``name: EspressoProfile`` not ``name: Espresso`` until those become stable in -ASE. For externally defined calculators, you can submit an issue and we will -implement it. For example, calculators for NequIP, Deep Potential, MACE, CHGNet -and M3GNet force fields are implemented. - -- **calc_id**: (str) unique key for identifying the calculator, ``calc_id`` in - ``sim_input.yaml`` must match one of the ``calc_id`` s defined in the - provided ``calc_input.yaml`` -- **calc_id.name**: (str) Either the name of the class or the reference to one - of the provided external calculators. -- **calc_id.module**: (str) The module from which the calculator class is - imported. e.g. if ``name=LennardJones`` and ``module=ase.calculators.lj``, - then the calculator object is imported as ``from ase.calculators.lj import - LennardJones``. This works if the calculator is available in ASE or follows - ASE format for initialization such as GPAW. Any other ASE calculator will - need to have the instantiation defined in :ref:calculators.py -- **calc_id.mode.run_prefix**: (str) string to append before running the - asimmodule e.g. if ``run_prefix=mpirun`` the asimmodule will be invoked with - the equivalent of ``mpirun python my_asimmodule.py``. ``run_prefix`` in - ``env_input.yaml`` is always prepended before the one provided by - ``calc_input.yaml``. -- **calc_id.mode.run_suffix**: (str) string to append after running the - asimmodule e.g. if ``run_postfix=' &> out.txt'`` the asimmodule will be - invoked with the equivalent of ``python my_asimmodule.py &> out.txt``. - ``run_postfix`` in ``env_input.yaml`` is always appended after the one - provided by ``calc_input.yaml``. -- **calc_id.precommands**: (list, optional) Commands to be run/added to the job - asimmodule before running the asimmodule. A common use case is loading a - module or activating an environment -- **calc_id.postcommands**: (list, optional) Commands to be run/added to the - job asimmodule after running the asimmodule. e.g. cleaning up bulky tmp or - wavefunction files -- **calc_id.args**: (dict) key-value pairs to be passed as arguments for the - initialization of the calculator class. e.g. if the class is LennardJones, - the arguments are passed as ``calc = LennardJones(**{'sigma':3.2, - 'epsilon':3})`` - -.. _siminput: - -sim_input.yaml --------------- - -The minimal requirement to run an asimmodule is to provide a ``sim_input.yaml`` -file. An example of a ``sim_input.yaml`` is shown below: - -.. code-block:: yaml - - asimmodule: singlepoint - env_id: inline - overwrite: false - submit: true - workdir: results - precommands: - - export MY_ENV_VAR=3 - args: - arg1: value_1 - arg2: value_2 - ... - -The parameters are: - -- **asimmodule**: (str) name of core asimmodule or /path/to/my/asimmodule.py. - Core asimmodules defined in the asimmodules directory can be simply referred - to using Python dot notation. E.g. to specify the - :func:`asimtools.asimmodules.workflows.sim_array` asimmodule, you would - specify `workflows.sim_array`. Any other asimmodule should be specified as - either a full path or a path relative to ``ASIMTOOLS_ASIMMODULE_DIR`` - variable to a python file. E.g. ``my_asimmodules/asim_ple.py`` -- **env_id**: (str, optional) Environment/context in which to run asimmodule - configured in env_input.yaml, defaults to running in the current console -- **overwrite**: (bool, optional) (bool) whether or not to overwrite work - directories if they exist, defaults to false -- **submit**: (bool, optional) whether to run the asimmodule. If set to false - it will just write the input files which is very useful for testing before - submitting large workflows. You can go in and test one example before - resubmitting with ``submit=True``, defaults to true -- **workdir**: (str, optional) The directory in which the asimmodule will be - run, `asim-execute` will create the directory whereas `asim-run` ignores this - parameter entirely, defaults to './results' -- **precommands**: (list, optional) a list of commands to run in the console - before running the asimmodule, defaults to empty list -- **postcommands**: (list, optional) a list of commands to run in the console - after running the asimmodule, defaults to empty list -- **args**: (dict) The arguments of the function being called in the asimmodule - as key-value pairs. These are specific to the asimmodule being run. - -All ASIMTools generated files are named ``sim_input.yaml`` but you can name -user defined files as whatever you like - -.. _specifyingimages: - -Specifying Images/Atoms ------------------------ - -One of the most useful applications of ASIMTools is the unification of methods -for setting up ASE atoms objects using the same interface. If an asimmodule -requires a single or multiple atoms objects as input, they are provided as -either an ``image`` dictionary for a single Atoms object or ``images`` for a -list of Atoms objects as part of the ``args`` section. Below are the different -ways to get an atoms object. You can also download images from The Materials -Project and for some cases generate them using Pymatgen. - -For a detailed description of the API and examples, see -:func:`asimtools.utils.get_atoms` - -.. code-block:: yaml - - # Reading a specific image from a structure file using ase.io.read - image: - image_file: /path/to/my/ASE-readable/image/file.xyz - # Optional keyword argument passed to ase.io.read - index: 3 - - # Building a bulk crystal using ase.build.bulk - image: - builder: bulk - # Optional keyword arguments passed to the builder, must match ASE exactly - name: Li - crystalstructure: bcc - a: 4.3 - cubic: True - - # Building a surface using ase.build.fcc100 - image: - builder: fcc100 - # Optional keyword arguments passed to the builder, must match ASE exactly - symbol: Fe - vacuum: 8 - periodic: False - - # Building a 3x3x3 supercell of Ar using ase.build.bulk then - # Atoms.repeat(repeat) and then applying Atoms.rattle(stdev=rattle_stdev) - image: - name: Ar - repeat: [3,3,3] - rattle_stdev: 0.01 - - # You can even supply an atoms object directly so that the interface is - # universal. This is most useful in the asimmodule code itself. - image: - atoms: Atoms - - # An example downloading a structure from Materials Project using your own - # USER_API_KEY - image: - mp_id: 'mp-14' - interface: pymatgen - user_api_key: "USER_API_KEY" - conventional_unit_cell': true - - -Similarly, if the asimmodule requires multiple image inputs, there exists a -universal interface. The keyword is usually specified as ``images``. This is -especially useful for distributing simulations across multiple structures or -reading structures from multiple previous simulations, even in different -directories. - -For a detailed description of the API, see :func:`asimtools.utils.get_images` - -.. code-block:: yaml - - # Reading specific images from a structure file using ase.io.read - images: - image_file: /path/to/my/ASE-readable/image/file.xyz - # Optional keyword arguments passed to ase.io.read - index: '3:8' - format: extxyz - - # You can read all files matching a certain pattern using a wildcard - images: - pattern: /path/to/my/structure/files/*.cif - # Optional keyword argument passed to ase.io.read - index: -1 - - # You can read all files matching certain patterns using a wildcard - images: - patterns: - - /path/to/my/structure/files/*.cif - - /path/to/my/other/structure/files/*.cfg - - # You can even supply a list of atoms objects directly so that the interface - # is universal. This is most useful in the asimmodule code itself. - images: - images: [Atoms1, Atoms2, ...] - -.. _asimrunvsasimexecute: - -Usage of asim-execute and asim-run -********************************** -The major difference between ``asim-execute`` and ``asim-run`` is that, -``asim-execute`` takes into account the ``workdir`` and the ``env_id``. -``asim-run`` will run the asimmodule in the current directory and in the -current console. In fact, ``asim-execute`` will create the ``workdir`` and then -run ``asim-run`` in the correct environment/batch job. You can always for -example, request a slurm allocation, go to the directory where you want the -asimmodule to be run and call ``asim-run`` from there if you would like more -control or to debug. If you want verbose logs for debugging, you can run with -the ``-d`` or ``--debug`` flag. - -.. _outputs: - -Output files -************ -A job or asimmodule run through ASIMTools will always produce a standard set of -output files in addition to whatever outputs the asimmodule produces. In -particular the most important outputs are the ``output.yaml`` and the -``job.log`` file. - -#. \``output.yaml`` contains the status of the job being run in the current - directory which can be one of ``clean, started, complete, failed, discard``. - The statuses are self-explanatory, the ``discard`` status is never written - by ASIMTools but a user can edit an ``output.yaml`` file and change it's - status to ``discard`` to tell ASIMTools to ignore that job in any workflows. - This is common for example if you launch multiple jobs and one of them fails - irredemably. Deleting the directory for that job is also ok if nothing - depends on it downstream. Importantly, any results returned by the function - defined in the asimmodule are found in ``output.yaml``. Asimmodule functions - should always return a dictionary of only primitive types for this purpose. - - An example of an ``output.yaml`` file is shown below. - -.. code-block:: yaml - - # Successful output for singlepoint asimmodule - end_time: 2023-08-28 21:50:51.368025 - energy: 13.77302319846367 #This was added by the scinglepoint asimmodule - files: - image: image_output.xyz - job_ids: '372919' - start_time: 2023-08-28 21:50:46.188300 - status: complete - - # Failed output - start_time: 14:29:55, 10/06/23 - status: failed - -#. ``job.log`` captures the logged output of ``asim-run`` or asimmodules - that use logging. It is extremely useful for debugging as following the logs - starting from the base directory will usually lead you to the correct - traceback that caused the failure. - -#. ``stderr.txt`` captures errors and backtraces from running asimmodules. This - is usually the most informative file for debugging. You can be directed to - the correct one by noting errors in ``job.log`` files. - -#. ``stdout.txt`` captures any stdout from running asimmodules. It is mostly a - safety measure for catching anything that prints to stdout and rarely has - useful information unless you write an asimmodule that uses ``print`` - statements. In batch jobs, this output this goes to the slurm job output. - -#. ``input_image.xyz`` and ``input_images.xyz`` capture the images input into - the asimmodule. This makes sure there is a concrete artifact for the - structure used by the asimmodule for the purposes of visualization and - debugging. They are always in ``extxyz`` format as a flexible standard - format - -#. ``slurm*`` are slurm job files which can be named according to flags - specified in ``env_input.yaml`` otherwise are named - ``slurm_stdout.id-%a_j%A`` or ``slurm_stderr.id-%a_j%A`` after job and array - IDs - -.. _restarting: - -Checking job status and Restarting failed jobs -********************************************** -To check the status of jobs, even complicated chains and distributed jobs, we -provide the ``asim-check`` utility which can be run using: - -.. code-block:: console - - asim-check /path/to/sim_input.yaml - -This will print the job tree, including statuses and work directories of the -jobs whose root directory is specified as ``workdir`` in ``sim_input.yaml``. - -In many cases, there may be mistakes in one of your configuration files leading -to a failed workflow. In these cases there are a few ways you could resolve the -issue: - -* Delete the work directory and restart the workflow. This is why it is - recommended that the base ``sim_input.yaml`` has ``workdir`` set to a new - directory that only has the results of the workflow. -* Modify the ASIMTools generated ``sim_input.yaml`` to fix the problem. If - there are downstream ``sim_input.yaml`` files in a chain, they will have to - be deleted or set ``overwrite=True``. Deleting is recommended for safety - purposes. -* Simply rerun ``asim-execute``. This will rerun the jobs, skipping any jobs - with a status of ``complete`` or ``discard``. Note that error files are not - deleted so you will have to clear those manually. Use this with caution! - -Importing functions from asimmodules and the API -************************************************ - -Because asimmodules contain what are merely Python functions, you can always -import them and use them in any other code for example, you can import -:func:`asimtools.asimmodules.singlepoint` and use it as below. - -.. code-block:: python - - from asimtools.asimmodules.singlepoint import singlepoint - - results = singlepoint(image={'name': 'Ar'}, calc_id='lj') - print(results) - -You can also use the utils and tools e.g. to load a calculator using just a -``calc_id`` - -.. code-block:: python - - from asimtools.calculators import load_calc - - calc = load_calc('lj') diff --git a/_build/_sources/workflows.rst.txt b/_build/_sources/workflows.rst.txt deleted file mode 100644 index 4867ded..0000000 --- a/_build/_sources/workflows.rst.txt +++ /dev/null @@ -1,33 +0,0 @@ -Using built-in workflow tools -============================= - -ASIMTools offers some standard tools for performing common workflows. These -are: - -#. :func:`asimtools.asimmodules.sim_array.sim_array` - Run the same asimmodule - with one or more specified arguments of the asimmodule iterated over. This - is the most useful asimmodule and can substitute most others except - ``chained`` - -#. :func:`asimtools.asimmodules.image_array.image_array` - Run the same - asimmodule on multiple images, e.g. a repeat calculation on a database - -#. :func:`asimtools.asimmodules.calc_array.calc_array` - Run the same - asimmodule using different calc_ids or calculator parameters based on a - template. e.g. to converge cutoffs in DFT or benchmark many force fields - -#. :func:`asimtools.asimmodules.distributed.distributed` - Run multiple - sim_inputs in parallel - -#. :func:`asimtools.asimmodules.chained.chained` - Run asimmodules one after - the other, e.g. if step 2 results depend on step 1 etc. This allows building - multi-step workflows. - -#. :func:`asimtools.asimmodules.iterative.iterative` - Run the same asimmodule - over and over until some condition is reached. This asimmodule is still - under active development - -Examples for each type of workflow are given in the examples directory and -documentation can be found in :mod:`asimtools.asimmodules`. They also serve as -templates for you to build your own workflows directly using -:func:`asimtools.job.Job` objects as an advanced user. diff --git a/_build/_static/_sphinx_javascript_frameworks_compat.js b/_build/_static/_sphinx_javascript_frameworks_compat.js deleted file mode 100644 index 8141580..0000000 --- a/_build/_static/_sphinx_javascript_frameworks_compat.js +++ /dev/null @@ -1,123 +0,0 @@ -/* Compatability shim for jQuery and underscores.js. - * - * Copyright Sphinx contributors - * Released under the two clause BSD licence - */ - -/** - * small helper function to urldecode strings - * - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL - */ -jQuery.urldecode = function(x) { - if (!x) { - return x - } - return decodeURIComponent(x.replace(/\+/g, ' ')); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s === 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node, addItems) { - if (node.nodeType === 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && - !jQuery(node.parentNode).hasClass(className) && - !jQuery(node.parentNode).hasClass("nohighlight")) { - var span; - var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.className = className; - } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - var bbox = node.parentElement.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this, addItems); - }); - } - } - var addItems = []; - var result = this.each(function() { - highlight(this, addItems); - }); - for (var i = 0; i < addItems.length; ++i) { - jQuery(addItems[i].parent).before(addItems[i].target); - } - return result; -}; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} diff --git a/_build/_static/basic.css b/_build/_static/basic.css deleted file mode 100644 index 7577acb..0000000 --- a/_build/_static/basic.css +++ /dev/null @@ -1,903 +0,0 @@ -/* - * basic.css - * ~~~~~~~~~ - * - * Sphinx stylesheet -- basic theme. - * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -div.section::after { - display: block; - content: ''; - clear: left; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; - word-wrap: break-word; - overflow-wrap : break-word; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar #searchbox form.search { - overflow: hidden; -} - -div.sphinxsidebar #searchbox input[type="text"] { - float: left; - width: 80%; - padding: 0.25em; - box-sizing: border-box; -} - -div.sphinxsidebar #searchbox input[type="submit"] { - float: left; - width: 20%; - border-left: none; - padding: 0.25em; - box-sizing: border-box; -} - - -img { - border: 0; - max-width: 100%; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li p.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; - margin-left: auto; - margin-right: auto; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable ul { - margin-top: 0; - margin-bottom: 0; - list-style-type: none; -} - -table.indextable > tbody > tr > td > ul { - padding-left: 0em; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- domain module index --------------------------------------------------- */ - -table.modindextable td { - padding: 2px; - border-collapse: collapse; -} - -/* -- general body styles --------------------------------------------------- */ - -div.body { - min-width: 360px; - max-width: 800px; -} - -div.body p, div.body dd, div.body li, div.body blockquote { - -moz-hyphens: auto; - -ms-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, figure.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, figure.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, figure.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -img.align-default, figure.align-default, .figure.align-default { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-default { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar, -aside.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px; - background-color: #ffe; - width: 40%; - float: right; - clear: right; - overflow-x: auto; -} - -p.sidebar-title { - font-weight: bold; -} - -nav.contents, -aside.topic, -div.admonition, div.topic, blockquote { - clear: left; -} - -/* -- topics ---------------------------------------------------------------- */ - -nav.contents, -aside.topic, -div.topic { - border: 1px solid #ccc; - padding: 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- content of sidebars/topics/admonitions -------------------------------- */ - -div.sidebar > :last-child, -aside.sidebar > :last-child, -nav.contents > :last-child, -aside.topic > :last-child, -div.topic > :last-child, -div.admonition > :last-child { - margin-bottom: 0; -} - -div.sidebar::after, -aside.sidebar::after, -nav.contents::after, -aside.topic::after, -div.topic::after, -div.admonition::after, -blockquote::after { - display: block; - content: ''; - clear: both; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - margin-top: 10px; - margin-bottom: 10px; - border: 0; - border-collapse: collapse; -} - -table.align-center { - margin-left: auto; - margin-right: auto; -} - -table.align-default { - margin-left: auto; - margin-right: auto; -} - -table caption span.caption-number { - font-style: italic; -} - -table caption span.caption-text { -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -th > :first-child, -td > :first-child { - margin-top: 0px; -} - -th > :last-child, -td > :last-child { - margin-bottom: 0px; -} - -/* -- figures --------------------------------------------------------------- */ - -div.figure, figure { - margin: 0.5em; - padding: 0.5em; -} - -div.figure p.caption, figcaption { - padding: 0.3em; -} - -div.figure p.caption span.caption-number, -figcaption span.caption-number { - font-style: italic; -} - -div.figure p.caption span.caption-text, -figcaption span.caption-text { -} - -/* -- field list styles ----------------------------------------------------- */ - -table.field-list td, table.field-list th { - border: 0 !important; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -/* -- hlist styles ---------------------------------------------------------- */ - -table.hlist { - margin: 1em 0; -} - -table.hlist td { - vertical-align: top; -} - -/* -- object description styles --------------------------------------------- */ - -.sig { - font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; -} - -.sig-name, code.descname { - background-color: transparent; - font-weight: bold; -} - -.sig-name { - font-size: 1.1em; -} - -code.descname { - font-size: 1.2em; -} - -.sig-prename, code.descclassname { - background-color: transparent; -} - -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - -.sig-param.n { - font-style: italic; -} - -/* C++ specific styling */ - -.sig-inline.c-texpr, -.sig-inline.cpp-texpr { - font-family: unset; -} - -.sig.c .k, .sig.c .kt, -.sig.cpp .k, .sig.cpp .kt { - color: #0033B3; -} - -.sig.c .m, -.sig.cpp .m { - color: #1750EB; -} - -.sig.c .s, .sig.c .sc, -.sig.cpp .s, .sig.cpp .sc { - color: #067D17; -} - - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -:not(li) > ol > li:first-child > :first-child, -:not(li) > ul > li:first-child > :first-child { - margin-top: 0px; -} - -:not(li) > ol > li:last-child > :last-child, -:not(li) > ul > li:last-child > :last-child { - margin-bottom: 0px; -} - -ol.simple ol p, -ol.simple ul p, -ul.simple ol p, -ul.simple ul p { - margin-top: 0; -} - -ol.simple > li:not(:first-child) > p, -ul.simple > li:not(:first-child) > p { - margin-top: 0; -} - -ol.simple p, -ul.simple p { - margin-bottom: 0; -} - -aside.footnote > span, -div.citation > span { - float: left; -} -aside.footnote > span:last-of-type, -div.citation > span:last-of-type { - padding-right: 0.5em; -} -aside.footnote > p { - margin-left: 2em; -} -div.citation > p { - margin-left: 4em; -} -aside.footnote > p:last-of-type, -div.citation > p:last-of-type { - margin-bottom: 0em; -} -aside.footnote > p:last-of-type:after, -div.citation > p:last-of-type:after { - content: ""; - clear: both; -} - -dl.field-list { - display: grid; - grid-template-columns: fit-content(30%) auto; -} - -dl.field-list > dt { - font-weight: bold; - word-break: break-word; - padding-left: 0.5em; - padding-right: 5px; -} - -dl.field-list > dd { - padding-left: 0.5em; - margin-top: 0em; - margin-left: 0em; - margin-bottom: 0em; -} - -dl { - margin-bottom: 15px; -} - -dd > :first-child { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dl > dd:last-child, -dl > dd:last-child > :last-child { - margin-bottom: 0; -} - -dt:target, span.highlighted { - background-color: #fbe54e; -} - -rect.highlighted { - fill: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -.classifier:before { - font-style: normal; - margin: 0 0.5em; - content: ":"; - display: inline-block; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -pre, div[class*="highlight-"] { - clear: both; -} - -span.pre { - -moz-hyphens: none; - -ms-hyphens: none; - -webkit-hyphens: none; - hyphens: none; - white-space: nowrap; -} - -div[class*="highlight-"] { - margin: 1em 0; -} - -td.linenos pre { - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - display: block; -} - -table.highlighttable tbody { - display: block; -} - -table.highlighttable tr { - display: flex; -} - -table.highlighttable td { - margin: 0; - padding: 0; -} - -table.highlighttable td.linenos { - padding-right: 0.5em; -} - -table.highlighttable td.code { - flex: 1; - overflow: hidden; -} - -.highlight .hll { - display: block; -} - -div.highlight pre, -table.highlighttable pre { - margin: 0; -} - -div.code-block-caption + div { - margin-top: 0; -} - -div.code-block-caption { - margin-top: 1em; - padding: 2px 5px; - font-size: small; -} - -div.code-block-caption code { - background-color: transparent; -} - -table.highlighttable td.linenos, -span.linenos, -div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; - -webkit-user-select: text; /* Safari fallback only */ - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+ */ -} - -div.code-block-caption span.caption-number { - padding: 0.1em 0.3em; - font-style: italic; -} - -div.code-block-caption span.caption-text { -} - -div.literal-block-wrapper { - margin: 1em 0; -} - -code.xref, a code { - background-color: transparent; - font-weight: bold; -} - -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -span.eqno a.headerlink { - position: absolute; - z-index: 1; -} - -div.math:hover a.headerlink { - visibility: visible; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} \ No newline at end of file diff --git a/_build/_static/css/badge_only.css b/_build/_static/css/badge_only.css deleted file mode 100644 index c718cee..0000000 --- a/_build/_static/css/badge_only.css +++ /dev/null @@ -1 +0,0 @@ -.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} \ No newline at end of file diff --git a/_build/_static/css/fonts/Roboto-Slab-Bold.woff b/_build/_static/css/fonts/Roboto-Slab-Bold.woff deleted file mode 100644 index 6cb6000..0000000 Binary files a/_build/_static/css/fonts/Roboto-Slab-Bold.woff and /dev/null differ diff --git a/_build/_static/css/fonts/Roboto-Slab-Bold.woff2 b/_build/_static/css/fonts/Roboto-Slab-Bold.woff2 deleted file mode 100644 index 7059e23..0000000 Binary files a/_build/_static/css/fonts/Roboto-Slab-Bold.woff2 and /dev/null differ diff --git a/_build/_static/css/fonts/Roboto-Slab-Regular.woff b/_build/_static/css/fonts/Roboto-Slab-Regular.woff deleted file mode 100644 index f815f63..0000000 Binary files a/_build/_static/css/fonts/Roboto-Slab-Regular.woff and /dev/null differ diff --git a/_build/_static/css/fonts/Roboto-Slab-Regular.woff2 b/_build/_static/css/fonts/Roboto-Slab-Regular.woff2 deleted file mode 100644 index f2c76e5..0000000 Binary files a/_build/_static/css/fonts/Roboto-Slab-Regular.woff2 and /dev/null differ diff --git a/_build/_static/css/fonts/fontawesome-webfont.eot b/_build/_static/css/fonts/fontawesome-webfont.eot deleted file mode 100644 index e9f60ca..0000000 Binary files a/_build/_static/css/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/_build/_static/css/fonts/fontawesome-webfont.svg b/_build/_static/css/fonts/fontawesome-webfont.svg deleted file mode 100644 index 855c845..0000000 --- a/_build/_static/css/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,2671 +0,0 @@ - - - - -Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 - By ,,, -Copyright Dave Gandy 2016. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_build/_static/css/fonts/fontawesome-webfont.ttf b/_build/_static/css/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 35acda2..0000000 Binary files a/_build/_static/css/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/_build/_static/css/fonts/fontawesome-webfont.woff b/_build/_static/css/fonts/fontawesome-webfont.woff deleted file mode 100644 index 400014a..0000000 Binary files a/_build/_static/css/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/_build/_static/css/fonts/fontawesome-webfont.woff2 b/_build/_static/css/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 4d13fc6..0000000 Binary files a/_build/_static/css/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/_build/_static/css/fonts/lato-bold-italic.woff b/_build/_static/css/fonts/lato-bold-italic.woff deleted file mode 100644 index 88ad05b..0000000 Binary files a/_build/_static/css/fonts/lato-bold-italic.woff and /dev/null differ diff --git a/_build/_static/css/fonts/lato-bold-italic.woff2 b/_build/_static/css/fonts/lato-bold-italic.woff2 deleted file mode 100644 index c4e3d80..0000000 Binary files a/_build/_static/css/fonts/lato-bold-italic.woff2 and /dev/null differ diff --git a/_build/_static/css/fonts/lato-bold.woff b/_build/_static/css/fonts/lato-bold.woff deleted file mode 100644 index c6dff51..0000000 Binary files a/_build/_static/css/fonts/lato-bold.woff and /dev/null differ diff --git a/_build/_static/css/fonts/lato-bold.woff2 b/_build/_static/css/fonts/lato-bold.woff2 deleted file mode 100644 index bb19504..0000000 Binary files a/_build/_static/css/fonts/lato-bold.woff2 and /dev/null differ diff --git a/_build/_static/css/fonts/lato-normal-italic.woff b/_build/_static/css/fonts/lato-normal-italic.woff deleted file mode 100644 index 76114bc..0000000 Binary files a/_build/_static/css/fonts/lato-normal-italic.woff and /dev/null differ diff --git a/_build/_static/css/fonts/lato-normal-italic.woff2 b/_build/_static/css/fonts/lato-normal-italic.woff2 deleted file mode 100644 index 3404f37..0000000 Binary files a/_build/_static/css/fonts/lato-normal-italic.woff2 and /dev/null differ diff --git a/_build/_static/css/fonts/lato-normal.woff b/_build/_static/css/fonts/lato-normal.woff deleted file mode 100644 index ae1307f..0000000 Binary files a/_build/_static/css/fonts/lato-normal.woff and /dev/null differ diff --git a/_build/_static/css/fonts/lato-normal.woff2 b/_build/_static/css/fonts/lato-normal.woff2 deleted file mode 100644 index 3bf9843..0000000 Binary files a/_build/_static/css/fonts/lato-normal.woff2 and /dev/null differ diff --git a/_build/_static/css/theme.css b/_build/_static/css/theme.css deleted file mode 100644 index 19a446a..0000000 --- a/_build/_static/css/theme.css +++ /dev/null @@ -1,4 +0,0 @@ -html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/_build/_static/doctools.js b/_build/_static/doctools.js deleted file mode 100644 index d06a71d..0000000 --- a/_build/_static/doctools.js +++ /dev/null @@ -1,156 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Base JavaScript utilities for all Sphinx HTML documentation. - * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ -"use strict"; - -const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ - "TEXTAREA", - "INPUT", - "SELECT", - "BUTTON", -]); - -const _ready = (callback) => { - if (document.readyState !== "loading") { - callback(); - } else { - document.addEventListener("DOMContentLoaded", callback); - } -}; - -/** - * Small JavaScript module for the documentation. - */ -const Documentation = { - init: () => { - Documentation.initDomainIndexTable(); - Documentation.initOnKeyListeners(); - }, - - /** - * i18n support - */ - TRANSLATIONS: {}, - PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), - LOCALE: "unknown", - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext: (string) => { - const translated = Documentation.TRANSLATIONS[string]; - switch (typeof translated) { - case "undefined": - return string; // no translation - case "string": - return translated; // translation exists - default: - return translated[0]; // (singular, plural) translation tuple exists - } - }, - - ngettext: (singular, plural, n) => { - const translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated !== "undefined") - return translated[Documentation.PLURAL_EXPR(n)]; - return n === 1 ? singular : plural; - }, - - addTranslations: (catalog) => { - Object.assign(Documentation.TRANSLATIONS, catalog.messages); - Documentation.PLURAL_EXPR = new Function( - "n", - `return (${catalog.plural_expr})` - ); - Documentation.LOCALE = catalog.locale; - }, - - /** - * helper function to focus on search bar - */ - focusSearchBar: () => { - document.querySelectorAll("input[name=q]")[0]?.focus(); - }, - - /** - * Initialise the domain index toggle buttons - */ - initDomainIndexTable: () => { - const toggler = (el) => { - const idNumber = el.id.substr(7); - const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); - if (el.src.substr(-9) === "minus.png") { - el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; - toggledRows.forEach((el) => (el.style.display = "none")); - } else { - el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; - toggledRows.forEach((el) => (el.style.display = "")); - } - }; - - const togglerElements = document.querySelectorAll("img.toggler"); - togglerElements.forEach((el) => - el.addEventListener("click", (event) => toggler(event.currentTarget)) - ); - togglerElements.forEach((el) => (el.style.display = "")); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); - }, - - initOnKeyListeners: () => { - // only install a listener if it is really needed - if ( - !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && - !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS - ) - return; - - document.addEventListener("keydown", (event) => { - // bail for input elements - if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; - // bail with special keys - if (event.altKey || event.ctrlKey || event.metaKey) return; - - if (!event.shiftKey) { - switch (event.key) { - case "ArrowLeft": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const prevLink = document.querySelector('link[rel="prev"]'); - if (prevLink && prevLink.href) { - window.location.href = prevLink.href; - event.preventDefault(); - } - break; - case "ArrowRight": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const nextLink = document.querySelector('link[rel="next"]'); - if (nextLink && nextLink.href) { - window.location.href = nextLink.href; - event.preventDefault(); - } - break; - } - } - - // some keyboard layouts may need Shift to get / - switch (event.key) { - case "/": - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; - Documentation.focusSearchBar(); - event.preventDefault(); - } - }); - }, -}; - -// quick alias for translations -const _ = Documentation.gettext; - -_ready(Documentation.init); diff --git a/_build/_static/documentation_options.js b/_build/_static/documentation_options.js deleted file mode 100644 index 995f333..0000000 --- a/_build/_static/documentation_options.js +++ /dev/null @@ -1,14 +0,0 @@ -var DOCUMENTATION_OPTIONS = { - URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '1.0.0', - LANGUAGE: 'en', - COLLAPSE_INDEX: false, - BUILDER: 'html', - FILE_SUFFIX: '.html', - LINK_SUFFIX: '.html', - HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt', - NAVIGATION_WITH_KEYS: false, - SHOW_SEARCH_SUMMARY: true, - ENABLE_SEARCH_SHORTCUTS: true, -}; \ No newline at end of file diff --git a/_build/_static/file.png b/_build/_static/file.png deleted file mode 100644 index a858a41..0000000 Binary files a/_build/_static/file.png and /dev/null differ diff --git a/_build/_static/jquery.js b/_build/_static/jquery.js deleted file mode 100644 index c4c6022..0000000 --- a/_build/_static/jquery.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/_build/_static/js/html5shiv.min.js b/_build/_static/js/html5shiv.min.js deleted file mode 100644 index cd1c674..0000000 --- a/_build/_static/js/html5shiv.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/** -* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed -*/ -!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/_build/_static/js/theme.js b/_build/_static/js/theme.js deleted file mode 100644 index 1fddb6e..0000000 --- a/_build/_static/js/theme.js +++ /dev/null @@ -1 +0,0 @@ -!function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t0 - var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 - var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 - var s_v = "^(" + C + ")?" + v; // vowel in stem - - this.stemWord = function (w) { - var stem; - var suffix; - var firstch; - var origword = w; - - if (w.length < 3) - return w; - - var re; - var re2; - var re3; - var re4; - - firstch = w.substr(0,1); - if (firstch == "y") - w = firstch.toUpperCase() + w.substr(1); - - // Step 1a - re = /^(.+?)(ss|i)es$/; - re2 = /^(.+?)([^s])s$/; - - if (re.test(w)) - w = w.replace(re,"$1$2"); - else if (re2.test(w)) - w = w.replace(re2,"$1$2"); - - // Step 1b - re = /^(.+?)eed$/; - re2 = /^(.+?)(ed|ing)$/; - if (re.test(w)) { - var fp = re.exec(w); - re = new RegExp(mgr0); - if (re.test(fp[1])) { - re = /.$/; - w = w.replace(re,""); - } - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = new RegExp(s_v); - if (re2.test(stem)) { - w = stem; - re2 = /(at|bl|iz)$/; - re3 = new RegExp("([^aeiouylsz])\\1$"); - re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re2.test(w)) - w = w + "e"; - else if (re3.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - else if (re4.test(w)) - w = w + "e"; - } - } - - // Step 1c - re = /^(.+?)y$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(s_v); - if (re.test(stem)) - w = stem + "i"; - } - - // Step 2 - re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step2list[suffix]; - } - - // Step 3 - re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step3list[suffix]; - } - - // Step 4 - re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - re2 = /^(.+?)(s|t)(ion)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - if (re.test(stem)) - w = stem; - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = new RegExp(mgr1); - if (re2.test(stem)) - w = stem; - } - - // Step 5 - re = /^(.+?)e$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - re2 = new RegExp(meq1); - re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) - w = stem; - } - re = /ll$/; - re2 = new RegExp(mgr1); - if (re.test(w) && re2.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - - // and turn initial Y back to y - if (firstch == "y") - w = firstch.toLowerCase() + w.substr(1); - return w; - } -} - diff --git a/_build/_static/minus.png b/_build/_static/minus.png deleted file mode 100644 index d96755f..0000000 Binary files a/_build/_static/minus.png and /dev/null differ diff --git a/_build/_static/plus.png b/_build/_static/plus.png deleted file mode 100644 index 7107cec..0000000 Binary files a/_build/_static/plus.png and /dev/null differ diff --git a/_build/_static/pygments.css b/_build/_static/pygments.css deleted file mode 100644 index 08bec68..0000000 --- a/_build/_static/pygments.css +++ /dev/null @@ -1,74 +0,0 @@ -pre { line-height: 125%; } -td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -.highlight .hll { background-color: #ffffcc } -.highlight { background: #f8f8f8; } -.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ -.highlight .err { border: 1px solid #FF0000 } /* Error */ -.highlight .k { color: #008000; font-weight: bold } /* Keyword */ -.highlight .o { color: #666666 } /* Operator */ -.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ -.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #9C6500 } /* Comment.Preproc */ -.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ -.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ -.highlight .gd { color: #A00000 } /* Generic.Deleted */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #E40000 } /* Generic.Error */ -.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #008400 } /* Generic.Inserted */ -.highlight .go { color: #717171 } /* Generic.Output */ -.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -.highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #0044DD } /* Generic.Traceback */ -.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #008000 } /* Keyword.Pseudo */ -.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #B00040 } /* Keyword.Type */ -.highlight .m { color: #666666 } /* Literal.Number */ -.highlight .s { color: #BA2121 } /* Literal.String */ -.highlight .na { color: #687822 } /* Name.Attribute */ -.highlight .nb { color: #008000 } /* Name.Builtin */ -.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ -.highlight .no { color: #880000 } /* Name.Constant */ -.highlight .nd { color: #AA22FF } /* Name.Decorator */ -.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #0000FF } /* Name.Function */ -.highlight .nl { color: #767600 } /* Name.Label */ -.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #19177C } /* Name.Variable */ -.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -.highlight .w { color: #bbbbbb } /* Text.Whitespace */ -.highlight .mb { color: #666666 } /* Literal.Number.Bin */ -.highlight .mf { color: #666666 } /* Literal.Number.Float */ -.highlight .mh { color: #666666 } /* Literal.Number.Hex */ -.highlight .mi { color: #666666 } /* Literal.Number.Integer */ -.highlight .mo { color: #666666 } /* Literal.Number.Oct */ -.highlight .sa { color: #BA2121 } /* Literal.String.Affix */ -.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ -.highlight .sc { color: #BA2121 } /* Literal.String.Char */ -.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ -.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ -.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ -.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ -.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ -.highlight .sx { color: #008000 } /* Literal.String.Other */ -.highlight .sr { color: #A45A77 } /* Literal.String.Regex */ -.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ -.highlight .ss { color: #19177C } /* Literal.String.Symbol */ -.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ -.highlight .fm { color: #0000FF } /* Name.Function.Magic */ -.highlight .vc { color: #19177C } /* Name.Variable.Class */ -.highlight .vg { color: #19177C } /* Name.Variable.Global */ -.highlight .vi { color: #19177C } /* Name.Variable.Instance */ -.highlight .vm { color: #19177C } /* Name.Variable.Magic */ -.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_build/_static/searchtools.js b/_build/_static/searchtools.js deleted file mode 100644 index 97d56a7..0000000 --- a/_build/_static/searchtools.js +++ /dev/null @@ -1,566 +0,0 @@ -/* - * searchtools.js - * ~~~~~~~~~~~~~~~~ - * - * Sphinx JavaScript utilities for the full-text search. - * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ -"use strict"; - -/** - * Simple result scoring code. - */ -if (typeof Scorer === "undefined") { - var Scorer = { - // Implement the following function to further tweak the score for each result - // The function takes a result array [docname, title, anchor, descr, score, filename] - // and returns the new score. - /* - score: result => { - const [docname, title, anchor, descr, score, filename] = result - return score - }, - */ - - // query matches the full name of an object - objNameMatch: 11, - // or matches in the last dotted part of the object name - objPartialMatch: 6, - // Additive scores depending on the priority of the object - objPrio: { - 0: 15, // used to be importantResults - 1: 5, // used to be objectResults - 2: -5, // used to be unimportantResults - }, - // Used when the priority is not in the mapping. - objPrioDefault: 0, - - // query found in title - title: 15, - partialTitle: 7, - // query found in terms - term: 5, - partialTerm: 2, - }; -} - -const _removeChildren = (element) => { - while (element && element.lastChild) element.removeChild(element.lastChild); -}; - -/** - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping - */ -const _escapeRegExp = (string) => - string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string - -const _displayItem = (item, searchTerms) => { - const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; - const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; - const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; - const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; - const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; - - const [docName, title, anchor, descr, score, _filename] = item; - - let listItem = document.createElement("li"); - let requestUrl; - let linkUrl; - if (docBuilder === "dirhtml") { - // dirhtml builder - let dirname = docName + "/"; - if (dirname.match(/\/index\/$/)) - dirname = dirname.substring(0, dirname.length - 6); - else if (dirname === "index/") dirname = ""; - requestUrl = docUrlRoot + dirname; - linkUrl = requestUrl; - } else { - // normal html builders - requestUrl = docUrlRoot + docName + docFileSuffix; - linkUrl = docName + docLinkSuffix; - } - let linkEl = listItem.appendChild(document.createElement("a")); - linkEl.href = linkUrl + anchor; - linkEl.dataset.score = score; - linkEl.innerHTML = title; - if (descr) - listItem.appendChild(document.createElement("span")).innerHTML = - " (" + descr + ")"; - else if (showSearchSummary) - fetch(requestUrl) - .then((responseData) => responseData.text()) - .then((data) => { - if (data) - listItem.appendChild( - Search.makeSearchSummary(data, searchTerms) - ); - }); - Search.output.appendChild(listItem); -}; -const _finishSearch = (resultCount) => { - Search.stopPulse(); - Search.title.innerText = _("Search Results"); - if (!resultCount) - Search.status.innerText = Documentation.gettext( - "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." - ); - else - Search.status.innerText = _( - `Search finished, found ${resultCount} page(s) matching the search query.` - ); -}; -const _displayNextItem = ( - results, - resultCount, - searchTerms -) => { - // results left, load the summary and display it - // this is intended to be dynamic (don't sub resultsCount) - if (results.length) { - _displayItem(results.pop(), searchTerms); - setTimeout( - () => _displayNextItem(results, resultCount, searchTerms), - 5 - ); - } - // search finished, update title and status message - else _finishSearch(resultCount); -}; - -/** - * Default splitQuery function. Can be overridden in ``sphinx.search`` with a - * custom function per language. - * - * The regular expression works by splitting the string on consecutive characters - * that are not Unicode letters, numbers, underscores, or emoji characters. - * This is the same as ``\W+`` in Python, preserving the surrogate pair area. - */ -if (typeof splitQuery === "undefined") { - var splitQuery = (query) => query - .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) - .filter(term => term) // remove remaining empty strings -} - -/** - * Search Module - */ -const Search = { - _index: null, - _queued_query: null, - _pulse_status: -1, - - htmlToText: (htmlString) => { - const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); - htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); - const docContent = htmlElement.querySelector('[role="main"]'); - if (docContent !== undefined) return docContent.textContent; - console.warn( - "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." - ); - return ""; - }, - - init: () => { - const query = new URLSearchParams(window.location.search).get("q"); - document - .querySelectorAll('input[name="q"]') - .forEach((el) => (el.value = query)); - if (query) Search.performSearch(query); - }, - - loadIndex: (url) => - (document.body.appendChild(document.createElement("script")).src = url), - - setIndex: (index) => { - Search._index = index; - if (Search._queued_query !== null) { - const query = Search._queued_query; - Search._queued_query = null; - Search.query(query); - } - }, - - hasIndex: () => Search._index !== null, - - deferQuery: (query) => (Search._queued_query = query), - - stopPulse: () => (Search._pulse_status = -1), - - startPulse: () => { - if (Search._pulse_status >= 0) return; - - const pulse = () => { - Search._pulse_status = (Search._pulse_status + 1) % 4; - Search.dots.innerText = ".".repeat(Search._pulse_status); - if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); - }; - pulse(); - }, - - /** - * perform a search for something (or wait until index is loaded) - */ - performSearch: (query) => { - // create the required interface elements - const searchText = document.createElement("h2"); - searchText.textContent = _("Searching"); - const searchSummary = document.createElement("p"); - searchSummary.classList.add("search-summary"); - searchSummary.innerText = ""; - const searchList = document.createElement("ul"); - searchList.classList.add("search"); - - const out = document.getElementById("search-results"); - Search.title = out.appendChild(searchText); - Search.dots = Search.title.appendChild(document.createElement("span")); - Search.status = out.appendChild(searchSummary); - Search.output = out.appendChild(searchList); - - const searchProgress = document.getElementById("search-progress"); - // Some themes don't use the search progress node - if (searchProgress) { - searchProgress.innerText = _("Preparing search..."); - } - Search.startPulse(); - - // index already loaded, the browser was quick! - if (Search.hasIndex()) Search.query(query); - else Search.deferQuery(query); - }, - - /** - * execute search (requires search index to be loaded) - */ - query: (query) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - const allTitles = Search._index.alltitles; - const indexEntries = Search._index.indexentries; - - // stem the search terms and add them to the correct list - const stemmer = new Stemmer(); - const searchTerms = new Set(); - const excludedTerms = new Set(); - const highlightTerms = new Set(); - const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); - splitQuery(query.trim()).forEach((queryTerm) => { - const queryTermLower = queryTerm.toLowerCase(); - - // maybe skip this "word" - // stopwords array is from language_data.js - if ( - stopwords.indexOf(queryTermLower) !== -1 || - queryTerm.match(/^\d+$/) - ) - return; - - // stem the word - let word = stemmer.stemWord(queryTermLower); - // select the correct list - if (word[0] === "-") excludedTerms.add(word.substr(1)); - else { - searchTerms.add(word); - highlightTerms.add(queryTermLower); - } - }); - - if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js - localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) - } - - // console.debug("SEARCH: searching for:"); - // console.info("required: ", [...searchTerms]); - // console.info("excluded: ", [...excludedTerms]); - - // array of [docname, title, anchor, descr, score, filename] - let results = []; - _removeChildren(document.getElementById("search-progress")); - - const queryLower = query.toLowerCase(); - for (const [title, foundTitles] of Object.entries(allTitles)) { - if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { - for (const [file, id] of foundTitles) { - let score = Math.round(100 * queryLower.length / title.length) - results.push([ - docNames[file], - titles[file] !== title ? `${titles[file]} > ${title}` : title, - id !== null ? "#" + id : "", - null, - score, - filenames[file], - ]); - } - } - } - - // search for explicit entries in index directives - for (const [entry, foundEntries] of Object.entries(indexEntries)) { - if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { - for (const [file, id] of foundEntries) { - let score = Math.round(100 * queryLower.length / entry.length) - results.push([ - docNames[file], - titles[file], - id ? "#" + id : "", - null, - score, - filenames[file], - ]); - } - } - } - - // lookup as object - objectTerms.forEach((term) => - results.push(...Search.performObjectSearch(term, objectTerms)) - ); - - // lookup as search terms in fulltext - results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); - - // let the scorer override scores with a custom scoring function - if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); - - // now sort the results by score (in opposite order of appearance, since the - // display function below uses pop() to retrieve items) and then - // alphabetically - results.sort((a, b) => { - const leftScore = a[4]; - const rightScore = b[4]; - if (leftScore === rightScore) { - // same score: sort alphabetically - const leftTitle = a[1].toLowerCase(); - const rightTitle = b[1].toLowerCase(); - if (leftTitle === rightTitle) return 0; - return leftTitle > rightTitle ? -1 : 1; // inverted is intentional - } - return leftScore > rightScore ? 1 : -1; - }); - - // remove duplicate search results - // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept - let seen = new Set(); - results = results.reverse().reduce((acc, result) => { - let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); - if (!seen.has(resultStr)) { - acc.push(result); - seen.add(resultStr); - } - return acc; - }, []); - - results = results.reverse(); - - // for debugging - //Search.lastresults = results.slice(); // a copy - // console.info("search results:", Search.lastresults); - - // print the results - _displayNextItem(results, results.length, searchTerms); - }, - - /** - * search for object names - */ - performObjectSearch: (object, objectTerms) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const objects = Search._index.objects; - const objNames = Search._index.objnames; - const titles = Search._index.titles; - - const results = []; - - const objectSearchCallback = (prefix, match) => { - const name = match[4] - const fullname = (prefix ? prefix + "." : "") + name; - const fullnameLower = fullname.toLowerCase(); - if (fullnameLower.indexOf(object) < 0) return; - - let score = 0; - const parts = fullnameLower.split("."); - - // check for different match types: exact matches of full name or - // "last name" (i.e. last dotted part) - if (fullnameLower === object || parts.slice(-1)[0] === object) - score += Scorer.objNameMatch; - else if (parts.slice(-1)[0].indexOf(object) > -1) - score += Scorer.objPartialMatch; // matches in last name - - const objName = objNames[match[1]][2]; - const title = titles[match[0]]; - - // If more than one term searched for, we require other words to be - // found in the name/title/description - const otherTerms = new Set(objectTerms); - otherTerms.delete(object); - if (otherTerms.size > 0) { - const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); - if ( - [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) - ) - return; - } - - let anchor = match[3]; - if (anchor === "") anchor = fullname; - else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; - - const descr = objName + _(", in ") + title; - - // add custom score for some objects according to scorer - if (Scorer.objPrio.hasOwnProperty(match[2])) - score += Scorer.objPrio[match[2]]; - else score += Scorer.objPrioDefault; - - results.push([ - docNames[match[0]], - fullname, - "#" + anchor, - descr, - score, - filenames[match[0]], - ]); - }; - Object.keys(objects).forEach((prefix) => - objects[prefix].forEach((array) => - objectSearchCallback(prefix, array) - ) - ); - return results; - }, - - /** - * search for full-text terms in the index - */ - performTermsSearch: (searchTerms, excludedTerms) => { - // prepare search - const terms = Search._index.terms; - const titleTerms = Search._index.titleterms; - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - - const scoreMap = new Map(); - const fileMap = new Map(); - - // perform the search on the required terms - searchTerms.forEach((word) => { - const files = []; - const arr = [ - { files: terms[word], score: Scorer.term }, - { files: titleTerms[word], score: Scorer.title }, - ]; - // add support for partial matches - if (word.length > 2) { - const escapedWord = _escapeRegExp(word); - Object.keys(terms).forEach((term) => { - if (term.match(escapedWord) && !terms[word]) - arr.push({ files: terms[term], score: Scorer.partialTerm }); - }); - Object.keys(titleTerms).forEach((term) => { - if (term.match(escapedWord) && !titleTerms[word]) - arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); - }); - } - - // no match but word was a required one - if (arr.every((record) => record.files === undefined)) return; - - // found search word in contents - arr.forEach((record) => { - if (record.files === undefined) return; - - let recordFiles = record.files; - if (recordFiles.length === undefined) recordFiles = [recordFiles]; - files.push(...recordFiles); - - // set score for the word in each file - recordFiles.forEach((file) => { - if (!scoreMap.has(file)) scoreMap.set(file, {}); - scoreMap.get(file)[word] = record.score; - }); - }); - - // create the mapping - files.forEach((file) => { - if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) - fileMap.get(file).push(word); - else fileMap.set(file, [word]); - }); - }); - - // now check if the files don't contain excluded terms - const results = []; - for (const [file, wordList] of fileMap) { - // check if all requirements are matched - - // as search terms with length < 3 are discarded - const filteredTermCount = [...searchTerms].filter( - (term) => term.length > 2 - ).length; - if ( - wordList.length !== searchTerms.size && - wordList.length !== filteredTermCount - ) - continue; - - // ensure that none of the excluded terms is in the search result - if ( - [...excludedTerms].some( - (term) => - terms[term] === file || - titleTerms[term] === file || - (terms[term] || []).includes(file) || - (titleTerms[term] || []).includes(file) - ) - ) - break; - - // select one (max) score for the file. - const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); - // add result to the result list - results.push([ - docNames[file], - titles[file], - "", - null, - score, - filenames[file], - ]); - } - return results; - }, - - /** - * helper function to return a node containing the - * search summary for a given text. keywords is a list - * of stemmed words. - */ - makeSearchSummary: (htmlText, keywords) => { - const text = Search.htmlToText(htmlText); - if (text === "") return null; - - const textLower = text.toLowerCase(); - const actualStartPosition = [...keywords] - .map((k) => textLower.indexOf(k.toLowerCase())) - .filter((i) => i > -1) - .slice(-1)[0]; - const startWithContext = Math.max(actualStartPosition - 120, 0); - - const top = startWithContext === 0 ? "" : "..."; - const tail = startWithContext + 240 < text.length ? "..." : ""; - - let summary = document.createElement("p"); - summary.classList.add("context"); - summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; - - return summary; - }, -}; - -_ready(Search.init); diff --git a/_build/_static/sphinx_highlight.js b/_build/_static/sphinx_highlight.js deleted file mode 100644 index aae669d..0000000 --- a/_build/_static/sphinx_highlight.js +++ /dev/null @@ -1,144 +0,0 @@ -/* Highlighting utilities for Sphinx HTML documentation. */ -"use strict"; - -const SPHINX_HIGHLIGHT_ENABLED = true - -/** - * highlight a given string on a node by wrapping it in - * span elements with the given class name. - */ -const _highlight = (node, addItems, text, className) => { - if (node.nodeType === Node.TEXT_NODE) { - const val = node.nodeValue; - const parent = node.parentNode; - const pos = val.toLowerCase().indexOf(text); - if ( - pos >= 0 && - !parent.classList.contains(className) && - !parent.classList.contains("nohighlight") - ) { - let span; - - const closestNode = parent.closest("body, svg, foreignObject"); - const isInSVG = closestNode && closestNode.matches("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.classList.add(className); - } - - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - parent.insertBefore( - span, - parent.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling - ) - ); - node.nodeValue = val.substr(0, pos); - - if (isInSVG) { - const rect = document.createElementNS( - "http://www.w3.org/2000/svg", - "rect" - ); - const bbox = parent.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute("class", className); - addItems.push({ parent: parent, target: rect }); - } - } - } else if (node.matches && !node.matches("button, select, textarea")) { - node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); - } -}; -const _highlightText = (thisNode, text, className) => { - let addItems = []; - _highlight(thisNode, addItems, text, className); - addItems.forEach((obj) => - obj.parent.insertAdjacentElement("beforebegin", obj.target) - ); -}; - -/** - * Small JavaScript module for the documentation. - */ -const SphinxHighlight = { - - /** - * highlight the search words provided in localstorage in the text - */ - highlightSearchWords: () => { - if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight - - // get and clear terms from localstorage - const url = new URL(window.location); - const highlight = - localStorage.getItem("sphinx_highlight_terms") - || url.searchParams.get("highlight") - || ""; - localStorage.removeItem("sphinx_highlight_terms") - url.searchParams.delete("highlight"); - window.history.replaceState({}, "", url); - - // get individual terms from highlight string - const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); - if (terms.length === 0) return; // nothing to do - - // There should never be more than one element matching "div.body" - const divBody = document.querySelectorAll("div.body"); - const body = divBody.length ? divBody[0] : document.querySelector("body"); - window.setTimeout(() => { - terms.forEach((term) => _highlightText(body, term, "highlighted")); - }, 10); - - const searchBox = document.getElementById("searchbox"); - if (searchBox === null) return; - searchBox.appendChild( - document - .createRange() - .createContextualFragment( - '" - ) - ); - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords: () => { - document - .querySelectorAll("#searchbox .highlight-link") - .forEach((el) => el.remove()); - document - .querySelectorAll("span.highlighted") - .forEach((el) => el.classList.remove("highlighted")); - localStorage.removeItem("sphinx_highlight_terms") - }, - - initEscapeListener: () => { - // only install a listener if it is really needed - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; - - document.addEventListener("keydown", (event) => { - // bail for input elements - if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; - // bail with special keys - if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; - if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { - SphinxHighlight.hideSearchWords(); - event.preventDefault(); - } - }); - }, -}; - -_ready(SphinxHighlight.highlightSearchWords); -_ready(SphinxHighlight.initEscapeListener); diff --git a/_build/asimplify.html b/_build/asimplify.html deleted file mode 100644 index 195bcbb..0000000 --- a/_build/asimplify.html +++ /dev/null @@ -1,423 +0,0 @@ - - - - - - - Developing Custom Asimmodules — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Developing Custom Asimmodules

-

This section will guide you through taking your own in-house simulation and -integrating it into asimtools. The process is designed to be as -straight-forward as reasonably possible and with continued user-feedback we -hope to make it more seamless.

-

As an example, we will ASIMplify the calculation of equations of state as shown -in ASE. To understand the code, visit the ASE tutorials page. -Ultimately, the ASIMplified code will work with any chemical species, any -supported calculator and any configured computing environment with fully -parallelizable job submission on HPCs in just a few steps!

-

The code is given below:

-
from ase.build import bulk
-from ase.calculators.emt import EMT
-from ase.eos import calculate_eos
-from ase.db import connect
-
-db = connect('bulk.db')
-for symb in ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']:
-    atoms = bulk(symb, 'fcc')
-    atoms.calc = EMT()
-    eos = calculate_eos(atoms)
-    v, e, B = eos.fit()  # find minimum
-    # Do one more calculation at the minimum and write to database:
-    atoms.cell *= (v / atoms.get_volume())**(1 / 3)
-    atoms.get_potential_energy()
-    db.write(atoms, bm=B)
-
-
-

There are a couple of issues here that make it difficult to make this a -high-throughput calculation. First, because we directly setup the calculator in -the code, if we want to change the calculator we have to change the code. The -same applies for the structures and chosen chemical species. In addition, the -current code runs independent calculations one after the other. If each of -these calculations was an expensive calculation, it would be much less -efficient than running them in separate jobs on a HPC with a job scheduler. To -fix any of these issues, we would have to modify the code, job scripts and -perhaps even file structure. We will show how ASIMTools can help with all of -these issues. The end-result will be that any of these changes can made without -touching code or a job script.

-
-

1. Build and test with a cheap calculator

-

To make things easier, it is best to first replace the -expensive parts of your workflow with toy examples e.g. use an empirical -calculator like EMT instead of DFT, use a smaller/simpler structure, loop -over fewer cases etc.

-

The ASE example already uses a simple EMT calculator and simple structures.

-
-
-

2. Wrap in a function

-

The workhorse of ASIMTools is the asimmodule, any code -wrapped in a function that returns a dictionary can be run within the -ASIMTools framework. The easiest thing to do would be to take the code and -copy and paste it in a function which is defined inside an asimmodule with the -same name

-
from ase.build import bulk
-from ase.calculators.emt import EMT
-from ase.eos import calculate_eos
-from ase.db import connect
-
-def ase_eos():
-    db = connect('bulk.db')
-    for symb in ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']:
-        atoms = bulk(symb, 'fcc')
-        atoms.calc = EMT()
-        eos = calculate_eos(atoms)
-        v, e, B = eos.fit()  # find minimum
-        # Do one more calculation at the minimu and write to database:
-        atoms.cell *= (v / atoms.get_volume())**(1 / 3)
-        atoms.get_potential_energy()
-        db.write(atoms, bm=B)
-
-    return {}
-
-
-

Immediately as it is, this is an asimmodule can be run in ASIMTools. You can -run it with the following sim_input.yaml

-
asimmodule: /path/to/ase_eos.py
-env_id: inline
-workdir: results
-
-
-

then call

-
asim-execute sim_input.yaml
-
-
-

Only a little bit more complicated than calling python ase_eos.py

-
-
-

3. Make the asimmodule use any calculator

-

This asimmodule however still depends on specific structures and a specific -calculator. Let’s do the easy thing first, let’s make the asimmodule work with any -calculator using a simple change.

-
from ase.build import bulk
-from ase.eos import calculate_eos
-from ase.db import connect
-from asimtools.calculators import load_calc
-
-def ase_eos(
-    calc_id,
-):
-    calc = load_calc(calc_id)
-    db = connect('bulk.db')
-    for symb in ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']:
-        atoms = bulk(symb, 'fcc')
-        atoms.calc = calc
-        eos = calculate_eos(atoms)
-        v, e, B = eos.fit()  # find minimum
-        # Do one more calculation at the minimu and write to database:
-        atoms.cell *= (v / atoms.get_volume())**(1 / 3)
-        atoms.get_potential_energy()
-        db.write(atoms, bm=B)
-
-    return {}
-
-
-

Just like that we can now run the asimmodule with any correctly configured -calculator for all the structures! We can even now run calc_array to -iterate getting the results using different calculators.

-
-
-

4. Make the asimmodule use any structure

-

The final change we will make is to parallelize over structures as below

-
from ase.build import bulk
-from ase.eos import calculate_eos
-from ase.db import connect
-from asimtools.calculators import load_calc
-
-def ase_eos(
-    image,
-    calc_id,
-):
-    calc = load_calc(calc_id)
-    db = connect('bulk.db')
-    atoms = get_atoms(**image)
-    atoms.calc = calc
-    eos = calculate_eos(atoms)
-    v, e, B = eos.fit()  # find minimum
-    # Do one more calculation at the minimu and write to database:
-    atoms.cell *= (v / atoms.get_volume())**(1 / 3)
-    atoms.get_potential_energy()
-    db.write(atoms, bm=B)
-
-    return {}
-
-
-

Easy-peasy. We now have an asimmodule that works with arbitrary environment, -arbitrary calculator and arbitrary input structure (Of course the simulation -will fail if we give a bad structure/calculator for example)

-
-
-

5. Final cleanup

-

We can do some final cleanup of the asimmodule so that it sends outputs to -output.yaml and logs some checkpoints. Additionally, any asimmodules added -to the repository will need clear syntax highlighting and documentation.

-
from typing import Dict
-import logging
-from ase.eos import calculate_eos
-from ase.db import connect
-from asimtools.calculators import load_calc
-from asimtools.utils import get_atoms
-
-def ase_eos(
-    image: Dict,
-    calc_id: str,
-    db_file: 'bulk.db'
-) -> Dict:
-    calc = load_calc(calc_id)
-    db = connect(db_file)
-    atoms = get_atoms(**image)
-    atoms.calc = calc
-    eos = calculate_eos(atoms)
-    v, e, B = eos.fit()  # find minimum
-    logging.info('Successfully fit EOS')
-    # Do one more calculation at the minimu and write to database:
-    atoms.cell *= (v / atoms.get_volume())**(1 / 3)
-    atoms.get_potential_energy()
-    db.write(atoms, bm=B)
-
-    results = {'v': float(v), 'e': float(e), 'B': float(B)}
-    return results
-
-
-

To run this asimmodule on an arbitrary structure say Argon with say the -LennardJones calculator, in a slurm job we can now use the following input -files.

-

sim_input.yaml:

-
asimmodule: /path/to/ase_eos.py
-env_id: batch
-workdir: results
-args:
-    image:
-        builder: bulk
-        name: Ar
-    calc_id: lj_Ar
-
-
-

calc_input.yaml:

-
lj_Ar:
-    name: LennardJones
-    module: ase.calculators.lj
-    args:
-        sigma: 3.54
-        epsilon: 0.00802236
-emt: #This is not used if an LJ calculator is chosen
-    name: EMT
-    module: ase.calculators.emt
-    args: {}
-
-
-

env_input.yaml:

-
batch:
-    mode:
-        use_slurm: true
-        interactive: false
-    slurm:
-        flags:
-            - -n 2
-        precommands:
-            - source ~/.bashrc
-            - conda activate asimtools
-inline: # This is not used if env_id is batch
-    mode:
-        use_slurm: false
-        interactive: true
-
-
-
-
-

6. Running multiple simulations in a workflow

-

Going back to the original problem, we wanted to run the simulation of multiple -different elements with the EMT calculator. To achieve that in parallel, we can -nest the ase_eos asimmodule in a -asimtools.asimmodules.workflows.sim_array.sim_array() asimmodule as follows

-

sim_input.yaml:

-
asimmodule: workflows.sim_array
-workdir: results
-args:
-    key_sequence: ['args', 'image', 'name']
-    array_values: ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']
-    env_ids: 'batch'
-    template_sim_input:
-        asimmodule: /path/to/ase_eos.py
-        args:
-            calc_id: emt
-            image:
-                builder: bulk
-                crystalstructure: 'fcc'
-
-
-

To make the asimmodule easier to access without having to use the full path, you -can set the environment variable

-
export ASIMTOOLS_ASIMMODULE_DIR=/path/to/my/asimmodule/dir/
-
-
-

You can then move the ase_eos.py asimmodule to -/path/to/my/asimmodule/dir/ i.e. the asimmodule directory. This allows you -to refer to asimmodules prepended with the asimmodule dir as below

-
asimmodule: workflows.sim_array
-workdir: results
-args:
-    key_sequence: ['args', 'image', 'name']
-    array_values: ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']
-    env_ids: 'batch'
-    template_sim_input:
-        asimmodule: ase_eos/ase_eos.py
-        args:
-            calc_id: emt
-            image:
-                builder: bulk
-                crystalstructure: 'fcc'
-
-
-

The above example loops over crystals for which ASE already has FCC lattice -parameters, but what if we want to loop over the species and corresponding -lattice parameters? We can either specify a list of images dictionaries as -array_values or use secondary_array_values. We can also explicitly tell -ASIMTools to include the array_values in the directory names in the standard -format (e.g. id-0000__Al__, id-0001__Ni__ etc.).

-
asimmodule: workflows.sim_array
-workdir: results
-args:
-    key_sequence: ['args', 'image', 'name']
-    array_values: ['Al', 'Ni', 'Cu', 'Pd', 'Ag', 'Pt', 'Au']
-    labels: values
-    secondary_key_sequences:
-    - ['args', 'image', 'a']
-    secondary_array_values:
-    - [4.0479, 3.524, 3.6149, 3.8907, 4.0853, 3.9242, 4.0782]
-    env_ids: 'batch'
-    template_sim_input:
-        asimmodule: ase_eos/ase_eos.py
-        args:
-            calc_id: emt
-            image:
-                builder: bulk
-                crystalstructure: 'fcc'
-
-
-

This will perform the EOS calculation for each species with the corresponding -lattice parameter. That’s 7x5=35 calculations in parallel without touching code -or a job script!

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.benchmarking.html b/_build/asimtools.asimmodules.benchmarking.html deleted file mode 100644 index 1c85269..0000000 --- a/_build/asimtools.asimmodules.benchmarking.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - - asimtools.asimmodules.benchmarking package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.benchmarking package

-
-

asimtools.asimmodules.benchmarking.parity module

-

Generates a parity plot and collects evaluation statistics comparing energy -and/or forces and/or stress to existing values in the provided dataset. This -asimmodule can work in parallel based on the number of cores specified.

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.benchmarking.parity.calc_parity_data(subset: List, calc_id: str, properties: Sequence = ('energy', 'forces', 'stress'), force_prob: float = 1.0) Dict[source]
-

Calculates parity data for each atoms instance in subset

-
-
Parameters:
-
    -
  • subset (List) – List of atoms instances

  • -
  • calc_id (str) – calc_id specification

  • -
  • properties (List, optional) – Properties to evaluate, choose from “energy”, “forces” and “stress”, defaults to (‘energy’, ‘forces’, ‘stress’)

  • -
  • force_prob (float, optional) – Fraction of forces to consider, may speed up sampling large structures by subsampling forces randomly, defaults to 1.0

  • -
-
-
Returns:
-

Dictionary with reference and predicted values for each property

-
-
Return type:
-

Dict

-
-
-
- -
-
-asimtools.asimmodules.benchmarking.parity.parity(images: Dict, calc_id: str, force_prob: float = 1.0, nprocs: int = 1, unit: str = 'meV', index: str = ':', properties: Sequence = ('energy', 'forces', 'stress')) Dict[source]
-

Generates a parity plot and collects evaluation statistics comparing energy -and/or forces and/or stress to existing values in the provided dataset

-
-
Parameters:
-
    -
  • images (Dict) – Image specification, see asimtools.utils.get_images()

  • -
  • calc_id (str) – ID of calculator provided in calc_input or global file

  • -
  • force_prob (float, optional) – Fraction of forces to consider in force parity, can be used for speeding up large structures by only subsampling randomly, defaults to 1.0

  • -
  • nprocs (int, optional) – Number of process to parallelize over, must be less than number of datapoints, defaults to 1

  • -
  • unit (str, optional) – Unit to plot, choose from meV, eV or kcal/mol, defaults to ‘meV’

  • -
  • index (int, optional) – index of data to use from full dataset, defaults to ‘:’

  • -
  • properties (Sequence, optional) – Properties to evaluate, choose from “energy”, “forces” and “stress”, defaults to (‘energy’, ‘forces’, ‘stress’)

  • -
-
-
Returns:
-

Dictionary of results

-
-
Return type:
-

Dict

-
-
-
- -
-
-asimtools.asimmodules.benchmarking.parity.rmse(yhat: Sequence, y: Sequence) float[source]
-

Calculate Root Mean Square Error between to sequences

-
-
Parameters:
-
    -
  • yhat (Sequence) – Predicted values

  • -
  • y (Sequence) – True values

  • -
-
-
Returns:
-

RMSE

-
-
Return type:
-

float

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.elastic_constants.html b/_build/asimtools.asimmodules.elastic_constants.html deleted file mode 100644 index b788f85..0000000 --- a/_build/asimtools.asimmodules.elastic_constants.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - asimtools.asimmodules.elastic_constants package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.elastic_constants package

-
-

asimtools.asimmodules.elastic_constants.cubic_energy_expansion module

-

Describe the asimmodule briefly here. If this is a asimmodule that runs multiple steps, -describe it here using reStructuredText to generate autodocs

-

Cite the papers where the method/asimmodule was first introduced here as well

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.elastic_constants.cubic_energy_expansion.cubic_energy_expansion(calc_id: str, image: Dict, deltas: Sequence[float] = (-0.01, -0.0075, -0.005, 0.0, 0.005, 0.0075, 0.01), ase_cubic_eos_args: Dict | None = None) Dict[source]
-

Calculates B (Bulk modulus), C11, C12 and C44 elastic constants of -a structure with cubic symmetry

-
-
Parameters:
-
-
-
Returns:
-

Elastic constant results

-
-
Return type:
-

Dict

-
-
-
- -
-
-asimtools.asimmodules.elastic_constants.cubic_energy_expansion.get_strained_atoms(atoms, strain: str, delta: float)[source]
-

Returns a unit cell with atoms strained according to some useful types

-
-
Parameters:
-
    -
  • atoms (ase.Atoms) – input atoms

  • -
  • strain (str) – Type of strain

  • -
  • delta (float) – value of strain

  • -
-
-
Returns:
-

atoms with strained cell

-
-
Return type:
-

ase.Atoms

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.eos.html b/_build/asimtools.asimmodules.eos.html deleted file mode 100644 index 3d65b8a..0000000 --- a/_build/asimtools.asimmodules.eos.html +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - asimtools.asimmodules.eos package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.eos package

-
-

asimtools.asimmodules.eos.postprocess module

-

.Xauthority

-
-
-asimtools.asimmodules.eos.postprocess.postprocess(images: Dict, initial_image: Dict) Tuple[None, Dict][source]
-

Plot an eos given a number of images and the initial image

-
-
Parameters:
-
-
-
Returns:
-

Empty dict

-
-
Return type:
-

Tuple[None,Dict]

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.geometry_optimization.html b/_build/asimtools.asimmodules.geometry_optimization.html deleted file mode 100644 index a2a3ce5..0000000 --- a/_build/asimtools.asimmodules.geometry_optimization.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - asimtools.asimmodules.geometry_optimization package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.geometry_optimization package

-
-

asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization module

-

Calculate the equation of state, fit it and extract the equilibrium -volume, energy and bulk modulus. This script is based on the example provided -on the ASE website: https://wiki.fysik.dtu.dk/ase/tutorials/db/db.html

-

author: mkphuthi@github.com

-
-
-asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization.ase_cubic_eos_optimization(calc_id: str, image: Dict, npoints: int | None = 5, eos_string: str | None = 'sj', eps: float | None = 0.04, scales: Sequence | None = None, plot: bool | None = True) Dict[source]
-

Generate the energy-volume equation of state (energy calculations not parallelized)

-
-
Parameters:
-
    -
  • calc_id (str) – calc_id specification

  • -
  • image (Dict) – Image specification, see asimtools.utils.get_atoms()

  • -
  • npoints (Optional[int], optional) – Number of energy points to calculate, must be >5, defaults to 5

  • -
  • eos_string (Optional[str], optional) – eos_string as specified for ase.eos.calculate_eos(), defaults to ‘sj’

  • -
  • eps (Optional[float], optional) – eps as sepecified for ase, defaults to 0.04

  • -
  • scales – array of values to scale the unit cell by (not volume)

  • -
  • plot (Optional[bool], optional) – Whether to plot eos or not, defaults to True

  • -
-
-
Returns:
-

Equilibrium energy, volume, bulk modulus and factor by which to scale lattice parameter to get equilibrium structure

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.geometry_optimization.atom_relax module

-

Relaxes the given atomic structure using ASE’s built-in structure -optimizers

-
-
-asimtools.asimmodules.geometry_optimization.atom_relax.atom_relax(calc_id: str, image: Dict, optimizer: str = 'GPMin', properties: Tuple[str] = ('energy', 'forces'), fmax: float = 0.02, prefix: str | None = None) Dict[source]
-

Relaxes the given tomic structure using ASE’s built-in structure -optimizers

-
-
Parameters:
-
    -
  • calc_id (str) – calc_id specification

  • -
  • image (Dict) – Image specification, see asimtools.utils.get_atoms()

  • -
  • prefix (str, optional) – Prefix of output files, defaults to ‘’

  • -
  • optimizer (str, optional) – ASE Optimizer class, defaults to ‘GPMin’

  • -
  • fmax (float, optional) – Force convergence threshold in optimizer, defaults to 0.02

  • -
-
-
Returns:
-

Dictionary of results

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.geometry_optimization.cell_relax module

-

Relaxes structure using ASE

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.geometry_optimization.cell_relax.cell_relax(calc_id: str, image: Dict, optimizer: str = 'BFGS', fmax: float = 0.002, mask: Sequence | None = None, prefix: str | None = None) Dict[source]
-

Relax cell using ASE Optimizer

-
-
Parameters:
-
    -
  • calc_id (str) – calc_id specification

  • -
  • image (Dict) – Image specification, see asimtools.utils.get_atoms()

  • -
  • prefix (str, optional) – Prefix to output files, defaults to ‘’

  • -
  • optimizer (str, optional) – Optimizer class to use from ase.optimize, defaults to ‘BFGS’

  • -
  • fmax (float, optional) – Maximum stress in eV/$AA^3$, defaults to 0.002

  • -
  • mask (Optional[Sequence], optional) – Mask to constrain cell deformation while relaxing, defaults to None

  • -
-
-
Returns:
-

Dictionary of results including, final energy, stress and output files

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.geometry_optimization.optimize module

-

Relaxes both atoms and cell coordinates simultaneously.

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.geometry_optimization.optimize.optimize(calc_id: str, image: Dict, optimizer: str = 'BFGS', fmax: float = 0.003, optimizer_args: Dict | None = None, expcellfilter_args: Dict | None = None) Dict[source]
-

Relaxes cell (and atoms) using ase.constraints.ExpCellFilter while retaining symmetry

-
-
Parameters:
-
    -
  • calc_id (str) – calc_id specification

  • -
  • image (Dict) – Image specification, see asimtools.utils.get_atoms()

  • -
  • optimizer (str, optional) – Any optimizer from ase.optimize, defaults to ‘BFGS’

  • -
  • fmax (float, optional) – fmax in optimizer, defaults to 0.003 which is ~0.48GPa

  • -
  • expcellfilter_args (Optional[Dict], optional) – arguments for ase.constraints.ExpCellFilter, defaults to None

  • -
-
-
Returns:
-

Results including relaxed structure energy

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.geometry_optimization.symmetric_cell_relax module

-

Relaxes structure using ASE while retaining symmetry. Requires ASE>=3.23

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.geometry_optimization.symmetric_cell_relax.symmetric_cell_relax(calc_id: str, image: Dict, optimizer: str = 'BFGS', fmax: float = 0.003, optimizer_args: Dict | None = None, fixsymmetry_args: Dict | None = None, expcellfilter_args: Dict | None = None) Dict[source]
-

Relaxes cell (and atoms) using ase.constraints.ExpCellFilter while retaining symmetry

-
-
Parameters:
-
    -
  • calc_id (str) – calc_id specification

  • -
  • image (Dict) – Image specification, see asimtools.utils.get_atoms()

  • -
  • optimizer (str, optional) – Any optimizer from ase.optimize, defaults to ‘BFGS’

  • -
  • fmax (float, optional) – fmax in optimizer, defaults to 0.003 which is ~0.48GPa

  • -
  • fixsymmetry_args (Optional[Dict], optional) – arguments for ase.constraints.FixSymmetry, defaults to None

  • -
  • expcellfilter_args (Optional[Dict], optional) – arguments for ase.constraints.ExpCellFilter, defaults to None

  • -
-
-
Returns:
-

Results including relaxed structure energy

-
-
Return type:
-

Dict

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.html b/_build/asimtools.asimmodules.html deleted file mode 100644 index 978ba31..0000000 --- a/_build/asimtools.asimmodules.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - asimtools.asimmodules package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules package

-
- -
-
-

asimtools.asimmodules.do_nothing module

-

asimmodule for unit tests and debugging, does nothing for specified duration

-
-
-asimtools.asimmodules.do_nothing.do_nothing(duration: int | None = 5) Dict[source]
-

Sleep for the specified duration

-
-
Parameters:
-

duration (int, optional) – time in seconds, defaults to 60

-
-
Returns:
-

Dictionary with duration slept for

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.singlepoint module

-

Calculates single point energy

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.singlepoint.singlepoint(calc_id: str, image: Dict, properties: Tuple[str] = ('energy', 'forces'), prefix: str | None = None) Dict[source]
-

Evaluates the properties of a single image, currently implemented -properties are energy, forces and stress

-
-
Parameters:
-
    -
  • calc_id (str) – calc_id specification

  • -
  • image (Dict) – Image specification, see asimtools.utils.get_atoms()

  • -
  • properties (Tuple[str], optional) – properties to evaluate, defaults to (‘energy’, ‘forces’)

  • -
-
-
Returns:
-

Dictionary of results

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.template module

-

Describe the asimmodule briefly here. If this is a asimmodule that runs multiple steps, -describe it here using reStructuredText to generate autodocs

-

Cite the papers where the method/asimmodule was first introduced here as well

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.template.template() Dict[source]
-

asimmodule does xyz

-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.lammps.html b/_build/asimtools.asimmodules.lammps.html deleted file mode 100644 index 9d543a6..0000000 --- a/_build/asimtools.asimmodules.lammps.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - asimtools.asimmodules.lammps package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.lammps package

-
-

asimtools.asimmodules.lammps.lammps module

-

Runs a user defined lammps script or template

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.lammps.lammps.lammps(template: str, image: Dict | None = None, atom_style: str = 'atomic', variables: Dict | None = None, lmp_cmd: str = 'lmp', masses: bool = True) Dict[source]
-

Runs a lammps script based on a specified template, variables can be -specified as arguments to be defined in the final LAMMPS input file if -placeholders are put in the template

-
-
Parameters:
-
    -
  • template (str) – path to lammps input template file

  • -
  • image (Dict, optional) – Initial image for MD simulation. Image specification, see asimtools.utils.get_atoms(), defaults to None

  • -
  • atom_style (str, optional) – LAMMPS style in which to write image to Lammps data input e.g. full, atomic etc., defaults to ‘atomic’

  • -
  • variables (Dict, optional) – Dictionary of variables to be defined into the lammps input, defaults to None

  • -
  • lmp_cmd (str, optional) – Command with which to run LAMMPS, defaults to ‘lmp’

  • -
  • masses (bool, optional) – Whether to specify atomic masses in LAMMPS data input, requires ASE>3.23.0, defaults to True

  • -
-
-
Returns:
-

LAMMPS out file names

-
-
Return type:
-

Dict

-
-
-

Runs a lammps simulation based on a template lammps input script

-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.phonons.html b/_build/asimtools.asimmodules.phonons.html deleted file mode 100644 index df55117..0000000 --- a/_build/asimtools.asimmodules.phonons.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - asimtools.asimmodules.phonons package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.phonons package

-
-

asimtools.asimmodules.phonons.ase_phonons module

-

Relaxes the given atomic structure using ASE’s built-in structure -optimizers

-
-
-asimtools.asimmodules.phonons.ase_phonons.ase_phonons(calc_id: str, image: Dict, path: str, delta: float = 0.01, kpts: Sequence[int] = (20, 20, 20), supercell: Sequence[int] = (5, 5, 5)) Dict[source]
-

Calculates phonon spectrum and DOS using ASE

-
-
Parameters:
-
    -
  • calc_id (str) – calc_id specification

  • -
  • image (Dict) – Image specification, see asimtools.utils.get_atoms()

  • -
  • path (str) – Path in BZ for plot

  • -
  • delta (float, optional) – delta in ASE phonons, defaults to 0.01

  • -
  • kpts (Sequence[int], optional) – kpts in ASE phonons, defaults to (20, 20, 20)

  • -
  • supercell (Sequence[int], optional) – repeat of image to use as supercell, defaults to (5,5,5)

  • -
-
-
Returns:
-

Empty dictionary

-
-
Return type:
-

Dict

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.surface_energies.html b/_build/asimtools.asimmodules.surface_energies.html deleted file mode 100644 index 86e705d..0000000 --- a/_build/asimtools.asimmodules.surface_energies.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - - - asimtools.asimmodules.surface_energies package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.surface_energies package

-
-

asimtools.asimmodules.surface_energies.surface_energies module

-

Calculates surface energies of slabs defined by args specified for -pymatgen.core.surface.generate_all_slabs()

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.surface_energies.surface_energies.get_surface_energy(slab, calc, bulk_e_per_atom)[source]
-
- -
-
-asimtools.asimmodules.surface_energies.surface_energies.surface_energies(calc_id: str, image: Dict, millers: str | Sequence = 'all', atom_relax_args: Dict | None = None, generate_all_slabs_args: Dict | None = None) Dict[source]
-

Calculates surface energies of slabs defined by args specified for -pymatgen.core.surface.generate_all_slabs()

-
-
Parameters:
-
-
-
Returns:
-

_description_

-
-
Return type:
-

Dict

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.transformations.html b/_build/asimtools.asimmodules.transformations.html deleted file mode 100644 index 080add3..0000000 --- a/_build/asimtools.asimmodules.transformations.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - asimtools.asimmodules.transformations package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.transformations package

-
-

asimtools.asimmodules.transformations.scale_unit_cells module

-

Produce a set of images with unit cells scaled compared to the input

-

author: mkphuthi@github.com

-
-
-asimtools.asimmodules.transformations.scale_unit_cells.apply_scale(old_atoms, scale)[source]
-

Applies a scaling factor to a unit cell

-
- -
-
-asimtools.asimmodules.transformations.scale_unit_cells.scale_unit_cells(image: Dict, scales: Sequence | None = None, logspace: Sequence | None = None, linspace: Sequence | None = None, scale_by: str = 'a') Dict[source]
-

Produce a set of images with unit cells scaled compared to the input

-
-
Parameters:
-
    -
  • image (Dict) – Image specification, see asimtools.utils.get_atoms()

  • -
  • scales (Optional[Sequence], optional) – Scaling values by which to scale cell, defaults to None

  • -
  • logspace (Optional[Sequence], optional) – Parameters to pass to np.logspace for scaling values, -defaults to None

  • -
  • linspace (Optional[Sequence], optional) – Parameters to pass to np.linspace for scaling values, -defaults to None

  • -
  • scale_by (str, optional) – Scale either “volume” or “a” which is lattice parameter, -defaults to ‘a’

  • -
-
-
Raises:
-

ValueError – If more than one of scales, linspace, logspace are -provided

-
-
Returns:
-

Path to xyz file

-
-
Return type:
-

Dict

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.vacancy_formation_energy.html b/_build/asimtools.asimmodules.vacancy_formation_energy.html deleted file mode 100644 index 3a2236e..0000000 --- a/_build/asimtools.asimmodules.vacancy_formation_energy.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - asimtools.asimmodules.vacancy_formation_energy package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.vacancy_formation_energy package

-
-

asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy module

-

Calculates the monovacancy formation energy from a bulk structure

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy.vacancy_formation_energy(calc_id: str, image: Dict, vacancy_index: int = 0, atom_relax_args: Dict | None = None, optimize_args: Dict | None = None, repeat: Sequence | None = (1, 1, 1)) Dict[source]
-

Calculates the monovacancy formation energy from a bulk structure

-
-
Parameters:
-
-
-
Returns:
-

Empty dictionary

-
-
Return type:
-

Dict

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.asimmodules.workflows.html b/_build/asimtools.asimmodules.workflows.html deleted file mode 100644 index 1603d91..0000000 --- a/_build/asimtools.asimmodules.workflows.html +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - - asimtools.asimmodules.workflows package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools.asimmodules.workflows package

-
-

asimtools.asimmodules.workflows.calc_array module

-

Apply the same asimmodule using multiple calculators

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.workflows.calc_array.calc_array(subsim_input: Dict, calc_ids: Sequence[str] | None = None, template_calc_id: str | None = None, key_sequence: Sequence[str] | None = None, array_values: Sequence | None = None, file_pattern: str | None = None, linspace_args: Sequence | None = None, arange_args: Sequence | None = None, label_prefix: str | None = None, env_ids: Sequence[str] | str | None = None, calc_input: Dict | None = None, env_input: Dict | None = None, labels: Sequence | str | None = 'values', str_btn_args: Dict | None = None, secondary_key_sequences: Sequence | None = None, secondary_array_values: Sequence | None = None, array_max: int | None = None) Dict[source]
-

Apply the same asimmodule using different calculators and if necessary -different environments

-
-
Parameters:
-
    -
  • calc_ids (Sequence, optional) – Iterable with calc_ids, defaults to None

  • -
  • calc_input (Dictionary, optional) – Dictionary of calculator inputs

  • -
  • labels (Sequence, optional -:param array_values: values to be iterated over in each simulation, -defaults to None) – Iterable with custom labels for each calc, defaults to None

  • -
  • file_pattern (Optional[str], optional) – pattern of files to be iterated over in each -simulation, defaults to None

  • -
  • linspace_args (Optional[Sequence], optional) – arguments to pass to numpy.linspace() to be -iterated over in each simulation, defaults to None

  • -
  • arange_args (Optional[Sequence], optional) – arguments to pass to numpy.arange() to be -iterated over in each simulation, defaults to None

  • -
  • label_prefix (str, optional) – Prefix to add before labels which can make extracting -data from file paths easier, defaults to None

  • -
  • env_ids (Optional[Union[Sequence[str],str]], optional) – Environment(s) to be used for each simulation, must either -be a list with as many env_ids as array values or a string with the -env_id to be used by all simulations, defaults to None

  • -
  • secondary_key_sequences (Sequence, optional) – list of other keys to iterate over in -tandem with key_sequence to allow changing multiple key-value pairs, -defaults to None

  • -
  • secondary_array_values (Sequence, optional) – list of other other array_values to iterate -over in tandem with array_values to allow changing multiple key-value -pairs, defaults to None

  • -
-
-
Returns:
-

Dictionary of results

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.workflows.chained module

-

Submits a chain of asimmodules in the order specified by steps -in input

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.workflows.chained.chained(steps: Dict, env_input: Dict | None = None, calc_input: Dict | None = None) Dict[source]
-

Run a workflow using the provided sim_input.yaml one after the other, -The jobs will run one after the other, if slurm is used, job dependencies -will be used. Note that if one of the subsim_inputs internally launches another -asimmodule e.g. image_array, calc_array etc, slurm job dependencies will not -work as expected. In those cases, we recommend running the steps one by one -or interactively

-
-
Parameters:
-
    -
  • steps (Dict) – Dictionary where each key is an ID and the value is a standard sim_input

  • -
  • env_input (Optional[Dict], optional) – env_input that overrides global file, defaults to None

  • -
  • calc_input (Optional[Dict], optional) – calc_input that overrides global file, defaults to None

  • -
-
-
Returns:
-

Dictionary of results

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.workflows.distributed module

-

Distributes a number of simulations at the same time if possible

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.workflows.distributed.distributed(subsim_inputs: Dict, env_input: Dict | None = None, calc_input: Dict | None = None, array_max: int | None = None) Dict[source]
-

Distributes a set of jobs based on inpout parameter. The scnarios are -as follows: -#. use_slurm: False, interactive: True -> Runs one after the other. -#. use_slurm: True, interactive: False, same env_id -> Launches a job # array. -#. use_slurm: False, interactive: False, different env_ids -> Launches # multiple jobs.

-
-
Parameters:
-
    -
  • subsim_inputs (Dict) – Dictionary of asimmodules, each key is an ID and each value is a sim_input file

  • -
  • env_input (Optional[Dict], optional) – env_input that overrides global file, defaults to None

  • -
  • calc_input (Optional[Dict], optional) – calc_input that overrides global file, defaults to None

  • -
  • array_max (Optional[int], optional) – Maximum number of jobs to run in array, defaults to None

  • -
-
-
Returns:
-

Dictionary of results

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.workflows.image_array module

-

Apply the same asimmodule on multiple images

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.workflows.image_array.image_array(images: Dict, subsim_input: Dict, calc_input: Dict | None = None, env_input: Dict | None = None, array_max: int | None = None, key_sequence: Sequence[str] | None = None, env_ids: Sequence[str] | str | None = None, labels: Sequence | str | None = None, label_prefix: str | None = None, str_btn_args: Dict | None = None, secondary_key_sequences: Sequence | None = None, secondary_array_values: Sequence | None = None) Dict[source]
-

Submit the same asimmodule on multiple images and if specified, use -different env_ids

-
-
Parameters:
-
    -
  • images (Dict) – Images specification, see asimtools.utils.get_images()

  • -
  • subsim_input (Dict) – sim_input of asimmodule to be run

  • -
  • calc_input (Optional[Dict], optional) – calc_input to override global file, defaults to None

  • -
  • env_input (Optional[Dict], optional) – env_input to override global file, defaults to None

  • -
  • array_max (Optional[int], optional) – Maximum jobs to run simultanteously in job array, defaults to None

  • -
  • labels (Sequence[str], optional) – Custom labels for each image, defaults to None

  • -
  • env_ids (Sequence[str], optional) – Sequence of envs for each image, must be the same length as the total number of images, defaults to None

  • -
  • labels – Custom labels to use for each simulation, defaults to None

  • -
  • label_prefix (str, optional) – Prefix to add before labels which can make extracting -data from file paths easier, defaults to None

  • -
  • secondary_key_sequences (Sequence, optional) – list of other keys to iterate over in -tandem with key_sequence to allow changing multiple key-value pairs, -defaults to None

  • -
  • secondary_array_values (Sequence, optional) – list of other other array_values to iterate -over in tandem with images to allow changing multiple key-value -pairs, defaults to None

  • -
-
-
Returns:
-

Dictionary of results

-
-
Return type:
-

Dict

-
-
-
- -
-
-

asimtools.asimmodules.workflows.sim_array module

-

Runs the same asimmodule, iterating over multiple values of a specified -argument based on a sim_input template provided by the user. The tasks are run -simultaneously if resources are available

-

Author: mkphuthi@github.com

-
-
-asimtools.asimmodules.workflows.sim_array.sim_array(template_sim_input: Dict, key_sequence: Sequence[str] | None = None, array_values: Sequence | None = None, file_pattern: str | None = None, linspace_args: Sequence | None = None, arange_args: Sequence | None = None, env_ids: Sequence[str] | str | None = None, calc_input: Dict | None = None, env_input: Dict | None = None, labels: Sequence | str | None = 'values', label_prefix: str | None = None, str_btn_args: Dict | None = None, secondary_key_sequences: Sequence | None = None, secondary_array_values: Sequence | None = None, array_max: int | None = None) Dict[source]
-

Runs the same asimmodule, iterating over multiple values of a specified -argument based on a sim_input template provided by the user

-
-
Parameters:
-
    -
  • template_sim_input (Dict) – sim_input containing all the default parameters

  • -
  • key_sequence (Optional[Sequence[str]], optional) – Sequence of keys to access value to be iterated over, -defaults to None

  • -
  • array_values (Optional[Sequence], optional) – values to be iterated over in each simulation, -defaults to None

  • -
  • file_pattern (Optional[str], optional) – pattern of files to be iterated over in each -simulation, defaults to None

  • -
  • linspace_args (Optional[Sequence], optional) – arguments to pass to numpy.linspace() to be -iterated over in each simulation, defaults to None

  • -
  • arange_args (Optional[Sequence], optional) – arguments to pass to numpy.arange() to be -iterated over in each simulation, defaults to None

  • -
  • labels (Sequence, optional) – Custom labels to use for each simulation, defaults to None

  • -
  • label_prefix (str, optional) – Prefix to add before labels which can make extracting -data from file paths easier, defaults to None

  • -
  • env_ids (Optional[Union[Sequence[str],str]], optional) – Environment(s) to be used for each simulation, must either -be a list with as many env_ids as array values or a string with the -env_id to be used by all simulations, defaults to None

  • -
  • secondary_key_sequences (Sequence, optional) – list of other keys to iterate over in -tandem with key_sequence to allow changing multiple key-value pairs, -defaults to None

  • -
  • secondary_array_values (Sequence, optional) – list of other other array_values to iterate -over in tandem with array_values to allow changing multiple key-value -pairs, defaults to None

  • -
  • array_max (int, optional) – Number of jobs to run at once in scheduler

  • -
  • calc_input (Optional[Dict], optional) – calc_input file to use, defaults to None

  • -
  • env_input (Optional[Dict], optional) – env_input to use, defaults to None

  • -
-
-
Returns:
-

Results

-
-
Return type:
-

Dict

-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/asimtools.html b/_build/asimtools.html deleted file mode 100644 index 274e32e..0000000 --- a/_build/asimtools.html +++ /dev/null @@ -1,1189 +0,0 @@ - - - - - - - asimtools package — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools package

-
- -
-
-

asimtools.calculators module

-

Tools for loading and returning ASE calculator objects for use in simulations

-
-
-asimtools.calculators.load_ase_calc(calc_params)[source]
-

Load any builtin ASE calculator

-
- -
-
-asimtools.calculators.load_calc(calc_id: str | None = None, calc_input: Dict | None = None)[source]
-

Loads a calculator using given calc_id or calc_input

-
-
Parameters:
-
    -
  • calc_id (str, optional) – ID/key to use to load calculator from the supplied/global calc_input file, defaults to None

  • -
  • calc_input (Optional[Dict], optional) – calc_input dictionary for a single calculator , defaults to None

  • -
-
-
Returns:
-

ASE calculator instance

-
-
Return type:
-

ase.calculators.calculators.Calculator

-
-
-
- -
-
-asimtools.calculators.load_chgnet(calc_params)[source]
-

Load CHGNet Calculator

-

https://chgnet.lbl.gov/#tutorials-and-docs

-
-
Parameters:
-

calc_params (Dict) – args to pass to loader

-
-
Returns:
-

CHGNet calculator

-
-
Return type:
-

chgnet.model.dynamics.CHGNetCalculator

-
-
-
- -
-
-asimtools.calculators.load_dp(calc_params)[source]
-

Load Deep Potential Calculator

-

https://docs.deepmodeling.com/projects/deepmd/en/master/

-
-
Parameters:
-

calc_params (Dict) – args to pass to loader

-
-
Returns:
-

DP calculator

-
-
Return type:
-

deepmd.calculator.DP

-
-
-
- -
-
-asimtools.calculators.load_espresso_profile(calc_params)[source]
-

Load Qunatum Espresso Calculator for ASE>3.22.1. If using older versions -such as the ones available on PyPI or conda-forge, just load it as an ASE -calculator. Until the new ASE version becomes an official release, we will -have to have both for compatibility. The interface however remains that of -ASE <=3.22.1 within ASIMTools for consistency using the command keyword

-

https://wiki.fysik.dtu.dk/ase/releasenotes.html

-
-
Parameters:
-

calc_params (Dict) – args to pass to loader

-
-
Returns:
-

Espresso calculator

-
-
Return type:
-

ase.calculators.espresso.Espresso

-
-
-
- -
-
-asimtools.calculators.load_m3gnet(calc_params)[source]
-

Load and M3GNet calculator

-
-
Parameters:
-

calc_params (Dict) – parameters to be passed to matgl.ext.ase.M3GNetCalculator. Must include a key “model” that points to the model used to instantiate the potential

-
-
Returns:
-

M3GNet calculator

-
-
Return type:
-

matgl.ext.ase.M3GNetCalculator

-
-
-
- -
-
-asimtools.calculators.load_mace(calc_params)[source]
-

Load MACE Calculator

-

https://github.com/ACEsuit/mace?tab=readme-ov-file

-
-
Parameters:
-

calc_params (Dict) – args to pass to loader

-
-
Returns:
-

MACE calculator

-
-
Return type:
-

mace.calculators.mace_mp

-
-
-
- -
-
-asimtools.calculators.load_mace_off(calc_params)[source]
-

Load MACE Calculator

-

https://github.com/ACEsuit/mace?tab=readme-ov-file

-
-
Parameters:
-

calc_params (Dict) – args to pass to loader

-
-
Returns:
-

MACE-OFF calculator

-
-
Return type:
-

mace.calculators.mace_mp

-
-
-
- -
-
-asimtools.calculators.load_nequip(calc_params)[source]
-

Load NequIP or Allegro calculator

-

https://github.com/mir-group/nequip/tree/main

-
-
Parameters:
-

calc_params (Dict) – args to pass to loader

-
-
Returns:
-

NequIP ase calculator

-
-
Return type:
-

nequip.ase.nequip_calculator.NequIPCalculator

-
-
-
- -
-
-

asimtools.job module

-

Set of tools for handling jobs in slurm, interactively or in the teminal for -a specific calculator.

-

Author: mkphuthi@github.com

-
-
-class asimtools.job.ChainedJob(sim_input: Dict, env_input: Dict | None = None, calc_input: Dict | None = None)[source]
-

Bases: Job

-

Jobs made of smaller sequential unitjobs. Note that this only works -well with unit jobs. If one of the UnitJobs calls asimmodules, internally, -slurm will fail to build the correct dependencies but the files will be -generated appropriately, you can submit them manually

-
-
-get_last_output() Dict[source]
-

Returns the output of the last job in the chain

-
- -
-
-submit(dependency: List | None = None) List[source]
-

Submit a job using slurm, interactively or in the terminal

-
- -
- -
-
-class asimtools.job.DistributedJob(sim_input: Dict, env_input: Dict | None = None, calc_input: Dict | None = None)[source]
-

Bases: Job

-

Array job object with ability to submit simultaneous jobs

-
-
-gen_input_files() None[source]
-

Write input files to working directory

-
- -
-
-submit(**kwargs) None[source]
-

Submit a job using slurm, interactively or in the terminal

-
- -
-
-submit_array(array_max=None, dependency: List[str] | None = None, **kwargs) None | List[str][source]
-

Submits a job array if all the jobs have the same env and use slurm

-
- -
-
-submit_jobs(**kwargs) None | List[str][source]
-

Submits the jobs. If submitting lots of batch jobs, we -recommend using DistributedJob.submit_array

-
- -
- -
-
-class asimtools.job.Job(sim_input: Dict, env_input: Dict | None = None, calc_input: Dict | None = None)[source]
-

Bases: object

-

Abstract class for the job object

-
-
-add_output_files(file_dict: Dict) None[source]
-

Adds a file to the output file list

-
- -
-
-complete() None[source]
-

Updates the output to signal that the job was started

-
- -
-
-discard() None[source]
-

Updates status to discarded

-
- -
-
-fail() None[source]
-

Updates status to failed

-
- -
-
-get_calc_input() Dict[source]
-

Get calculator input

-
- -
-
-get_env_input() Dict[source]
-

Get environment input

-
- -
-
-get_logger(logfilename='job.log', level='info')[source]
-

Get the logger

-
- -
-
-get_output() Dict[source]
-

Get values in output.yaml

-
- -
-
-get_output_yaml() Dict[source]
-

Get current output file

-
- -
-
-get_sim_input() Dict[source]
-

Get simulation input

-
- -
-
-get_status(display=False) Tuple[bool, str][source]
-

Check job status

-
- -
-
-get_workdir() Path[source]
-

Get working directory

-
- -
-
-go_to_workdir() None[source]
-

Go to workdir

-
- -
-
-leave_workdir() None[source]
-

goes to directory from which job was launched

-
- -
-
-mkworkdir() None[source]
-

Creates the work directory if it doesn’t exist

-
- -
-
-set_workdir(workdir) None[source]
-

Set working directory both in sim_input and instance

-
- -
-
-start() None[source]
-

Updates the output to signal that the job was started

-
- -
-
-update_calc_input(new_params) None[source]
-

Update calculator parameters

-
- -
-
-update_env_input(new_params) None[source]
-

Update calculator parameters

-
- -
-
-update_output(output_update: Dict) None[source]
-

Update output.yaml if it exists or write a new one

-
- -
-
-update_sim_input(new_params) None[source]
-

Update simulation parameters

-
- -
-
-update_status(status: str) None[source]
-

Updates job status to specificied value

-
- -
- -
-
-class asimtools.job.UnitJob(sim_input: Dict, env_input: Dict | None = None, calc_input: Dict | None = None)[source]
-

Bases: Job

-

Unit job object with ability to submit a slurm/interactive job. -Unit jobs run in a specific environment and if required, run a -specific calculator. More complex workflows are built up of unit -jobs

-
-
-gen_input_files(write_calc_input: bool = True, write_env_input: bool = True, write_image: bool = True) None[source]
-

Write input files to working directory

-
- -
-
-gen_run_command() str[source]
-

Generates the command to run the job, independent of slurm

-
- -
-
-submit(dependency: List | None = None, write_image: bool = True) None | List[str][source]
-

Submit a job using slurm, interactively or in the terminal

-
- -
- -
-
-asimtools.job.create_unitjob(sim_input, env_input, workdir, calc_input=None)[source]
-

Helper for making a generic UnitJob object, mostly for testing

-
- -
-
-asimtools.job.load_job_from_directory(workdir: str)[source]
-

Loads a job from a given directory

-
- -
-
-

asimtools.utils module

-

Utilities and helper functions for reading and writing data using set -standards

-
-
-asimtools.utils.change_dict_value(d: Dict, new_value, key_sequence: Sequence, return_copy: bool = True) Dict[source]
-

Changes a value in the specified dictionary given by following the -key sequence

-
-
Parameters:
-
    -
  • d (Dict) – dictionary to be changed

  • -
  • new_value (_type_) – The new value that will replace the old one

  • -
  • key_sequence (Sequence) – List of keys in the order in which they access the dictionary key

  • -
  • return_copy (bool, optional) – Whether to return a copy only or to modify the dictionary in-place as well, defaults to True

  • -
-
-
Returns:
-

The changed dictionary

-
-
Return type:
-

Dict

-
-
-
- -
-
-asimtools.utils.change_dict_values(d: Dict, new_values: Sequence, key_sequences: Sequence, return_copy: bool = True) Dict[source]
-

Changes values in the specified dictionary given by following the -key sequences. Key-value pairs are set in the given order

-
-
Parameters:
-
    -
  • d (Dict) – dictionary to be changed

  • -
  • new_values (Sequence) – The new values that will replace the old one

  • -
  • key_sequence (Sequence) – List of list of keys in the order in which they access the dictionary key

  • -
  • return_copy (bool, optional) – Whether to return a copy only or to modify the dictionary in-place as well, defaults to True

  • -
-
-
Returns:
-

The changed dictionary

-
-
Return type:
-

Dict

-
-
-
- -
-
-asimtools.utils.check_if_slurm_job_is_running(slurm_job_id: str | int)[source]
-

Checks if the slurm job with specifying job_id is running

-
-
Parameters:
-

slurm_job_id (Union[str,int]) – Job ID as str or int

-
-
Returns:
-

Whether job is running or not

-
-
Return type:
-

bool

-
-
-
- -
-
-asimtools.utils.find_nth(haystack: str, needle: str, n: int) int[source]
-

Return index of nth occurence of substring in string

-
- -
-
-asimtools.utils.get_atoms(image_file: str | None = None, interface: str = 'ase', builder: str | None = 'bulk', atoms: Atoms | None = None, repeat: Tuple[int, int, int] | None = None, rattle_stdev: float | None = None, mp_id: str | None = None, user_api_key: str | None = None, return_type: str = 'ase', **kwargs) Atoms | Structure[source]
-

Return an ASE Atoms or pymatgen Structure object based on specified -config. This is the recommended way to load atoms objects for asimmodules.

-
-
Parameters:
-
    -
  • image_file (str, optional) – Path to an ASE-readable image file, defaults to None

  • -
  • interface (str, optional) – Whether to use “ase” or “pymatgen” to create the atoms -object

  • -
  • builder (str, optional) – Builder to use from ase.build, defaults to ‘bulk’. Any extra keyword arguments specified are passed to the build

  • -
  • atoms (Atoms, optional) – ase.Atoms object, defaults to None

  • -
  • repeat (Tuple[int, int, int], optional) – Number of times to repeat input to create supercell, defaults to None

  • -
  • rattle_stdev (float, optional) – stdev to be provided to ase.Atoms.rattle(), or as distance to pymatgen.core.structure.Structure.perturb() -defaults to None

  • -
  • mp_id (str, optional) – Material Project ID to fetch structure from, defaults to None

  • -
  • user_api_key (str, optional) – Material Project API key, must be provided to get -structures from Materials Project, defaults to None

  • -
  • return_type – When set to ase returns a ase.Atoms object, -when set to pymatgen returns a -pymatgen.core.structure.Structure object, defaults to ‘ase’

  • -
-
-
Returns:
-

One ase.Atoms or -pymatgen.core.structure.Structure instance

-
-
Return type:
-

Union[Atoms, Structure]

-
-
-

There are three options one could use to specify and image or an atoms -objects:

-
    -
  1. image_file + **kwargs

  2. -
  3. builder + **kwargs.

  4. -
  5. atoms

  6. -
-
-

Examples

-

Some examples using builders from ASE. All **kwargs are passed to -ase.build():

-
>>> get_atoms(builder='molecule', name='H2O')
-Atoms(symbols='OH2', pbc=False)
->>> get_atoms(builder='bulk', name='Cu')
-Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]])
->>> get_atoms(builder='bulk', name='Ar', crystalstructure='fcc', a=3.4, cubic=True)
-Atoms(symbols='Ar4', pbc=True, cell=[3.4, 3.4, 3.4])
->>> get_atoms(builder='fcc100', symbol='Fe', vacuum=8, size=[4,4, 5])
-Atoms(symbols='Cu80', pbc=[True, True, False], cell=[10.210621920333747, 10.210621920333747, 23.22], tags=...)
-
-
-

Some examples for reading an image from a file using ase.io.read() -are given below. All **kwargs are passed to ase.io.read()

-
>>> h2o = get_atoms(builder='molecule', name='H2O')
->>> h2o.write('h2o.cif')
->>> get_atoms(image_file='h2o.cif')
-Atoms(symbols='OH2', pbc=False)
->>> get_atoms(image_file='h2o.cif', format='cif')
-Atoms(symbols='OH2', pbc=False)
->>> from ase.io import write
->>> molecules = [get_atoms(builder='molecule', name='H2O'), get_atoms(builder='molecule', name='H2')]
->>> write('molecules.xyz', molecules, format='extxyz')
->>> get_atoms(image_file='molecules.xyz', index=0) # Pick out one structure using indexing
-Atoms(symbols='OH2', pbc=False)
-
-
-

You can also make supercells and rattle the atoms

-
>>> li_bulk = get_atoms(name='Li')
->>> li_bulk.write('POSCAR', format='vasp')
->>> get_atoms(image_file='POSCAR', repeat=[3,3,3])
-Atoms(symbols='Li27', pbc=True, cell=[[-5.235, 5.235, 5.235], [5.235, -5.235, 5.235], [5.235, 5.235, -5.235]])
->>> get_atoms(builder='bulk', name='Li', repeat=[2,2,2], rattle_stdev=0.01)
-Atoms(symbols='Li8', pbc=True, cell=[[-3.49, 3.49, 3.49], [3.49, -3.49, 3.49], [3.49, 3.49, -3.49]])
-
-
-

Mostly for internal use and use in asimmodules, one can specify atoms -directly

-
>>> li_bulk = get_atoms(name='Li')
->>> get_atoms(atoms=li_bulk)
-Atoms(symbols='Li', pbc=True, cell=[[-1.745, 1.745, 1.745], [1.745, -1.745, 1.745], [1.745, 1.745, -1.745]])
-
-
-

In an asimmodule, the image argument is always given as a dictionary, -you therefore have to expand it before passing it to get_atoms

-
>>> image = {'name': 'Pt'}
->>> get_atoms(**image)
-Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]])
-
-
-

To get a pymatgen structure object, set the return_type to “pymatgen”

-
>>> image = {'name': 'Pt', 'return_type': 'pymatgen'}
->>> get_atoms(**image)
-Structure Summary
-Lattice
-...
-
-
-

To download a structure from the Materials Project, you need to provide -an API key, the MP ID of the structure and set the interface to ‘pymatgen’ -You can also specify whether you want the primitive(default) or -conventional unit cell as a keyword argument

-
>>> {'mp_id': 'mp-14', 'interface': 'pymatgen', 'user_api_key': "USER_API_KEY", 'conventional_unit_cell': True},
->>> get_atoms(**image)
-Structure Summary
-Lattice
-abc : 2.7718585822512662 2.7718585822512662 2.7718585822512662
-...
-
-
-
-
- -
-
-asimtools.utils.get_axis_lims(x: Sequence, y: Sequence, padding: float = 0.1)[source]
-

Get an estimate of good limits for a plot axis

-
- -
-
-asimtools.utils.get_calc_input()[source]
-

Gets the global calc_input from the environment variable, then tries -then .asimtools dotfile

-
-
Returns:
-

calc_input dictionary or empty dictionary if not found

-
-
Return type:
-

Dict

-
-
-
- -
-
-asimtools.utils.get_env_input() Dict[source]
-

Gets the global env_input from the environment variable, then tries -then .asimtools dotfile. If an env_input.yaml is present in the -work direcory, it takes precedence.

-
-
Returns:
-

env_input dictionary or empty dictionary if not found

-
-
Return type:
-

Dict

-
-
-
- -
-
-asimtools.utils.get_images(image_file: str | None = None, pattern: str | None = None, patterns: List[str] | None = None, images: Iterable[Atoms] | None = None, index: str | int = ':', skip_failed: bool = False, **kwargs) List[Atoms][source]
-
-
Return a list of atoms objects based on the input arguments. Options to specify are:
    -
  1. image_file

  2. -
  3. pattern

  4. -
  5. patterns

  6. -
  7. images

  8. -
-
-
-
-
Parameters:
-
    -
  • image_file (str, optional) – Path to ASE-readable file with one or more images, defaults to None

  • -
  • pattern (str, optional) – String pattern of paths from which to search for images, defaults to None. This only gets the last image from each file as in ase.io.read() if an index is not specified.

  • -
  • patterns – Sequence of string patterns/paths from which to search for images, defaults to None. This only gets one image from each file as in ase.io.read() without specifying an index

  • -
  • images (Iterable[Atoms], optional) – A list of atoms objects, defaults to None

  • -
  • index (Union[str, int], optional) – Index to specify when using ase.io.read(), defaults -to ‘:’

  • -
  • skip_failed (bool, optional) – Whether to raise an IO error if it fails to read any of -the specified images or ignore errors, defaults to False

  • -
-
-
Raises:
-

IOError – Failed to read one of the specified images

-
-
Returns:
-

List of ase.Atoms for all images found

-
-
Return type:
-

List[Atoms]

-
-
-

There are three options one could use to specify and image or an atoms -objects:

-
    -
  1. image_file + **kwargs for specifying one image file

  2. -
  3. pattern + **kwargs for specifying multiple image files with a wildcard -character

  4. -
  5. patterns + **kwargs for specifying a list of patterns to match, -captures the above two cases

  6. -
  7. images

  8. -
-
-

Examples

-

Some examples for reading images selectively from an image_file. All -**kwargs are passed to ase.io.read():

-
>>> from asimtools.utils import get_atoms
->>> molecules = []
->>> molecules.append(get_atoms(builder='molecule', name='H2O'))
->>> molecules.append(get_atoms(builder='molecule', name='H2'))
->>> molecules.append(get_atoms(builder='molecule', name='N2'))
->>> write('molecules.xyz', molecules, format='extxyz')
->>> get_images(image_file='molecules.xyz')
-[Atoms(symbols='OH2', pbc=False), Atoms(symbols='H2', pbc=False), Atoms(symbols='N2', pbc=False)]
->>> get_images(image_file='molecules.xyz', index=':2')
-[Atoms(symbols='OH2', pbc=False), Atoms(symbols='H2', pbc=False)]
-
-
-

You can also use a wildcard (*) by specifying the pattern argument. Notice -that the files don’t have to be the same format if ASE can guess all the -file formats, otherwise you can specify the format argument which should -apply to all the images.

-
>>> cu = get_atoms(name='Cu')
->>> cu.write('bulk_cu.cfg')
->>> fe = get_atoms(name='Fe')
->>> fe.write('bulk_fe.cif')
->>> pt = get_atoms(name='Pt')
->>> pt.write('bulk_pt.cfg')
->>> get_images(pattern='bulk*')
-[Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], masses=..., momenta=...), Atoms(symbols='Fe', pbc=True, cell=[[2.48549, 0.0, 0.0], [-0.8284876429214074, 2.3433456351179887, 0.0], [-0.8284876429214074, -1.171653675382785, 2.0294079014797743]], spacegroup_kinds=...), Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]], masses=..., momenta=...)]
-Atoms(symbols='OH2', pbc=False)
->>> get_images(pattern='bulk*.cfg', format='cfg')
-[Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], masses=..., momenta=...), Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]], masses=..., momenta=...)]
-
-
-

You can also specify multiple patterns

-
>>> get_images(patterns=['bulk*.cfg', 'bulk\*.cif'])
-[Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], masses=..., momenta=...), Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]], masses=..., momenta=...), Atoms(symbols='Fe', pbc=True, cell=[[2.48549, 0.0, 0.0], [-0.8284876429214074, 2.3433456351179887, 0.0], [-0.8284876429214074, -1.171653675382785, 2.0294079014797743]], spacegroup_kinds=...)]
-
-
-

Or you can directly pass a list of Atoms, mostly for internal use

-
>>> get_images(images=molecules)
-[Atoms(symbols='OH2', pbc=False), Atoms(symbols='H2', pbc=False), Atoms(symbols='N2', pbc=False)]
-
-
-

In an asimmodule, the images argument is always given as a dictionary, -you therefore have to expand it before passing it to get_images

-
>>> images = {'pattern': 'bulk*'}
->>> get_images(**images)
-[Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], masses=..., momenta=...), Atoms(symbols='Fe', pbc=True, cell=[[2.48549, 0.0, 0.0], [-0.8284876429214074, 2.3433456351179887, 0.0], [-0.8284876429214074, -1.171653675382785, 2.0294079014797743]], spacegroup_kinds=...), Atoms(symbols='Pt', pbc=True, cell=[[0.0, 1.96, 1.96], [1.96, 0.0, 1.96], [1.96, 1.96, 0.0]], masses=..., momenta=...)]
-
-
-
-
- -
-
-asimtools.utils.get_logger(logfile='job.log', fstr='%(asctime)s |%(module)s|%(funcName)s| %(levelname)s: %(message)s', level='debug')[source]
-

Get the logger

-
- -
-
-asimtools.utils.get_nth_label(s: str, n: int = 1)[source]
-

Return nth label in a string potentially containing multiple labels, -indexing starts from 0

-
- -
-
-asimtools.utils.get_str_btn(s: str | PathLike, s1: str, s2: str, occurence: int | None = 0, start_index: int | None = 0)[source]
-

Returns the substring between strings s1 and s2 from s

-
-
Parameters:
-
    -
  • s (str) – string/path from which to extract substring

  • -
  • s1 (str) – substring before the desired substring, None starts from -the beginning of s

  • -
  • s2 (str) – substring after the desired substring, None ends at the -end of the string

  • -
  • occurence (int, optional) – which occurence to return e.g. occurence=1 returns the -second time a substring is encountered, defaults to 0

  • -
  • start_index – first index from which to search for substring, -defaults to 0

  • -
-
-
Returns:
-

substring

-
-
Return type:
-

_type_

-
-
-
- -
-
-asimtools.utils.join_names(substrs: Sequence[str]) str[source]
-

Join multiple strings using a hyphen neatly

-
-
Parameters:
-

substrs (Sequence[str]) – Sequence of strings to merge

-
-
Returns:
-

Joined strings

-
-
Return type:
-

str

-
-
-
- -
-
-asimtools.utils.new_db(dbname: str)[source]
-

Creates a new ASE database overwriting an old one

-
-
Parameters:
-

dbname (str) – Name for the new database

-
-
Returns:
-

Connection to database

-
-
Return type:
-

ase.db connection

-
-
-
- -
-
-asimtools.utils.parse_slice(value: str) slice[source]
-

Parses a slice() from string, like start:stop:step.

-
-
Parameters:
-

value (str) – Slice string

-
-
Returns:
-

slice object

-
-
Return type:
-

slice

-
-
-
- -
-
-asimtools.utils.read_yaml(yaml_path: str) Dict[source]
-

Read a yaml file

-
-
Parameters:
-

yaml_path (str) – Path to yaml file

-
-
Returns:
-

Dictionary

-
-
Return type:
-

Dict

-
-
-
- -
-
-asimtools.utils.strip_symbols(substr: str) str[source]
-

Helper function to format filenames using standard

-
-
Parameters:
-

substr (str) – substring

-
-
Returns:
-

stripped string

-
-
Return type:
-

str

-
-
-
- -
-
-asimtools.utils.write_csv_from_dict(fname: str, data: Dict, columns: Sequence | None = None, header: str = '', **kwargs) DataFrame[source]
-

Write a tabulated csv to a file from a dictionary. The keys will -become the columns and the values will be the columns, All columns used -must have the same length. kwargs are passed to -pandas.Dataframe.to_csv()

-
-
Parameters:
-
    -
  • fname (str) – File name to be return to

  • -
  • data (Dict) – Dictionary to write

  • -
  • columns (Iterable, optional) – Keys to use as columns of csv, defaults to None

  • -
-
-
Returns:
-

Pandas dataframe of results

-
-
Return type:
-

pd.DataFrame

-
-
-
- -
-
-asimtools.utils.write_yaml(yaml_path: str, yaml_Dict: Dict) None[source]
-

Write a dictionary to a yaml file

-
-
Parameters:
-
    -
  • yaml_path (str) – Path to write yaml to

  • -
  • yaml_Dict (Dict) – Dictionary to write

  • -
-
-
-
- -
-
-

Module contents

-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/genindex.html b/_build/genindex.html deleted file mode 100644 index f2082b4..0000000 --- a/_build/genindex.html +++ /dev/null @@ -1,781 +0,0 @@ - - - - - - Index — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- - -

Index

- -
- A - | C - | D - | F - | G - | I - | J - | L - | M - | N - | O - | P - | R - | S - | T - | U - | V - | W - -
-

A

- - - -
    -
  • - asimtools.asimmodules.phonons - -
  • -
  • - asimtools.asimmodules.phonons.ase_phonons - -
  • -
  • - asimtools.asimmodules.singlepoint - -
  • -
  • - asimtools.asimmodules.surface_energies - -
  • -
  • - asimtools.asimmodules.surface_energies.surface_energies - -
  • -
  • - asimtools.asimmodules.template - -
  • -
  • - asimtools.asimmodules.transformations - -
  • -
  • - asimtools.asimmodules.transformations.scale_unit_cells - -
  • -
  • - asimtools.asimmodules.vacancy_formation_energy - -
  • -
  • - asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy - -
  • -
  • - asimtools.asimmodules.workflows - -
  • -
  • - asimtools.asimmodules.workflows.calc_array - -
  • -
  • - asimtools.asimmodules.workflows.chained - -
  • -
  • - asimtools.asimmodules.workflows.distributed - -
  • -
  • - asimtools.asimmodules.workflows.image_array - -
  • -
  • - asimtools.asimmodules.workflows.sim_array - -
  • -
  • - asimtools.calculators - -
  • -
  • - asimtools.job - -
  • -
  • - asimtools.utils - -
  • -
  • atom_relax() (in module asimtools.asimmodules.geometry_optimization.atom_relax) -
  • -
- -

C

- - - -
- -

D

- - - -
- -

F

- - - -
- -

G

- - - -
- -

I

- - -
- -

J

- - - -
- -

L

- - - -
- -

M

- - -
- -

N

- - -
- -

O

- - -
- -

P

- - - -
- -

R

- - - -
- -

S

- - - -
- -

T

- - -
- -

U

- - - -
- -

V

- - -
- -

W

- - - -
- - - -
-
-
- -
- -
-

© Copyright 2023, Mgcini Keith Phuthi.

-
- - Built with Sphinx using a - theme - provided by Read the Docs. - - -
-
-
-
-
- - - - \ No newline at end of file diff --git a/_build/include_contributing.html b/_build/include_contributing.html deleted file mode 100644 index 5d80a76..0000000 --- a/_build/include_contributing.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - Contributing to ASIMTools — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Contributing to ASIMTools

-
-

Contributing

-

When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.

-

Please note we have a code of conduct, please follow it in all your interactions with the project.

-

There are two main ways to contribute. One is to make changes to the existing -codes and asimmodules. In this case, please make sure your change passes tests or -submit a test accordinly. The second way to contribute is to add a new asimmodule -to the core set of asimmodules. Reviewers will work with you to make sure your new -asimmodule follows best practice including using utils, syntax highlighting, docs -and tests.

-
-

Pull Request Process

-
    -
  1. Ensure any install or build dependencies are removed before the end of the layer when doing a build.

  2. -
  3. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters.

  4. -
  5. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is SemVer.

  6. -
  7. You may merge the Pull Request in once you have the sign-off of one other developer, or if you do not have permission to do that, you may request the other reviewer to merge it for you.

  8. -
-
-
-

Code of Conduct

-
-

Our Pledge

-

In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation.

-
-
-

Our Standards

-

Examples of behavior that contributes to creating a positive environment -include:

-
    -
  • Using welcoming and inclusive language

  • -
  • Being respectful of differing viewpoints and experiences

  • -
  • Gracefully accepting constructive criticism

  • -
  • Focusing on what is best for the community

  • -
  • Showing empathy towards other community members

  • -
-

Examples of unacceptable behavior by participants include:

-
    -
  • The use of sexualized language or imagery and unwelcome sexual attention or -advances

  • -
  • Trolling, insulting/derogatory comments, and personal or political attacks

  • -
  • Public or private harassment

  • -
  • Publishing others’ private information, such as a physical or electronic -address, without explicit permission

  • -
  • Other conduct which could reasonably be considered inappropriate in a -professional setting

  • -
-
-
-

Our Responsibilities

-

Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior.

-

Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful.

-
-
-

Scope

-

This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers.

-
-
-

Enforcement

-

Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [INSERT EMAIL ADDRESS]. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately.

-

Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project’s leadership.

-
-
-

Attribution

-

This Code of Conduct is adapted from the Contributor Covenant, version 1.4, -available at http://contributor-covenant.org/version/1/4

-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/include_readme.html b/_build/include_readme.html deleted file mode 100644 index a99fe6f..0000000 --- a/_build/include_readme.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - README — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

README

- - - - - -

Documentation | GitHub

-
-

Atomic SIMulation Tools

-

This package is a lightweight workflow and simulation manager for reproducible -atomistic simulations that can be transferred across environments, calculators -and structures on Unix systems. By using in-built or user-defined asimmodules -and utilities, users can run/build their own simulation recipes and -automagically scale them locally or on slurm based clusters. The core idea is -to separate the dependence of the atomistic potential/calculator and the -simulations steps thereby allowing the same simulation to be run with multiple -calculators/codes and the same calculator to be used for multiple simulation -parameters without altering simulation code. Input and output files follow a -simple consisten file structure and format so that consistent analysis -pipelines can be used across users. For a concrete example of how ASIMTools -achieves this, see the Developing Custom Asimmodules page

-
-

Developer philosophy

-

The goal of asimtools is to push all the complexity of workflow management, -best-practices, file management etc. into the backend such that the everyday -user only has to handle input files for existing workflows and asimmodule files -for workflows they want to implement.This allows the user to focus on doing the -science and designing experiments. The following are the guiding principles for -how asimtools should work:

-
    -
  • Asimmodules should resemble boilerplate ASE code as much as possible.

  • -
  • Asimmodules should avoid explicitly depending on a calculator

  • -
  • Asimmodules should not explicitly depend on the context/environment in which -they run

  • -
  • It should be easy to debug individual asimmodules/parts in large workflows. -In addition, it should always be possible to debug/resubmit jobs without -using asimtools.

  • -
  • Input file structure and format should be standard across all asimmodules. In -addition all input parameters should match how they would like without -asimtools i.e. do not provide an API!

  • -
  • Job progress tracking must be incorporated for easy debugging

  • -
  • Best practices should be built-in e.g. if multiple jobs of the same slurm -context are submitted simulataneously, it must be a job array.

  • -
-
-
-

Philosophy on User Experience

-

The philosophy is to build “simulations” using building blocks of asimmodules. -Asimmodules are nothing but Python functions that return a dictionary, anything -can be done in the function code. These asimmodules can be as -complicated/efficient as you make them using any external packages you want and -can be optimized with time but can still be run within the framework. This -allows a test friendly way to transition from say a tutorial on the -ASE/pymatgen website to an asimtools asimmodule. So while complicated wrappers -are discouraged, they would still work as long as the asimmodule works. The -benefit out of the box is that you can make your asimmodule independent of -calculator or input structures and submit them easily.

-

We also aim to provide a standard set of robust and efficient simulation -protocols as we develop. You can see all the implemented workflows provided -with the package in the examples directory and modify them to your application -If you have suggestions for improvements in methodology or code, please bring -up an issue on github!

-
-
-

Getting Started

-

These instructions will give you a copy of the project up and running.

-
-

Installing ASIMTools

-

If you prefer to use a conda a environment, you can create and activate one -using:

-
conda create -n asimtools python=3.9
-conda activate asimtools
-
-
-

Then you can install asimtools either using pip or by cloning the source code -from github. Note that the cloned version might have some minor bug fixes that -are not included in the official PyPI release. It is also easier to go through -the examples if you clone the repository.

-

To install the latest asimtools release from PyPI, you can simply use

-
pip install asimtools
-
-
-

To install from source use

-
git clone
-https://gitlab.com/ase/ase.git && cd ase pip install . cd ../
-
-git clone https://github.com/BattModels/asimtools.git
-cd asimtools
-pip install .
-
-
-

You can also choose to use the latest version of ASE since the ones on PyPI and -conda are quite outdated.

-
git clone https://gitlab.com/ase/ase.git
-cd ase
-pip install .
-
-
-

Individual calculators may need external packages for running them. For example -if you want to use Quantum Espresso or CASTEP, you will have to install them. -Similarly some asimmodules e.g. lammps.py might also need external packages -to be used. It is up to the user to make sure those are installed.

-

You will also need to setup some environment variables, these variables point -to global env_input.yaml and calc_input.yaml files with your favorite -configurations since these are commonly shared among simulations. You can also -directly specify them when running asim-execute (See asim-execute -h). You -can also provide a directory for ASIMTools to search for your custom -asimmodules. Examples of these files can be found in the examples.

-

Add the following to your .bashrc

-
export ASIMTOOLS_ENV_INPUT=/path/to/my/global/env_input.yaml
-export ASIMTOOLS_CALC_INPUT=/path/to/my/global/calc_input.yaml
-export ASIMTOOLS_ASIMMODULE_DIR=/path/to/my/asimmodule/dir
-
-
-
-
-
-

Running the tests

-

To run tests for the workflow tools, from the tests directory, call:

-
pytest
-
-
-

To run the test suite on a component component.py , call:

-
pytest test_component.py
-
-
-

To run all tests for the provided asimmodules, cd into the examples directory -and call:

-
source run_all.sh
-
-
-

Or you can run a test for each individual example in its directory using:

-
source run.sh
-
-
-

If no errors are reported, the tests have passed. These tests simply test the -functionality of the code, not the scientific validity of the simulations!

-

To run tests for the provided asimmodules using slurm, you can similarly run -the bash scripts ending with _slurm.sh. This will submit a number of jobs, -none longer than 1 minute.

-
-
-

Contributing

-

Please read CONTRIBUTING.md for details on our code -of conduct, and the process for submitting pull requests to us.

-
-
-

Authors

- -

See also the list of -contributors -who participated in this project.

-
-
-

License

-

This project is licensed under the MIT License

-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/index.html b/_build/index.html deleted file mode 100644 index f5c9ea6..0000000 --- a/_build/index.html +++ /dev/null @@ -1,403 +0,0 @@ - - - - - - - Welcome to asimtools’s documentation! — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Welcome to asimtools’s documentation!

-
-

Contents:

- -
-
-
-

Indices and tables

- -
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/modules.html b/_build/modules.html deleted file mode 100644 index cf028f5..0000000 --- a/_build/modules.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - asimtools — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

asimtools

-
- -
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/objects.inv b/_build/objects.inv deleted file mode 100644 index 20e669f..0000000 Binary files a/_build/objects.inv and /dev/null differ diff --git a/_build/py-modindex.html b/_build/py-modindex.html deleted file mode 100644 index 4f59254..0000000 --- a/_build/py-modindex.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - Python Module Index — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- - -

Python Module Index

- -
- a -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
- a
- asimtools -
    - asimtools.asimmodules -
    - asimtools.asimmodules.benchmarking -
    - asimtools.asimmodules.benchmarking.parity -
    - asimtools.asimmodules.do_nothing -
    - asimtools.asimmodules.elastic_constants -
    - asimtools.asimmodules.elastic_constants.cubic_energy_expansion -
    - asimtools.asimmodules.eos -
    - asimtools.asimmodules.eos.postprocess -
    - asimtools.asimmodules.geometry_optimization -
    - asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization -
    - asimtools.asimmodules.geometry_optimization.atom_relax -
    - asimtools.asimmodules.geometry_optimization.cell_relax -
    - asimtools.asimmodules.geometry_optimization.optimize -
    - asimtools.asimmodules.geometry_optimization.symmetric_cell_relax -
    - asimtools.asimmodules.lammps -
    - asimtools.asimmodules.lammps.lammps -
    - asimtools.asimmodules.phonons -
    - asimtools.asimmodules.phonons.ase_phonons -
    - asimtools.asimmodules.singlepoint -
    - asimtools.asimmodules.surface_energies -
    - asimtools.asimmodules.surface_energies.surface_energies -
    - asimtools.asimmodules.template -
    - asimtools.asimmodules.transformations -
    - asimtools.asimmodules.transformations.scale_unit_cells -
    - asimtools.asimmodules.vacancy_formation_energy -
    - asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy -
    - asimtools.asimmodules.workflows -
    - asimtools.asimmodules.workflows.calc_array -
    - asimtools.asimmodules.workflows.chained -
    - asimtools.asimmodules.workflows.distributed -
    - asimtools.asimmodules.workflows.image_array -
    - asimtools.asimmodules.workflows.sim_array -
    - asimtools.calculators -
    - asimtools.job -
    - asimtools.utils -
- - -
-
-
- -
- -
-

© Copyright 2023, Mgcini Keith Phuthi.

-
- - Built with Sphinx using a - theme - provided by Read the Docs. - - -
-
-
-
-
- - - - \ No newline at end of file diff --git a/_build/search.html b/_build/search.html deleted file mode 100644 index 0847a90..0000000 --- a/_build/search.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - Search — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
-
    -
  • - -
  • -
  • -
-
-
-
-
- - - - -
- -
- -
-
-
- -
- -
-

© Copyright 2023, Mgcini Keith Phuthi.

-
- - Built with Sphinx using a - theme - provided by Read the Docs. - - -
-
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/_build/searchindex.js b/_build/searchindex.js deleted file mode 100644 index ad60bc0..0000000 --- a/_build/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({"docnames": ["CONTRIBUTING", "README", "asimplify", "asimtools", "asimtools.asimmodules", "asimtools.asimmodules.benchmarking", "asimtools.asimmodules.elastic_constants", "asimtools.asimmodules.eos", "asimtools.asimmodules.geometry_optimization", "asimtools.asimmodules.lammps", "asimtools.asimmodules.phonons", "asimtools.asimmodules.surface_energies", "asimtools.asimmodules.transformations", "asimtools.asimmodules.vacancy_formation_energy", "asimtools.asimmodules.workflows", "include_contributing", "include_readme", "index", "modules", "usage", "workflows"], "filenames": ["CONTRIBUTING.md", "README.md", "asimplify.rst", "asimtools.rst", "asimtools.asimmodules.rst", "asimtools.asimmodules.benchmarking.rst", "asimtools.asimmodules.elastic_constants.rst", "asimtools.asimmodules.eos.rst", "asimtools.asimmodules.geometry_optimization.rst", "asimtools.asimmodules.lammps.rst", "asimtools.asimmodules.phonons.rst", "asimtools.asimmodules.surface_energies.rst", "asimtools.asimmodules.transformations.rst", "asimtools.asimmodules.vacancy_formation_energy.rst", "asimtools.asimmodules.workflows.rst", "include_contributing.rst", "include_readme.rst", "index.rst", "modules.rst", "usage.rst", "workflows.rst"], "titles": ["Contributing", "Atomic SIMulation Tools", "Developing Custom Asimmodules", "asimtools package", "asimtools.asimmodules package", "asimtools.asimmodules.benchmarking package", "asimtools.asimmodules.elastic_constants package", "asimtools.asimmodules.eos package", "asimtools.asimmodules.geometry_optimization package", "asimtools.asimmodules.lammps package", "asimtools.asimmodules.phonons package", "asimtools.asimmodules.surface_energies package", "asimtools.asimmodules.transformations package", "asimtools.asimmodules.vacancy_formation_energy package", "asimtools.asimmodules.workflows package", "Contributing to ASIMTools", "README", "Welcome to asimtools\u2019s documentation!", "asimtools", "Running an Existing Asimmodule", "Using built-in workflow tools"], "terms": {"when": [0, 1, 3, 15, 16], "thi": [0, 1, 2, 3, 4, 5, 6, 8, 13, 15, 16, 19, 20], "repositori": [0, 1, 2, 15, 16, 19], "pleas": [0, 1, 15, 16], "first": [0, 2, 3, 4, 6, 15], "discuss": [0, 15], "chang": [0, 2, 3, 14, 15, 19], "you": [0, 1, 2, 3, 13, 15, 16, 19, 20], "wish": [0, 15], "make": [0, 1, 3, 14, 15, 16, 17, 19], "via": [0, 15], "issu": [0, 1, 2, 15, 16, 19], "email": [0, 15], "ani": [0, 1, 3, 8, 15, 16, 17, 19], "other": [0, 2, 14, 15, 19, 20], "method": [0, 4, 6, 15, 19], "owner": [0, 15], "befor": [0, 3, 14, 15, 19], "note": [0, 1, 3, 14, 15, 16, 19], "we": [0, 1, 2, 3, 14, 15, 16, 19], "have": [0, 1, 2, 3, 15, 16, 19], "follow": [0, 1, 2, 3, 14, 15, 16, 19], "all": [0, 1, 2, 3, 11, 13, 14, 15, 16, 19], "your": [0, 1, 2, 15, 16, 19, 20], "interact": [0, 2, 3, 14, 15, 19], "project": [0, 1, 3, 15, 16, 19], "There": [0, 2, 3, 15], "ar": [0, 1, 2, 3, 4, 9, 12, 14, 15, 16, 19, 20], "two": [0, 3, 15], "main": [0, 3, 15, 19], "wai": [0, 1, 3, 15, 16, 19], "One": [0, 3, 15, 19], "i": [0, 1, 2, 3, 4, 6, 8, 12, 14, 15, 16, 19, 20], "exist": [0, 1, 3, 5, 15, 16], "asimmodul": [0, 1, 3, 15, 16, 17, 18, 20], "In": [0, 1, 2, 3, 14, 15, 16, 19], "case": [0, 2, 3, 14, 15, 19], "sure": [0, 1, 15, 16, 19], "pass": [0, 1, 3, 6, 11, 12, 13, 14, 15, 16, 19], "test": [0, 3, 4, 15, 17, 19], "submit": [0, 1, 3, 14, 15, 16, 17, 18, 19], "accordinli": [0, 15], "The": [0, 1, 2, 3, 14, 15, 16, 19], "second": [0, 3, 4, 15], "add": [0, 1, 3, 14, 15, 16, 19], "new": [0, 3, 15, 19], "core": [0, 1, 3, 5, 11, 15, 16, 19], "set": [0, 1, 2, 3, 12, 14, 15, 16, 19], "review": [0, 15], "work": [0, 1, 2, 3, 5, 14, 15, 16, 19], "best": [0, 1, 2, 15, 16], "practic": [0, 1, 15, 16], "includ": [0, 1, 2, 3, 8, 15, 16, 19], "us": [0, 1, 3, 4, 5, 6, 8, 10, 14, 15, 16, 17, 19], "util": [0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], "syntax": [0, 2, 15], "highlight": [0, 2, 15], "doc": [0, 3, 15, 17], "ensur": [0, 15], "instal": [0, 15, 17, 19], "build": [0, 1, 3, 15, 16, 17, 19, 20], "depend": [0, 1, 2, 3, 14, 15, 16, 19, 20], "remov": [0, 13, 15], "end": [0, 1, 2, 3, 15, 16], "layer": [0, 15], "do": [0, 1, 2, 10, 13, 15, 16, 19], "updat": [0, 3, 15], "readm": [0, 3, 15, 17], "md": [0, 1, 9, 15, 16], "detail": [0, 1, 15, 16, 19], "interfac": [0, 3, 15, 19], "environ": [0, 1, 2, 3, 14, 15, 16, 19], "variabl": [0, 1, 2, 3, 9, 15, 16, 19], "expos": [0, 15], "port": [0, 15], "file": [0, 1, 2, 3, 5, 8, 9, 12, 14, 15, 16, 17], "locat": [0, 15], "contain": [0, 3, 14, 15, 19], "paramet": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 20], "increas": [0, 15], "version": [0, 1, 3, 15, 16, 19], "number": [0, 1, 3, 5, 7, 8, 14, 15, 16, 19], "exampl": [0, 1, 2, 8, 15, 16, 19, 20], "would": [0, 1, 2, 15, 16, 19], "repres": [0, 15], "scheme": [0, 15], "semver": [0, 15], "mai": [0, 1, 5, 15, 16, 19], "merg": [0, 3, 15], "onc": [0, 14, 15], "sign": [0, 15], "off": [0, 3, 15], "one": [0, 1, 2, 3, 12, 14, 15, 16, 19, 20], "develop": [0, 15, 17, 20], "permiss": [0, 15], "interest": [0, 15], "foster": [0, 15], "an": [0, 1, 2, 3, 7, 14, 15, 16, 20], "open": [0, 15], "welcom": [0, 15], "contributor": [0, 1, 15, 16], "maintain": [0, 15], "particip": [0, 1, 15, 16], "commun": [0, 15], "harass": [0, 15], "free": [0, 15], "experi": [0, 15, 17], "everyon": [0, 15], "regardless": [0, 15], "ag": [0, 2, 15], "bodi": [0, 15], "size": [0, 3, 15], "disabl": [0, 15], "ethnic": [0, 15], "gender": [0, 15], "ident": [0, 15], "express": [0, 15], "level": [0, 3, 15, 19], "nation": [0, 15], "person": [0, 15], "appear": [0, 15], "race": [0, 15], "religion": [0, 15], "sexual": [0, 15], "orient": [0, 15], "behavior": [0, 15], "creat": [0, 1, 3, 13, 15, 16, 19], "posit": [0, 13, 15], "inclus": [0, 15], "languag": [0, 15], "Being": [0, 15], "respect": [0, 15], "differ": [0, 2, 14, 15, 19, 20], "viewpoint": [0, 15], "gracefulli": [0, 15], "accept": [0, 15], "construct": [0, 15], "critic": [0, 15], "focus": [0, 15], "what": [0, 2, 15, 19], "show": [0, 2, 15], "empathi": [0, 15], "toward": [0, 15], "member": [0, 15], "unaccept": [0, 15], "imageri": [0, 15], "unwelcom": [0, 15], "attent": [0, 15], "advanc": [0, 15, 20], "troll": [0, 15], "insult": [0, 15], "derogatori": [0, 15], "comment": [0, 15], "polit": [0, 15], "attack": [0, 15], "public": [0, 15], "privat": [0, 15], "publish": [0, 15], "inform": [0, 15, 19], "physic": [0, 15], "electron": [0, 15], "address": [0, 15], "without": [0, 1, 2, 3, 15, 16], "explicit": [0, 15], "which": [0, 1, 2, 3, 8, 9, 12, 14, 15, 16, 19], "could": [0, 3, 15, 19], "reason": [0, 2, 15], "consid": [0, 5, 11, 15], "inappropri": [0, 15], "profession": [0, 15], "clarifi": [0, 15], "expect": [0, 14, 15], "take": [0, 2, 3, 15, 19], "appropri": [0, 3, 15], "fair": [0, 15], "correct": [0, 3, 15, 19], "action": [0, 15], "instanc": [0, 3, 5, 15], "right": [0, 15], "edit": [0, 15, 19], "reject": [0, 15], "commit": [0, 15], "wiki": [0, 3, 8, 15], "align": [0, 15], "ban": [0, 15], "temporarili": [0, 15], "perman": [0, 15], "thei": [0, 1, 3, 15, 16, 19, 20], "deem": [0, 15], "threaten": [0, 15], "offens": [0, 15], "harm": [0, 15], "appli": [0, 2, 3, 6, 12, 13, 14, 15, 19], "both": [0, 3, 8, 13, 15], "within": [0, 1, 2, 3, 15, 16], "space": [0, 15], "individu": [0, 1, 15, 16], "its": [0, 1, 15, 16], "offici": [0, 1, 3, 15, 16], "e": [0, 1, 2, 3, 9, 14, 15, 16, 19, 20], "mail": [0, 15], "post": [0, 15], "social": [0, 15], "media": [0, 15], "account": [0, 15, 19], "act": [0, 15], "appoint": [0, 15], "onlin": [0, 15], "offlin": [0, 15], "event": [0, 15], "represent": [0, 15], "further": [0, 15], "defin": [0, 1, 2, 9, 11, 15, 16, 19], "abus": [0, 15], "otherwis": [0, 3, 15, 19], "report": [0, 1, 15, 16], "contact": [0, 15], "team": [0, 15], "insert": [0, 15], "complaint": [0, 15], "investig": [0, 15], "result": [0, 2, 3, 4, 5, 6, 8, 14, 15, 19, 20], "necessari": [0, 14, 15], "circumst": [0, 15], "oblig": [0, 15], "confidenti": [0, 15], "regard": [0, 15], "incid": [0, 15], "specif": [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 19], "polici": [0, 15], "separ": [0, 1, 2, 15, 16], "who": [0, 1, 15, 16], "good": [0, 3, 15], "faith": [0, 15], "face": [0, 15], "temporari": [0, 15], "repercuss": [0, 15], "determin": [0, 15], "": [0, 2, 3, 8, 10, 14, 15, 19], "leadership": [0, 15], "adapt": [0, 15], "from": [0, 1, 2, 3, 5, 8, 13, 14, 15, 16, 17], "coven": [0, 15], "1": [0, 1, 3, 5, 13, 15, 16, 17, 19, 20], "4": [0, 3, 15, 17, 19], "avail": [0, 3, 14, 15, 19], "http": [0, 1, 3, 8, 15, 16], "org": [0, 15], "document": [1, 2, 16, 20], "github": [1, 3, 4, 5, 6, 8, 9, 11, 12, 13, 14, 16], "packag": [1, 16, 17, 18], "lightweight": [1, 16], "workflow": [1, 3, 4, 16, 17, 18, 19], "manag": [1, 16], "reproduc": [1, 16], "atomist": [1, 16], "can": [1, 2, 3, 5, 9, 14, 16, 19, 20], "transfer": [1, 16], "across": [1, 16, 19], "calcul": [1, 4, 5, 6, 8, 10, 11, 13, 14, 16, 17, 18, 19, 20], "structur": [1, 3, 5, 6, 8, 10, 13, 16, 17, 19], "unix": [1, 16], "system": [1, 16], "By": [1, 16], "built": [1, 3, 8, 10, 16, 19], "own": [1, 2, 16, 19, 20], "recip": [1, 16], "automag": [1, 16], "scale": [1, 7, 8, 12, 16], "them": [1, 2, 3, 16, 19], "local": [1, 16], "slurm": [1, 2, 3, 14, 16, 19], "base": [1, 3, 5, 8, 9, 14, 16, 19, 20], "cluster": [1, 16], "idea": [1, 16], "potenti": [1, 3, 16, 19], "step": [1, 2, 3, 4, 6, 14, 16, 19, 20], "therebi": [1, 16], "allow": [1, 2, 14, 16, 20], "same": [1, 2, 3, 14, 16, 19, 20], "multipl": [1, 3, 4, 6, 14, 16, 17, 19, 20], "code": [1, 2, 16, 17, 19], "alter": [1, 16], "input": [1, 2, 3, 6, 9, 12, 14, 16, 17], "output": [1, 2, 3, 8, 16, 17], "simpl": [1, 2, 16, 19], "consisten": [1, 16], "format": [1, 2, 3, 13, 16, 19], "so": [1, 2, 16, 19], "consist": [1, 3, 16], "analysi": [1, 16], "pipelin": [1, 16], "For": [1, 16, 19], "concret": [1, 16, 19], "how": [1, 2, 16], "achiev": [1, 2, 16], "see": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 19], "custom": [1, 14, 16, 17, 19], "page": [1, 2, 16, 17], "goal": [1, 16], "push": [1, 16], "complex": [1, 3, 16], "etc": [1, 2, 9, 14, 16, 20], "backend": [1, 16], "everydai": [1, 16], "onli": [1, 2, 3, 5, 16, 19], "ha": [1, 2, 16, 19], "handl": [1, 3, 16], "want": [1, 2, 3, 13, 16, 19], "implement": [1, 4, 16, 19], "focu": [1, 16], "scienc": [1, 16], "design": [1, 2, 16], "guid": [1, 2, 16, 19], "principl": [1, 16], "should": [1, 3, 16, 19], "resembl": [1, 16], "boilerpl": [1, 16], "ASE": [1, 2, 3, 8, 9, 10, 16, 19], "much": [1, 2, 16], "possibl": [1, 2, 14, 16], "avoid": [1, 16], "explicitli": [1, 2, 16], "context": [1, 16, 19], "It": [1, 16, 19], "easi": [1, 2, 16], "debug": [1, 3, 4, 16, 19], "part": [1, 2, 16, 19], "larg": [1, 5, 16, 19], "addit": [1, 2, 16, 19], "alwai": [1, 3, 16, 19], "resubmit": [1, 16, 19], "job": [1, 2, 14, 16, 17, 18, 20], "standard": [1, 2, 3, 14, 16, 17, 19, 20], "match": [1, 3, 16, 19], "like": [1, 2, 3, 16, 19], "provid": [1, 3, 5, 8, 12, 14, 16, 19], "api": [1, 3, 16, 17], "progress": [1, 16], "track": [1, 16], "must": [1, 3, 5, 8, 14, 16, 19], "incorpor": [1, 16], "g": [1, 2, 3, 9, 14, 16, 19, 20], "simulatan": [1, 16], "arrai": [1, 3, 8, 14, 16, 19], "block": [1, 16], "noth": [1, 4, 16, 19], "python": [1, 2, 16, 19], "function": [1, 3, 16, 17], "return": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 19], "dictionari": [1, 2, 3, 4, 5, 8, 9, 10, 13, 14, 16, 19], "anyth": [1, 16, 19], "done": [1, 16], "These": [1, 16, 19, 20], "complic": [1, 2, 16, 19], "effici": [1, 2, 16], "extern": [1, 16, 19], "optim": [1, 3, 4, 10, 13, 16, 17, 18], "time": [1, 3, 4, 14, 16, 19], "still": [1, 2, 16, 19, 20], "framework": [1, 2, 16], "friendli": [1, 16], "transit": [1, 16], "sai": [1, 2, 16], "tutori": [1, 2, 3, 8, 16], "pymatgen": [1, 3, 11, 16, 19], "websit": [1, 8, 16], "while": [1, 8, 16], "wrapper": [1, 16], "discourag": [1, 16], "long": [1, 16], "benefit": [1, 16], "out": [1, 3, 9, 16, 19], "box": [1, 16], "independ": [1, 2, 3, 16], "easili": [1, 16], "also": [1, 2, 3, 16, 19, 20], "aim": [1, 16], "robust": [1, 16], "protocol": [1, 16], "directori": [1, 2, 3, 16, 19, 20], "modifi": [1, 2, 3, 16, 19], "applic": [1, 16, 19], "If": [1, 2, 3, 4, 6, 12, 16, 19], "suggest": [1, 16], "improv": [1, 16], "methodologi": [1, 16], "bring": [1, 16], "up": [1, 3, 5, 16, 19], "instruct": [1, 16], "give": [1, 2, 16], "copi": [1, 2, 3, 16], "prefer": [1, 16], "conda": [1, 2, 3, 16, 19], "activ": [1, 2, 16, 19, 20], "n": [1, 2, 3, 16, 19], "3": [1, 3, 8, 9, 16, 17, 19], "9": [1, 16], "Then": [1, 16], "either": [1, 2, 12, 14, 16, 19], "pip": [1, 16], "clone": [1, 16], "sourc": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 19], "might": [1, 16, 19], "some": [1, 2, 3, 6, 16, 19, 20], "minor": [1, 16], "bug": [1, 16], "fix": [1, 2, 16, 19], "pypi": [1, 3, 16], "releas": [1, 3, 16], "easier": [1, 2, 14, 16], "go": [1, 2, 3, 16, 19], "through": [1, 2, 16, 19], "To": [1, 2, 3, 16, 19], "latest": [1, 16], "simpli": [1, 16, 19], "git": [1, 16], "gitlab": [1, 16], "com": [1, 3, 4, 5, 6, 8, 9, 11, 12, 13, 14, 16], "ase": [1, 2, 3, 6, 8, 16, 19], "cd": [1, 16], "battmodel": [1, 16], "choos": [1, 5, 16], "sinc": [1, 16], "ones": [1, 3, 16], "quit": [1, 16], "outdat": [1, 16], "need": [1, 2, 3, 16, 19], "quantum": [1, 16], "espresso": [1, 3, 16, 19], "castep": [1, 16], "similarli": [1, 16, 19], "lammp": [1, 3, 4, 16, 17, 18, 19], "py": [1, 2, 16, 19], "those": [1, 14, 16, 19], "setup": [1, 2, 16, 19], "point": [1, 3, 4, 8, 16, 19], "global": [1, 3, 5, 14, 16, 19], "env_input": [1, 2, 3, 14, 16, 17], "yaml": [1, 2, 3, 14, 16, 17], "calc_input": [1, 2, 3, 5, 14, 16, 17], "favorit": [1, 16], "configur": [1, 2, 16, 19], "commonli": [1, 16], "share": [1, 16], "among": [1, 16], "directli": [1, 2, 3, 16, 19, 20], "specifi": [1, 2, 3, 4, 5, 8, 9, 11, 14, 16, 17, 20], "asim": [1, 2, 16, 17], "execut": [1, 2, 16, 17], "h": [1, 16, 19], "search": [1, 3, 16, 17], "found": [1, 3, 16, 19, 20], "bashrc": [1, 2, 16, 19], "export": [1, 2, 16, 19], "asimtools_env_input": [1, 16, 19], "path": [1, 2, 3, 9, 10, 12, 14, 16, 19], "my": [1, 2, 16, 19], "asimtools_calc_input": [1, 16, 19], "asimtools_asimmodule_dir": [1, 2, 16, 19], "dir": [1, 2, 16], "call": [1, 2, 3, 16, 19], "pytest": [1, 16], "suit": [1, 16], "compon": [1, 16], "test_compon": [1, 16], "run_al": [1, 16], "sh": [1, 16], "Or": [1, 3, 16], "each": [1, 2, 3, 5, 6, 14, 16, 20], "error": [1, 3, 5, 16, 19], "scientif": [1, 16], "valid": [1, 16], "bash": [1, 16], "script": [1, 2, 8, 9, 16, 19], "_slurm": [1, 16], "none": [1, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14, 16], "longer": [1, 16], "than": [1, 2, 5, 12, 16], "minut": [1, 16], "read": [1, 3, 16, 19], "our": [1, 16, 17], "conduct": [1, 16, 17], "process": [1, 2, 5, 16, 17], "pull": [1, 16, 17], "request": [1, 16, 17, 19], "u": [1, 16], "keith": [1, 16], "phuthi": [1, 16], "mkphuthi": [1, 3, 4, 5, 6, 8, 9, 11, 12, 13, 14, 16], "emil": [1, 16], "annevelink": [1, 16], "emilannevelink": [1, 16], "list": [1, 2, 3, 5, 11, 14, 16, 19], "under": [1, 16, 19, 20], "mit": [1, 16], "section": [2, 19], "hous": 2, "integr": 2, "asimtool": [2, 19, 20], "straight": 2, "forward": 2, "continu": 2, "user": [2, 9, 14, 17, 19, 20], "feedback": 2, "hope": 2, "more": [2, 3, 12, 19, 20], "seamless": 2, "As": [2, 19], "asimplifi": 2, "equat": [2, 8], "state": [2, 8], "shown": [2, 19], "understand": 2, "visit": 2, "ultim": 2, "chemic": 2, "speci": 2, "support": 2, "comput": 2, "fulli": 2, "paralleliz": 2, "submiss": 2, "hpc": 2, "just": [2, 3, 19], "few": [2, 19], "given": [2, 3, 7, 8, 10, 19, 20], "below": [2, 3, 19], "import": [2, 3, 17], "bulk": [2, 3, 6, 8, 13, 19], "emt": 2, "eo": [2, 3, 4, 8, 17, 18], "calculate_eo": [2, 8], "db": [2, 3, 8], "connect": [2, 3], "symb": 2, "al": 2, "ni": 2, "cu": [2, 3], "pd": [2, 3], "pt": [2, 3], "au": 2, "atom": [2, 3, 5, 6, 8, 9, 10, 13, 17], "fcc": [2, 3], "calc": [2, 11, 14, 19], "v": 2, "b": [2, 6], "fit": [2, 8], "find": 2, "minimum": 2, "write": [2, 3, 9, 19], "databas": [2, 3, 20], "cell": [2, 3, 6, 8, 12, 13], "get_volum": 2, "get_potential_energi": 2, "bm": 2, "coupl": 2, "here": [2, 4, 6, 19], "difficult": 2, "high": 2, "throughput": 2, "becaus": [2, 19], "chosen": 2, "current": [2, 3, 4, 19], "after": [2, 3, 14, 19, 20], "wa": [2, 3, 4, 6, 19], "expens": 2, "less": [2, 5], "schedul": [2, 14], "perhap": 2, "even": [2, 19], "help": 2, "made": [2, 3], "touch": 2, "thing": 2, "replac": [2, 3], "toi": 2, "empir": 2, "instead": [2, 19], "dft": [2, 20], "smaller": [2, 3], "simpler": 2, "loop": 2, "over": [2, 5, 14, 20], "fewer": 2, "alreadi": [2, 19], "workhors": 2, "easiest": 2, "past": 2, "insid": 2, "name": [2, 3, 9, 19], "def": 2, "ase_eo": 2, "minimu": 2, "immedi": 2, "sim_input": [2, 3, 14, 17, 20], "env_id": [2, 14, 19], "inlin": [2, 19], "workdir": [2, 3, 19], "littl": 2, "bit": 2, "howev": [2, 3], "let": 2, "load_calc": [2, 3, 17, 18, 19], "calc_id": [2, 3, 4, 5, 6, 8, 10, 11, 13, 14, 19, 20], "now": 2, "correctli": 2, "calc_arrai": [2, 3, 4, 17, 18, 20], "iter": [2, 3, 14, 20], "get": [2, 3, 8, 17, 19], "parallel": [2, 5, 8, 19, 20], "imag": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 20], "get_atom": [2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 17, 18, 19], "peasi": 2, "arbitrari": 2, "Of": 2, "cours": 2, "fail": [2, 3, 17, 18], "bad": 2, "send": 2, "log": [2, 3, 19], "checkpoint": 2, "addition": 2, "ad": [2, 19], "clear": [2, 19], "type": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 20], "dict": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19], "str": [2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 19], "db_file": 2, "info": [2, 3], "successfulli": 2, "float": [2, 3, 5, 6, 8, 10], "argon": 2, "lennardjon": [2, 19], "batch": [2, 3, 19], "arg": [2, 3, 11, 13, 19], "builder": [2, 3, 19], "lj_ar": 2, "modul": [2, 17, 18, 19], "lj": [2, 19], "sigma": [2, 19], "54": [2, 19], "epsilon": [2, 19], "0": [2, 3, 5, 6, 8, 9, 10, 13, 19], "00802236": [2, 19], "mode": [2, 19], "use_slurm": [2, 14, 19], "true": [2, 3, 5, 8, 9, 14, 19], "fals": [2, 3, 14, 19], "flag": [2, 19], "precommand": [2, 19], "back": 2, "origin": [2, 7], "problem": [2, 19], "element": 2, "nest": 2, "sim_arrai": [2, 3, 4, 17, 18, 19, 20], "key_sequ": [2, 3, 14], "array_valu": [2, 14], "template_sim_input": [2, 14], "crystalstructur": [2, 3, 19], "access": [2, 3, 14], "full": [2, 5, 9, 19], "move": [2, 19], "refer": [2, 5, 19], "prepend": [2, 19], "abov": [2, 3, 19], "crystal": [2, 19], "lattic": [2, 3, 8, 12], "correspond": 2, "secondary_array_valu": [2, 14], "tell": [2, 19], "id": [2, 3, 5, 14, 19], "0000__al__": 2, "0001__ni__": 2, "label": [2, 3, 14], "valu": [2, 3, 5, 6, 8, 12, 14, 19], "secondary_key_sequ": [2, 14], "0479": 2, "524": 2, "6149": 2, "8907": 2, "0853": 2, "9242": 2, "0782": 2, "perform": [2, 20], "That": [2, 19], "7x5": 2, "35": 2, "benchmark": [3, 4, 17, 18, 20], "pariti": [3, 4, 17, 18], "calc_parity_data": [3, 4, 5, 17], "rmse": [3, 4, 5, 17], "elastic_const": [3, 4, 17, 18], "cubic_energy_expans": [3, 4, 17, 18], "get_strained_atom": [3, 4, 6, 17], "postprocess": [3, 4, 17, 18], "geometry_optim": [3, 4, 6, 11, 13, 17, 18], "ase_cubic_eos_optim": [3, 4, 6, 17, 18], "atom_relax": [3, 4, 11, 13, 17, 18], "cell_relax": [3, 4, 17, 18], "symmetric_cell_relax": [3, 4, 17, 18], "phonon": [3, 4, 17, 18], "ase_phonon": [3, 4, 17, 18], "surface_energi": [3, 4, 17, 18], "get_surface_energi": [3, 4, 11, 17], "transform": [3, 4, 17, 18], "scale_unit_cel": [3, 4, 17, 18], "apply_scal": [3, 4, 12, 17], "vacancy_formation_energi": [3, 4, 17, 18], "chain": [3, 4, 17, 18, 19, 20], "distribut": [3, 4, 17, 18, 19, 20], "image_arrai": [3, 4, 17, 18, 20], "do_noth": [3, 17, 18], "singlepoint": [3, 17, 18, 19], "templat": [3, 9, 14, 17, 18, 19, 20], "tool": [3, 17, 19], "load": [3, 19], "object": [3, 19, 20], "simul": [3, 9, 14, 17, 19], "load_ase_calc": [3, 17, 18], "calc_param": 3, "builtin": 3, "option": [3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 19], "kei": [3, 14, 19], "suppli": [3, 19], "default": [3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 19], "singl": [3, 4, 19], "load_chgnet": [3, 17, 18], "chgnet": [3, 19], "lbl": 3, "gov": 3, "loader": 3, "model": [3, 19], "dynam": 3, "chgnetcalcul": 3, "load_dp": [3, 17, 18], "deep": [3, 19], "deepmodel": 3, "deepmd": 3, "en": 3, "master": 3, "dp": 3, "load_espresso_profil": [3, 17, 18], "qunatum": 3, "22": [3, 19], "older": 3, "forg": 3, "until": [3, 19, 20], "becom": [3, 19], "compat": 3, "remain": 3, "command": [3, 9, 19], "keyword": [3, 19], "fysik": [3, 8], "dtu": [3, 8], "dk": [3, 8], "releasenot": 3, "html": [3, 8], "load_m3gnet": [3, 17, 18], "m3gnet": [3, 19], "matgl": 3, "ext": 3, "m3gnetcalcul": 3, "instanti": [3, 19], "load_mac": [3, 17, 18], "mace": [3, 19], "acesuit": 3, "tab": 3, "ov": 3, "mace_mp": 3, "load_mace_off": [3, 17, 18], "load_nequip": [3, 17, 18], "nequip": [3, 19], "allegro": 3, "mir": 3, "group": 3, "tree": [3, 19], "nequip_calcul": 3, "nequipcalcul": 3, "temin": 3, "author": [3, 4, 5, 6, 8, 9, 11, 12, 13, 14, 17], "class": [3, 8, 19], "chainedjob": [3, 17, 18], "sequenti": 3, "unitjob": [3, 17, 18], "well": [3, 4, 6, 19], "unit": [3, 4, 5, 6, 8, 12], "intern": [3, 14], "gener": [3, 4, 5, 6, 8, 19], "manual": [3, 19], "get_last_output": [3, 17, 18], "last": 3, "termin": [3, 19], "distributedjob": [3, 17, 18], "abil": 3, "simultan": [3, 8, 14], "gen_input_fil": [3, 17, 18], "kwarg": 3, "submit_arrai": [3, 17, 18], "array_max": [3, 14], "env": [3, 14], "submit_job": [3, 17, 18], "lot": 3, "recommend": [3, 14, 19], "abstract": 3, "add_output_fil": [3, 17, 18], "file_dict": 3, "complet": [3, 17, 18, 19], "signal": 3, "start": [3, 17, 18, 19], "discard": [3, 17, 18, 19], "statu": [3, 17], "get_calc_input": [3, 17, 18], "get_env_input": [3, 17, 18], "get_logg": [3, 17, 18], "logfilenam": 3, "logger": 3, "get_output": [3, 17, 18], "get_output_yaml": [3, 17, 18], "get_sim_input": [3, 17, 18], "get_statu": [3, 17, 18], "displai": 3, "tupl": [3, 4, 7, 8], "bool": [3, 8, 9, 19], "check": [3, 17], "get_workdir": [3, 17, 18], "go_to_workdir": [3, 17, 18], "leave_workdir": [3, 17, 18], "goe": [3, 19], "launch": [3, 14, 19], "mkworkdir": [3, 17, 18], "doesn": 3, "t": 3, "set_workdir": [3, 17, 18], "update_calc_input": [3, 17, 18], "new_param": 3, "update_env_input": [3, 17, 18], "update_output": [3, 17, 18], "output_upd": 3, "update_sim_input": [3, 17, 18], "update_statu": [3, 17, 18], "specifici": 3, "run": [3, 4, 6, 9, 14, 17, 20], "requir": [3, 8, 9, 19], "write_calc_input": 3, "write_env_input": 3, "write_imag": 3, "gen_run_command": [3, 17, 18], "create_unitjob": [3, 17, 18], "helper": 3, "mostli": [3, 19], "load_job_from_directori": [3, 17, 18], "data": [3, 5, 9, 14], "change_dict_valu": [3, 17, 18], "d": [3, 19], "new_valu": 3, "sequenc": [3, 5, 6, 8, 10, 11, 12, 13, 14], "return_copi": 3, "_type_": 3, "old": 3, "order": [3, 14], "whether": [3, 8, 9, 19], "place": 3, "pair": [3, 14, 19], "check_if_slurm_job_is_run": [3, 17, 18], "slurm_job_id": 3, "int": [3, 4, 5, 8, 10, 13, 14], "job_id": [3, 19], "union": [3, 11, 14], "find_nth": [3, 17, 18], "haystack": 3, "needl": 3, "index": [3, 5, 13, 17, 19], "nth": 3, "occur": 3, "substr": 3, "string": [3, 14, 19], "image_fil": [3, 19], "repeat": [3, 10, 13, 19, 20], "rattle_stdev": [3, 19], "mp_id": [3, 19], "user_api_kei": [3, 19], "return_typ": 3, "config": [3, 19], "readabl": [3, 19], "extra": 3, "argument": [3, 8, 9, 14, 19, 20], "supercel": [3, 10, 13, 19], "stdev": [3, 19], "rattl": [3, 19], "distanc": 3, "perturb": 3, "materi": [3, 19], "fetch": 3, "three": 3, "molecul": 3, "h2o": 3, "symbol": [3, 19], "oh2": 3, "pbc": 3, "805": 3, "cubic": [3, 6, 19], "ar4": 3, "fcc100": [3, 19], "fe": [3, 19], "vacuum": [3, 19], "8": [3, 19], "5": [3, 4, 8, 10, 17], "cu80": 3, "10": [3, 19], "210621920333747": 3, "23": [3, 8, 9, 19], "tag": 3, "io": [3, 19], "cif": [3, 19], "h2": 3, "xyz": [3, 4, 11, 12, 19], "extxyz": [3, 19], "pick": 3, "li_bulk": 3, "li": [3, 19], "poscar": 3, "vasp": 3, "li27": 3, "235": 3, "2": [3, 17, 19, 20], "01": [3, 6, 10, 19], "li8": 3, "49": 3, "745": 3, "therefor": 3, "expand": 3, "96": 3, "summari": [3, 19], "download": [3, 19], "mp": [3, 19], "primit": [3, 19], "convent": 3, "14": [3, 19], "conventional_unit_cel": [3, 19], "abc": 3, "7718585822512662": 3, "get_axis_lim": [3, 17, 18], "x": 3, "y": [3, 5], "pad": 3, "estim": 3, "limit": 3, "plot": [3, 5, 7, 8, 10], "axi": 3, "tri": 3, "dotfil": 3, "empti": [3, 7, 10, 13, 19], "present": 3, "direcori": 3, "preced": 3, "get_imag": [3, 5, 7, 14, 17, 18, 19], "pattern": [3, 14, 19], "skip_fail": 3, "A": [3, 19], "rais": [3, 12], "ignor": [3, 19], "ioerror": 3, "wildcard": [3, 19], "charact": 3, "captur": [3, 19], "select": 3, "append": [3, 19], "n2": 3, "notic": 3, "don": 3, "guess": 3, "bulk_cu": 3, "cfg": [3, 19], "bulk_f": 3, "bulk_pt": 3, "mass": [3, 9], "momenta": 3, "48549": 3, "8284876429214074": 3, "3433456351179887": 3, "171653675382785": 3, "0294079014797743": 3, "spacegroup_kind": 3, "logfil": 3, "fstr": 3, "asctim": 3, "funcnam": 3, "levelnam": 3, "messag": 3, "get_nth_label": [3, 17, 18], "get_str_btn": [3, 17, 18], "pathlik": 3, "s1": 3, "s2": 3, "start_index": 3, "between": [3, 5, 19], "extract": [3, 8, 14], "desir": 3, "begin": 3, "encount": 3, "join_nam": [3, 17, 18], "join": 3, "hyphen": 3, "neatli": 3, "new_db": [3, 17, 18], "dbname": 3, "overwrit": [3, 19], "parse_slic": [3, 17, 18], "slice": 3, "pars": 3, "stop": 3, "read_yaml": [3, 17, 18], "yaml_path": 3, "strip_symbol": [3, 17, 18], "filenam": 3, "strip": 3, "write_csv_from_dict": [3, 17, 18], "fname": 3, "column": 3, "header": 3, "datafram": 3, "tabul": 3, "csv": 3, "length": [3, 14], "panda": 3, "to_csv": 3, "write_yaml": [3, 17, 18], "yaml_dict": 3, "doe": 4, "durat": 4, "sleep": 4, "60": 4, "slept": 4, "energi": [4, 5, 8, 11, 13, 19], "properti": [4, 5, 8], "forc": [4, 5, 8, 19, 20], "prefix": [4, 8, 14], "evalu": [4, 5], "stress": [4, 5, 8], "describ": [4, 6, 19], "briefli": [4, 6], "restructuredtext": [4, 6], "autodoc": [4, 6], "cite": [4, 6], "paper": [4, 6], "where": [4, 6, 14, 19], "introduc": [4, 6], "collect": 5, "statist": 5, "compar": [5, 12], "dataset": 5, "subset": 5, "force_prob": 5, "fraction": 5, "speed": 5, "sampl": 5, "subsampl": 5, "randomli": 5, "predict": 5, "nproc": 5, "mev": 5, "datapoint": 5, "ev": [5, 8], "kcal": 5, "mol": 5, "yhat": 5, "root": [5, 19], "mean": 5, "squar": 5, "delta": [6, 10], "0075": 6, "005": 6, "ase_cubic_eos_arg": 6, "modulu": [6, 8], "c11": 6, "c12": 6, "c44": 6, "elast": 6, "constant": 6, "symmetri": [6, 8], "strain": 6, "direct": [6, 19], "00": 6, "argumen": 6, "accord": [6, 19], "xauthor": 7, "initial_imag": 7, "initi": [7, 9, 19], "equilibrium": 8, "volum": [8, 12], "npoint": 8, "eos_str": 8, "sj": 8, "ep": 8, "04": 8, "sepecifi": 8, "factor": [8, 12], "relax": [8, 10], "gpmin": 8, "fmax": 8, "02": 8, "tomic": 8, "converg": [8, 20], "threshold": 8, "bfg": 8, "002": 8, "mask": 8, "maximum": [8, 14], "aa": 8, "constrain": 8, "deform": 8, "final": [8, 9, 17], "coordin": 8, "003": 8, "optimizer_arg": 8, "expcellfilter_arg": 8, "constraint": 8, "expcellfilt": 8, "retain": 8, "48gpa": 8, "fixsymmetry_arg": 8, "fixsymmetri": 8, "atom_styl": 9, "lmp_cmd": 9, "lmp": 9, "placehold": 9, "put": 9, "style": 9, "kpt": [10, 19], "20": 10, "spectrum": 10, "bz": 10, "surfac": [11, 19], "slab": 11, "generate_all_slab": 11, "bulk_e_per_atom": 11, "miller": 11, "atom_relax_arg": [11, 13], "generate_all_slabs_arg": 11, "indic": 11, "form": 11, "_description_": 11, "produc": [12, 19], "old_atom": 12, "logspac": 12, "linspac": [12, 14], "scale_bi": 12, "np": 12, "valueerror": 12, "monovac": 13, "vacancy_index": 13, "optimize_arg": 13, "subsim_input": 14, "template_calc_id": 14, "file_pattern": 14, "linspace_arg": 14, "arange_arg": 14, "label_prefix": 14, "str_btn_arg": 14, "param": 14, "numpi": 14, "arang": 14, "mani": [14, 19, 20], "tandem": 14, "anoth": 14, "overrid": 14, "inpout": 14, "scnario": 14, "simultant": 14, "total": 14, "task": [14, 19], "resourc": 14, "philosophi": 17, "contribut": 17, "licens": 17, "usag": 17, "restart": 17, "cheap": 17, "wrap": 17, "cleanup": [17, 19], "6": 17, "pledg": 17, "respons": 17, "scope": 17, "enforc": 17, "attribut": 17, "content": 18, "written": 19, "yourself": 19, "c": 19, "automat": 19, "rare": 19, "most": [19, 20], "ever": 19, "explain": 19, "pythonpath": 19, "hesit": 19, "confus": 19, "phase": 19, "kind": 19, "run_prefix": 19, "run_suffix": 19, "flag1": 19, "flag2": 19, "precommand1": 19, "precommand2": 19, "postcommand": 19, "postcommand1": 19, "postcommand2": 19, "consol": 19, "batch_job": 19, "mem": 19, "per": 19, "cpu": 19, "2g": 19, "deactiv": 19, "interactive_job": 19, "gre": 19, "gpu": 19, "highest": 19, "repeatedli": 19, "look": 19, "uniqu": 19, "identifi": 19, "being": 19, "alloc": 19, "salloc": 19, "sbatch": 19, "mpirun": 19, "invok": 19, "equival": 19, "my_asimmodul": 19, "txt": 19, "common": [19, 20], "farther": 19, "down": 19, "arg1": 19, "value_1": 19, "gpaw": 19, "xc": 19, "pbe": 19, "gpaw_output": 19, "univers": 19, "mace32": 19, "medium": 19, "use_devic": 19, "cuda": 19, "assumpt": 19, "v3": 19, "newer": 19, "profil": 19, "espressoprofil": 19, "stabl": 19, "field": [19, 20], "ref": 19, "run_postfix": 19, "clean": 19, "bulki": 19, "tmp": 19, "wavefunct": 19, "minim": 19, "my_env_var": 19, "arg2": 19, "value_2": 19, "dot": 19, "notat": 19, "rel": 19, "asim_pl": 19, "veri": 19, "wherea": 19, "entir": 19, "whatev": 19, "unif": 19, "descript": 19, "exactli": 19, "bcc": 19, "period": 19, "3x3x3": 19, "itself": 19, "usual": 19, "especi": 19, "previou": 19, "certain": 19, "atoms1": 19, "atoms2": 19, "major": 19, "fact": 19, "control": 19, "verbos": 19, "particular": 19, "status": 19, "self": 19, "explanatori": 19, "never": 19, "irredem": 19, "delet": 19, "ok": 19, "downstream": 19, "importantli": 19, "purpos": 19, "success": 19, "end_tim": 19, "2023": 19, "08": 19, "28": 19, "21": 19, "50": 19, "51": 19, "368025": 19, "13": 19, "77302319846367": 19, "scinglepoint": 19, "image_output": 19, "372919": 19, "start_tim": 19, "46": 19, "188300": 19, "29": 19, "55": 19, "06": 19, "extrem": 19, "lead": 19, "traceback": 19, "caus": 19, "failur": 19, "stderr": 19, "backtrac": 19, "stdout": 19, "safeti": 19, "measur": 19, "catch": 19, "print": 19, "unless": 19, "statement": 19, "input_imag": 19, "artifact": 19, "visual": 19, "flexibl": 19, "slurm_stdout": 19, "a_j": 19, "slurm_stderr": 19, "whose": 19, "mistak": 19, "resolv": 19, "why": 19, "rerun": 19, "skip": 19, "caution": 19, "mere": 19, "offer": 20, "substitut": 20, "except": 20, "cutoff": 20, "multi": 20, "condit": 20, "reach": 20, "serv": 20}, "objects": {"": [[3, 0, 0, "-", "asimtools"]], "asimtools": [[4, 0, 0, "-", "asimmodules"], [3, 0, 0, "-", "calculators"], [3, 0, 0, "-", "job"], [3, 0, 0, "-", "utils"]], "asimtools.asimmodules": [[5, 0, 0, "-", "benchmarking"], [4, 0, 0, "-", "do_nothing"], [6, 0, 0, "-", "elastic_constants"], [7, 0, 0, "-", "eos"], [8, 0, 0, "-", "geometry_optimization"], [9, 0, 0, "-", "lammps"], [10, 0, 0, "-", "phonons"], [4, 0, 0, "-", "singlepoint"], [11, 0, 0, "-", "surface_energies"], [4, 0, 0, "-", "template"], [12, 0, 0, "-", "transformations"], [13, 0, 0, "-", "vacancy_formation_energy"], [14, 0, 0, "-", "workflows"]], "asimtools.asimmodules.benchmarking": [[5, 0, 0, "-", "parity"]], "asimtools.asimmodules.benchmarking.parity": [[5, 1, 1, "", "calc_parity_data"], [5, 1, 1, "", "parity"], [5, 1, 1, "", "rmse"]], "asimtools.asimmodules.do_nothing": [[4, 1, 1, "", "do_nothing"]], "asimtools.asimmodules.elastic_constants": [[6, 0, 0, "-", "cubic_energy_expansion"]], "asimtools.asimmodules.elastic_constants.cubic_energy_expansion": [[6, 1, 1, "", "cubic_energy_expansion"], [6, 1, 1, "", "get_strained_atoms"]], "asimtools.asimmodules.eos": [[7, 0, 0, "-", "postprocess"]], "asimtools.asimmodules.eos.postprocess": [[7, 1, 1, "", "postprocess"]], "asimtools.asimmodules.geometry_optimization": [[8, 0, 0, "-", "ase_cubic_eos_optimization"], [8, 0, 0, "-", "atom_relax"], [8, 0, 0, "-", "cell_relax"], [8, 0, 0, "-", "optimize"], [8, 0, 0, "-", "symmetric_cell_relax"]], "asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization": [[8, 1, 1, "", "ase_cubic_eos_optimization"]], "asimtools.asimmodules.geometry_optimization.atom_relax": [[8, 1, 1, "", "atom_relax"]], "asimtools.asimmodules.geometry_optimization.cell_relax": [[8, 1, 1, "", "cell_relax"]], "asimtools.asimmodules.geometry_optimization.optimize": [[8, 1, 1, "", "optimize"]], "asimtools.asimmodules.geometry_optimization.symmetric_cell_relax": [[8, 1, 1, "", "symmetric_cell_relax"]], "asimtools.asimmodules.lammps": [[9, 0, 0, "-", "lammps"]], "asimtools.asimmodules.lammps.lammps": [[9, 1, 1, "", "lammps"]], "asimtools.asimmodules.phonons": [[10, 0, 0, "-", "ase_phonons"]], "asimtools.asimmodules.phonons.ase_phonons": [[10, 1, 1, "", "ase_phonons"]], "asimtools.asimmodules.singlepoint": [[4, 1, 1, "", "singlepoint"]], "asimtools.asimmodules.surface_energies": [[11, 0, 0, "-", "surface_energies"]], "asimtools.asimmodules.surface_energies.surface_energies": [[11, 1, 1, "", "get_surface_energy"], [11, 1, 1, "", "surface_energies"]], "asimtools.asimmodules.template": [[4, 1, 1, "", "template"]], "asimtools.asimmodules.transformations": [[12, 0, 0, "-", "scale_unit_cells"]], "asimtools.asimmodules.transformations.scale_unit_cells": [[12, 1, 1, "", "apply_scale"], [12, 1, 1, "", "scale_unit_cells"]], "asimtools.asimmodules.vacancy_formation_energy": [[13, 0, 0, "-", "vacancy_formation_energy"]], "asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy": [[13, 1, 1, "", "vacancy_formation_energy"]], "asimtools.asimmodules.workflows": [[14, 0, 0, "-", "calc_array"], [14, 0, 0, "-", "chained"], [14, 0, 0, "-", "distributed"], [14, 0, 0, "-", "image_array"], [14, 0, 0, "-", "sim_array"]], "asimtools.asimmodules.workflows.calc_array": [[14, 1, 1, "", "calc_array"]], "asimtools.asimmodules.workflows.chained": [[14, 1, 1, "", "chained"]], "asimtools.asimmodules.workflows.distributed": [[14, 1, 1, "", "distributed"]], "asimtools.asimmodules.workflows.image_array": [[14, 1, 1, "", "image_array"]], "asimtools.asimmodules.workflows.sim_array": [[14, 1, 1, "", "sim_array"]], "asimtools.calculators": [[3, 1, 1, "", "load_ase_calc"], [3, 1, 1, "", "load_calc"], [3, 1, 1, "", "load_chgnet"], [3, 1, 1, "", "load_dp"], [3, 1, 1, "", "load_espresso_profile"], [3, 1, 1, "", "load_m3gnet"], [3, 1, 1, "", "load_mace"], [3, 1, 1, "", "load_mace_off"], [3, 1, 1, "", "load_nequip"]], "asimtools.job": [[3, 2, 1, "", "ChainedJob"], [3, 2, 1, "", "DistributedJob"], [3, 2, 1, "", "Job"], [3, 2, 1, "", "UnitJob"], [3, 1, 1, "", "create_unitjob"], [3, 1, 1, "", "load_job_from_directory"]], "asimtools.job.ChainedJob": [[3, 3, 1, "", "get_last_output"], [3, 3, 1, "", "submit"]], "asimtools.job.DistributedJob": [[3, 3, 1, "", "gen_input_files"], [3, 3, 1, "", "submit"], [3, 3, 1, "", "submit_array"], [3, 3, 1, "", "submit_jobs"]], "asimtools.job.Job": [[3, 3, 1, "", "add_output_files"], [3, 3, 1, "", "complete"], [3, 3, 1, "", "discard"], [3, 3, 1, "", "fail"], [3, 3, 1, "", "get_calc_input"], [3, 3, 1, "", "get_env_input"], [3, 3, 1, "", "get_logger"], [3, 3, 1, "", "get_output"], [3, 3, 1, "", "get_output_yaml"], [3, 3, 1, "", "get_sim_input"], [3, 3, 1, "", "get_status"], [3, 3, 1, "", "get_workdir"], [3, 3, 1, "", "go_to_workdir"], [3, 3, 1, "", "leave_workdir"], [3, 3, 1, "", "mkworkdir"], [3, 3, 1, "", "set_workdir"], [3, 3, 1, "", "start"], [3, 3, 1, "", "update_calc_input"], [3, 3, 1, "", "update_env_input"], [3, 3, 1, "", "update_output"], [3, 3, 1, "", "update_sim_input"], [3, 3, 1, "", "update_status"]], "asimtools.job.UnitJob": [[3, 3, 1, "", "gen_input_files"], [3, 3, 1, "", "gen_run_command"], [3, 3, 1, "", "submit"]], "asimtools.utils": [[3, 1, 1, "", "change_dict_value"], [3, 1, 1, "", "change_dict_values"], [3, 1, 1, "", "check_if_slurm_job_is_running"], [3, 1, 1, "", "find_nth"], [3, 1, 1, "", "get_atoms"], [3, 1, 1, "", "get_axis_lims"], [3, 1, 1, "", "get_calc_input"], [3, 1, 1, "", "get_env_input"], [3, 1, 1, "", "get_images"], [3, 1, 1, "", "get_logger"], [3, 1, 1, "", "get_nth_label"], [3, 1, 1, "", "get_str_btn"], [3, 1, 1, "", "join_names"], [3, 1, 1, "", "new_db"], [3, 1, 1, "", "parse_slice"], [3, 1, 1, "", "read_yaml"], [3, 1, 1, "", "strip_symbols"], [3, 1, 1, "", "write_csv_from_dict"], [3, 1, 1, "", "write_yaml"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"]}, "titleterms": {"contribut": [0, 1, 15, 16], "pull": [0, 15], "request": [0, 15], "process": [0, 15], "code": [0, 15], "conduct": [0, 15], "our": [0, 15], "pledg": [0, 15], "standard": [0, 15], "respons": [0, 15], "scope": [0, 15], "enforc": [0, 15], "attribut": [0, 15], "atom": [1, 16, 19], "simul": [1, 2, 16], "tool": [1, 16, 20], "develop": [1, 2, 16], "philosophi": [1, 16], "user": [1, 16], "experi": [1, 16], "get": [1, 16], "start": [1, 16], "instal": [1, 16], "asimtool": [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], "run": [1, 2, 16, 19], "test": [1, 2, 16], "author": [1, 16], "licens": [1, 16], "custom": 2, "asimmodul": [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19], "1": 2, "build": 2, "cheap": 2, "calcul": [2, 3], "2": 2, "wrap": 2, "function": [2, 19], "3": 2, "make": 2, "us": [2, 20], "ani": 2, "4": 2, "structur": 2, "5": 2, "final": 2, "cleanup": 2, "6": 2, "multipl": 2, "workflow": [2, 14, 20], "packag": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "modul": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "job": [3, 19], "util": 3, "exampl": 3, "content": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17], "do_noth": 4, "singlepoint": 4, "templat": 4, "benchmark": 5, "pariti": 5, "elastic_const": 6, "cubic_energy_expans": 6, "eo": 7, "postprocess": 7, "geometry_optim": 8, "ase_cubic_eos_optim": 8, "atom_relax": 8, "cell_relax": 8, "optim": 8, "symmetric_cell_relax": 8, "lammp": 9, "phonon": 10, "ase_phonon": 10, "surface_energi": 11, "transform": 12, "scale_unit_cel": 12, "vacancy_formation_energi": 13, "calc_arrai": 14, "chain": 14, "distribut": 14, "image_arrai": 14, "sim_arrai": 14, "readm": 16, "welcom": 17, "": 17, "document": 17, "indic": 17, "tabl": 17, "an": 19, "exist": 19, "input": 19, "file": 19, "env_input": 19, "yaml": 19, "calc_input": 19, "sim_input": 19, "specifi": 19, "imag": 19, "usag": 19, "asim": 19, "execut": 19, "output": 19, "check": 19, "statu": 19, "restart": 19, "fail": 19, "import": 19, "from": 19, "api": 19, "built": 20}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"Contributing": [[0, "contributing"], [1, "contributing"], [15, "contributing"], [16, "contributing"]], "Pull Request Process": [[0, "pull-request-process"], [15, "pull-request-process"]], "Code of Conduct": [[0, "code-of-conduct"], [15, "code-of-conduct"]], "Our Pledge": [[0, "our-pledge"], [15, "our-pledge"]], "Our Standards": [[0, "our-standards"], [15, "our-standards"]], "Our Responsibilities": [[0, "our-responsibilities"], [15, "our-responsibilities"]], "Scope": [[0, "scope"], [15, "scope"]], "Enforcement": [[0, "enforcement"], [15, "enforcement"]], "Attribution": [[0, "attribution"], [15, "attribution"]], "Atomic SIMulation Tools": [[1, "atomic-simulation-tools"], [16, "atomic-simulation-tools"]], "Developer philosophy": [[1, "developer-philosophy"], [16, "developer-philosophy"]], "Philosophy on User Experience": [[1, "philosophy-on-user-experience"], [16, "philosophy-on-user-experience"]], "Getting Started": [[1, "getting-started"], [16, "getting-started"]], "Installing ASIMTools": [[1, "installing-asimtools"], [16, "installing-asimtools"]], "Running the tests": [[1, "running-the-tests"], [16, "running-the-tests"]], "Authors": [[1, "authors"], [16, "authors"]], "License": [[1, "license"], [16, "license"]], "Developing Custom Asimmodules": [[2, "developing-custom-asimmodules"]], "1. Build and test with a cheap calculator": [[2, "build-and-test-with-a-cheap-calculator"]], "2. Wrap in a function": [[2, "wrap-in-a-function"]], "3. Make the asimmodule use any calculator": [[2, "make-the-asimmodule-use-any-calculator"]], "4. Make the asimmodule use any structure": [[2, "make-the-asimmodule-use-any-structure"]], "5. Final cleanup": [[2, "final-cleanup"]], "6. Running multiple simulations in a workflow": [[2, "running-multiple-simulations-in-a-workflow"]], "asimtools package": [[3, "asimtools-package"]], "asimtools.calculators module": [[3, "module-asimtools.calculators"]], "asimtools.job module": [[3, "module-asimtools.job"]], "asimtools.utils module": [[3, "module-asimtools.utils"]], "Examples": [[3, "examples"], [3, "id1"]], "Module contents": [[3, "module-asimtools"], [4, "module-asimtools.asimmodules"], [5, "module-asimtools.asimmodules.benchmarking"], [6, "module-asimtools.asimmodules.elastic_constants"], [7, "module-asimtools.asimmodules.eos"], [8, "module-asimtools.asimmodules.geometry_optimization"], [9, "module-asimtools.asimmodules.lammps"], [10, "module-asimtools.asimmodules.phonons"], [11, "module-asimtools.asimmodules.surface_energies"], [12, "module-asimtools.asimmodules.transformations"], [13, "module-asimtools.asimmodules.vacancy_formation_energy"], [14, "module-asimtools.asimmodules.workflows"]], "asimtools.asimmodules package": [[4, "asimtools-asimmodules-package"]], "asimtools.asimmodules.do_nothing module": [[4, "module-asimtools.asimmodules.do_nothing"]], "asimtools.asimmodules.singlepoint module": [[4, "module-asimtools.asimmodules.singlepoint"]], "asimtools.asimmodules.template module": [[4, "module-asimtools.asimmodules.template"]], "asimtools.asimmodules.benchmarking package": [[5, "asimtools-asimmodules-benchmarking-package"]], "asimtools.asimmodules.benchmarking.parity module": [[5, "module-asimtools.asimmodules.benchmarking.parity"]], "asimtools.asimmodules.elastic_constants package": [[6, "asimtools-asimmodules-elastic-constants-package"]], "asimtools.asimmodules.elastic_constants.cubic_energy_expansion module": [[6, "module-asimtools.asimmodules.elastic_constants.cubic_energy_expansion"]], "asimtools.asimmodules.eos package": [[7, "asimtools-asimmodules-eos-package"]], "asimtools.asimmodules.eos.postprocess module": [[7, "module-asimtools.asimmodules.eos.postprocess"]], "asimtools.asimmodules.geometry_optimization package": [[8, "asimtools-asimmodules-geometry-optimization-package"]], "asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization module": [[8, "module-asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization"]], "asimtools.asimmodules.geometry_optimization.atom_relax module": [[8, "module-asimtools.asimmodules.geometry_optimization.atom_relax"]], "asimtools.asimmodules.geometry_optimization.cell_relax module": [[8, "module-asimtools.asimmodules.geometry_optimization.cell_relax"]], "asimtools.asimmodules.geometry_optimization.optimize module": [[8, "module-asimtools.asimmodules.geometry_optimization.optimize"]], "asimtools.asimmodules.geometry_optimization.symmetric_cell_relax module": [[8, "module-asimtools.asimmodules.geometry_optimization.symmetric_cell_relax"]], "asimtools.asimmodules.lammps package": [[9, "asimtools-asimmodules-lammps-package"]], "asimtools.asimmodules.lammps.lammps module": [[9, "module-asimtools.asimmodules.lammps.lammps"]], "asimtools.asimmodules.phonons package": [[10, "asimtools-asimmodules-phonons-package"]], "asimtools.asimmodules.phonons.ase_phonons module": [[10, "module-asimtools.asimmodules.phonons.ase_phonons"]], "asimtools.asimmodules.surface_energies package": [[11, "asimtools-asimmodules-surface-energies-package"]], "asimtools.asimmodules.surface_energies.surface_energies module": [[11, "module-asimtools.asimmodules.surface_energies.surface_energies"]], "asimtools.asimmodules.transformations package": [[12, "asimtools-asimmodules-transformations-package"]], "asimtools.asimmodules.transformations.scale_unit_cells module": [[12, "module-asimtools.asimmodules.transformations.scale_unit_cells"]], "asimtools.asimmodules.vacancy_formation_energy package": [[13, "asimtools-asimmodules-vacancy-formation-energy-package"]], "asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy module": [[13, "module-asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy"]], "asimtools.asimmodules.workflows package": [[14, "asimtools-asimmodules-workflows-package"]], "asimtools.asimmodules.workflows.calc_array module": [[14, "module-asimtools.asimmodules.workflows.calc_array"]], "asimtools.asimmodules.workflows.chained module": [[14, "module-asimtools.asimmodules.workflows.chained"]], "asimtools.asimmodules.workflows.distributed module": [[14, "module-asimtools.asimmodules.workflows.distributed"]], "asimtools.asimmodules.workflows.image_array module": [[14, "module-asimtools.asimmodules.workflows.image_array"]], "asimtools.asimmodules.workflows.sim_array module": [[14, "module-asimtools.asimmodules.workflows.sim_array"]], "Contributing to ASIMTools": [[15, "contributing-to-asimtools"]], "README": [[16, "readme"]], "Welcome to asimtools\u2019s documentation!": [[17, "welcome-to-asimtools-s-documentation"]], "Contents:": [[17, null]], "Indices and tables": [[17, "indices-and-tables"]], "asimtools": [[18, "asimtools"]], "Running an Existing Asimmodule": [[19, "running-an-existing-asimmodule"]], "Input files": [[19, "input-files"]], "env_input.yaml": [[19, "env-input-yaml"]], "calc_input.yaml": [[19, "calc-input-yaml"]], "sim_input.yaml": [[19, "sim-input-yaml"]], "Specifying Images/Atoms": [[19, "specifying-images-atoms"]], "Usage of asim-execute and asim-run": [[19, "usage-of-asim-execute-and-asim-run"]], "Output files": [[19, "output-files"]], "Checking job status and Restarting failed jobs": [[19, "checking-job-status-and-restarting-failed-jobs"]], "Importing functions from asimmodules and the API": [[19, "importing-functions-from-asimmodules-and-the-api"]], "Using built-in workflow tools": [[20, "using-built-in-workflow-tools"]]}, "indexentries": {"chainedjob (class in asimtools.job)": [[3, "asimtools.job.ChainedJob"]], "distributedjob (class in asimtools.job)": [[3, "asimtools.job.DistributedJob"]], "job (class in asimtools.job)": [[3, "asimtools.job.Job"]], "unitjob (class in asimtools.job)": [[3, "asimtools.job.UnitJob"]], "add_output_files() (asimtools.job.job method)": [[3, "asimtools.job.Job.add_output_files"]], "asimtools": [[3, "module-asimtools"]], "asimtools.calculators": [[3, "module-asimtools.calculators"]], "asimtools.job": [[3, "module-asimtools.job"]], "asimtools.utils": [[3, "module-asimtools.utils"]], "change_dict_value() (in module asimtools.utils)": [[3, "asimtools.utils.change_dict_value"]], "change_dict_values() (in module asimtools.utils)": [[3, "asimtools.utils.change_dict_values"]], "check_if_slurm_job_is_running() (in module asimtools.utils)": [[3, "asimtools.utils.check_if_slurm_job_is_running"]], "complete() (asimtools.job.job method)": [[3, "asimtools.job.Job.complete"]], "create_unitjob() (in module asimtools.job)": [[3, "asimtools.job.create_unitjob"]], "discard() (asimtools.job.job method)": [[3, "asimtools.job.Job.discard"]], "fail() (asimtools.job.job method)": [[3, "asimtools.job.Job.fail"]], "find_nth() (in module asimtools.utils)": [[3, "asimtools.utils.find_nth"]], "gen_input_files() (asimtools.job.distributedjob method)": [[3, "asimtools.job.DistributedJob.gen_input_files"]], "gen_input_files() (asimtools.job.unitjob method)": [[3, "asimtools.job.UnitJob.gen_input_files"]], "gen_run_command() (asimtools.job.unitjob method)": [[3, "asimtools.job.UnitJob.gen_run_command"]], "get_atoms() (in module asimtools.utils)": [[3, "asimtools.utils.get_atoms"]], "get_axis_lims() (in module asimtools.utils)": [[3, "asimtools.utils.get_axis_lims"]], "get_calc_input() (asimtools.job.job method)": [[3, "asimtools.job.Job.get_calc_input"]], "get_calc_input() (in module asimtools.utils)": [[3, "asimtools.utils.get_calc_input"]], "get_env_input() (asimtools.job.job method)": [[3, "asimtools.job.Job.get_env_input"]], "get_env_input() (in module asimtools.utils)": [[3, "asimtools.utils.get_env_input"]], "get_images() (in module asimtools.utils)": [[3, "asimtools.utils.get_images"]], "get_last_output() (asimtools.job.chainedjob method)": [[3, "asimtools.job.ChainedJob.get_last_output"]], "get_logger() (asimtools.job.job method)": [[3, "asimtools.job.Job.get_logger"]], "get_logger() (in module asimtools.utils)": [[3, "asimtools.utils.get_logger"]], "get_nth_label() (in module asimtools.utils)": [[3, "asimtools.utils.get_nth_label"]], "get_output() (asimtools.job.job method)": [[3, "asimtools.job.Job.get_output"]], "get_output_yaml() (asimtools.job.job method)": [[3, "asimtools.job.Job.get_output_yaml"]], "get_sim_input() (asimtools.job.job method)": [[3, "asimtools.job.Job.get_sim_input"]], "get_status() (asimtools.job.job method)": [[3, "asimtools.job.Job.get_status"]], "get_str_btn() (in module asimtools.utils)": [[3, "asimtools.utils.get_str_btn"]], "get_workdir() (asimtools.job.job method)": [[3, "asimtools.job.Job.get_workdir"]], "go_to_workdir() (asimtools.job.job method)": [[3, "asimtools.job.Job.go_to_workdir"]], "join_names() (in module asimtools.utils)": [[3, "asimtools.utils.join_names"]], "leave_workdir() (asimtools.job.job method)": [[3, "asimtools.job.Job.leave_workdir"]], "load_ase_calc() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_ase_calc"]], "load_calc() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_calc"]], "load_chgnet() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_chgnet"]], "load_dp() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_dp"]], "load_espresso_profile() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_espresso_profile"]], "load_job_from_directory() (in module asimtools.job)": [[3, "asimtools.job.load_job_from_directory"]], "load_m3gnet() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_m3gnet"]], "load_mace() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_mace"]], "load_mace_off() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_mace_off"]], "load_nequip() (in module asimtools.calculators)": [[3, "asimtools.calculators.load_nequip"]], "mkworkdir() (asimtools.job.job method)": [[3, "asimtools.job.Job.mkworkdir"]], "module": [[3, "module-asimtools"], [3, "module-asimtools.calculators"], [3, "module-asimtools.job"], [3, "module-asimtools.utils"], [4, "module-asimtools.asimmodules"], [4, "module-asimtools.asimmodules.do_nothing"], [4, "module-asimtools.asimmodules.singlepoint"], [4, "module-asimtools.asimmodules.template"], [5, "module-asimtools.asimmodules.benchmarking"], [5, "module-asimtools.asimmodules.benchmarking.parity"], [6, "module-asimtools.asimmodules.elastic_constants"], [6, "module-asimtools.asimmodules.elastic_constants.cubic_energy_expansion"], [7, "module-asimtools.asimmodules.eos"], [7, "module-asimtools.asimmodules.eos.postprocess"], [8, "module-asimtools.asimmodules.geometry_optimization"], [8, "module-asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization"], [8, "module-asimtools.asimmodules.geometry_optimization.atom_relax"], [8, "module-asimtools.asimmodules.geometry_optimization.cell_relax"], [8, "module-asimtools.asimmodules.geometry_optimization.optimize"], [8, "module-asimtools.asimmodules.geometry_optimization.symmetric_cell_relax"], [9, "module-asimtools.asimmodules.lammps"], [9, "module-asimtools.asimmodules.lammps.lammps"], [10, "module-asimtools.asimmodules.phonons"], [10, "module-asimtools.asimmodules.phonons.ase_phonons"], [11, "module-asimtools.asimmodules.surface_energies"], [11, "module-asimtools.asimmodules.surface_energies.surface_energies"], [12, "module-asimtools.asimmodules.transformations"], [12, "module-asimtools.asimmodules.transformations.scale_unit_cells"], [13, "module-asimtools.asimmodules.vacancy_formation_energy"], [13, "module-asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy"], [14, "module-asimtools.asimmodules.workflows"], [14, "module-asimtools.asimmodules.workflows.calc_array"], [14, "module-asimtools.asimmodules.workflows.chained"], [14, "module-asimtools.asimmodules.workflows.distributed"], [14, "module-asimtools.asimmodules.workflows.image_array"], [14, "module-asimtools.asimmodules.workflows.sim_array"]], "new_db() (in module asimtools.utils)": [[3, "asimtools.utils.new_db"]], "parse_slice() (in module asimtools.utils)": [[3, "asimtools.utils.parse_slice"]], "read_yaml() (in module asimtools.utils)": [[3, "asimtools.utils.read_yaml"]], "set_workdir() (asimtools.job.job method)": [[3, "asimtools.job.Job.set_workdir"]], "start() (asimtools.job.job method)": [[3, "asimtools.job.Job.start"]], "strip_symbols() (in module asimtools.utils)": [[3, "asimtools.utils.strip_symbols"]], "submit() (asimtools.job.chainedjob method)": [[3, "asimtools.job.ChainedJob.submit"]], "submit() (asimtools.job.distributedjob method)": [[3, "asimtools.job.DistributedJob.submit"]], "submit() (asimtools.job.unitjob method)": [[3, "asimtools.job.UnitJob.submit"]], "submit_array() (asimtools.job.distributedjob method)": [[3, "asimtools.job.DistributedJob.submit_array"]], "submit_jobs() (asimtools.job.distributedjob method)": [[3, "asimtools.job.DistributedJob.submit_jobs"]], "update_calc_input() (asimtools.job.job method)": [[3, "asimtools.job.Job.update_calc_input"]], "update_env_input() (asimtools.job.job method)": [[3, "asimtools.job.Job.update_env_input"]], "update_output() (asimtools.job.job method)": [[3, "asimtools.job.Job.update_output"]], "update_sim_input() (asimtools.job.job method)": [[3, "asimtools.job.Job.update_sim_input"]], "update_status() (asimtools.job.job method)": [[3, "asimtools.job.Job.update_status"]], "write_csv_from_dict() (in module asimtools.utils)": [[3, "asimtools.utils.write_csv_from_dict"]], "write_yaml() (in module asimtools.utils)": [[3, "asimtools.utils.write_yaml"]], "asimtools.asimmodules": [[4, "module-asimtools.asimmodules"]], "asimtools.asimmodules.do_nothing": [[4, "module-asimtools.asimmodules.do_nothing"]], "asimtools.asimmodules.singlepoint": [[4, "module-asimtools.asimmodules.singlepoint"]], "asimtools.asimmodules.template": [[4, "module-asimtools.asimmodules.template"]], "do_nothing() (in module asimtools.asimmodules.do_nothing)": [[4, "asimtools.asimmodules.do_nothing.do_nothing"]], "singlepoint() (in module asimtools.asimmodules.singlepoint)": [[4, "asimtools.asimmodules.singlepoint.singlepoint"]], "template() (in module asimtools.asimmodules.template)": [[4, "asimtools.asimmodules.template.template"]], "asimtools.asimmodules.benchmarking": [[5, "module-asimtools.asimmodules.benchmarking"]], "asimtools.asimmodules.benchmarking.parity": [[5, "module-asimtools.asimmodules.benchmarking.parity"]], "calc_parity_data() (in module asimtools.asimmodules.benchmarking.parity)": [[5, "asimtools.asimmodules.benchmarking.parity.calc_parity_data"]], "parity() (in module asimtools.asimmodules.benchmarking.parity)": [[5, "asimtools.asimmodules.benchmarking.parity.parity"]], "rmse() (in module asimtools.asimmodules.benchmarking.parity)": [[5, "asimtools.asimmodules.benchmarking.parity.rmse"]], "asimtools.asimmodules.elastic_constants": [[6, "module-asimtools.asimmodules.elastic_constants"]], "asimtools.asimmodules.elastic_constants.cubic_energy_expansion": [[6, "module-asimtools.asimmodules.elastic_constants.cubic_energy_expansion"]], "cubic_energy_expansion() (in module asimtools.asimmodules.elastic_constants.cubic_energy_expansion)": [[6, "asimtools.asimmodules.elastic_constants.cubic_energy_expansion.cubic_energy_expansion"]], "get_strained_atoms() (in module asimtools.asimmodules.elastic_constants.cubic_energy_expansion)": [[6, "asimtools.asimmodules.elastic_constants.cubic_energy_expansion.get_strained_atoms"]], "asimtools.asimmodules.eos": [[7, "module-asimtools.asimmodules.eos"]], "asimtools.asimmodules.eos.postprocess": [[7, "module-asimtools.asimmodules.eos.postprocess"]], "postprocess() (in module asimtools.asimmodules.eos.postprocess)": [[7, "asimtools.asimmodules.eos.postprocess.postprocess"]], "ase_cubic_eos_optimization() (in module asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization)": [[8, "asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization.ase_cubic_eos_optimization"]], "asimtools.asimmodules.geometry_optimization": [[8, "module-asimtools.asimmodules.geometry_optimization"]], "asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization": [[8, "module-asimtools.asimmodules.geometry_optimization.ase_cubic_eos_optimization"]], "asimtools.asimmodules.geometry_optimization.atom_relax": [[8, "module-asimtools.asimmodules.geometry_optimization.atom_relax"]], "asimtools.asimmodules.geometry_optimization.cell_relax": [[8, "module-asimtools.asimmodules.geometry_optimization.cell_relax"]], "asimtools.asimmodules.geometry_optimization.optimize": [[8, "module-asimtools.asimmodules.geometry_optimization.optimize"]], "asimtools.asimmodules.geometry_optimization.symmetric_cell_relax": [[8, "module-asimtools.asimmodules.geometry_optimization.symmetric_cell_relax"]], "atom_relax() (in module asimtools.asimmodules.geometry_optimization.atom_relax)": [[8, "asimtools.asimmodules.geometry_optimization.atom_relax.atom_relax"]], "cell_relax() (in module asimtools.asimmodules.geometry_optimization.cell_relax)": [[8, "asimtools.asimmodules.geometry_optimization.cell_relax.cell_relax"]], "optimize() (in module asimtools.asimmodules.geometry_optimization.optimize)": [[8, "asimtools.asimmodules.geometry_optimization.optimize.optimize"]], "symmetric_cell_relax() (in module asimtools.asimmodules.geometry_optimization.symmetric_cell_relax)": [[8, "asimtools.asimmodules.geometry_optimization.symmetric_cell_relax.symmetric_cell_relax"]], "asimtools.asimmodules.lammps": [[9, "module-asimtools.asimmodules.lammps"]], "asimtools.asimmodules.lammps.lammps": [[9, "module-asimtools.asimmodules.lammps.lammps"]], "lammps() (in module asimtools.asimmodules.lammps.lammps)": [[9, "asimtools.asimmodules.lammps.lammps.lammps"]], "ase_phonons() (in module asimtools.asimmodules.phonons.ase_phonons)": [[10, "asimtools.asimmodules.phonons.ase_phonons.ase_phonons"]], "asimtools.asimmodules.phonons": [[10, "module-asimtools.asimmodules.phonons"]], "asimtools.asimmodules.phonons.ase_phonons": [[10, "module-asimtools.asimmodules.phonons.ase_phonons"]], "asimtools.asimmodules.surface_energies": [[11, "module-asimtools.asimmodules.surface_energies"]], "asimtools.asimmodules.surface_energies.surface_energies": [[11, "module-asimtools.asimmodules.surface_energies.surface_energies"]], "get_surface_energy() (in module asimtools.asimmodules.surface_energies.surface_energies)": [[11, "asimtools.asimmodules.surface_energies.surface_energies.get_surface_energy"]], "surface_energies() (in module asimtools.asimmodules.surface_energies.surface_energies)": [[11, "asimtools.asimmodules.surface_energies.surface_energies.surface_energies"]], "apply_scale() (in module asimtools.asimmodules.transformations.scale_unit_cells)": [[12, "asimtools.asimmodules.transformations.scale_unit_cells.apply_scale"]], "asimtools.asimmodules.transformations": [[12, "module-asimtools.asimmodules.transformations"]], "asimtools.asimmodules.transformations.scale_unit_cells": [[12, "module-asimtools.asimmodules.transformations.scale_unit_cells"]], "scale_unit_cells() (in module asimtools.asimmodules.transformations.scale_unit_cells)": [[12, "asimtools.asimmodules.transformations.scale_unit_cells.scale_unit_cells"]], "asimtools.asimmodules.vacancy_formation_energy": [[13, "module-asimtools.asimmodules.vacancy_formation_energy"]], "asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy": [[13, "module-asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy"]], "vacancy_formation_energy() (in module asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy)": [[13, "asimtools.asimmodules.vacancy_formation_energy.vacancy_formation_energy.vacancy_formation_energy"]], "asimtools.asimmodules.workflows": [[14, "module-asimtools.asimmodules.workflows"]], "asimtools.asimmodules.workflows.calc_array": [[14, "module-asimtools.asimmodules.workflows.calc_array"]], "asimtools.asimmodules.workflows.chained": [[14, "module-asimtools.asimmodules.workflows.chained"]], "asimtools.asimmodules.workflows.distributed": [[14, "module-asimtools.asimmodules.workflows.distributed"]], "asimtools.asimmodules.workflows.image_array": [[14, "module-asimtools.asimmodules.workflows.image_array"]], "asimtools.asimmodules.workflows.sim_array": [[14, "module-asimtools.asimmodules.workflows.sim_array"]], "calc_array() (in module asimtools.asimmodules.workflows.calc_array)": [[14, "asimtools.asimmodules.workflows.calc_array.calc_array"]], "chained() (in module asimtools.asimmodules.workflows.chained)": [[14, "asimtools.asimmodules.workflows.chained.chained"]], "distributed() (in module asimtools.asimmodules.workflows.distributed)": [[14, "asimtools.asimmodules.workflows.distributed.distributed"]], "image_array() (in module asimtools.asimmodules.workflows.image_array)": [[14, "asimtools.asimmodules.workflows.image_array.image_array"]], "sim_array() (in module asimtools.asimmodules.workflows.sim_array)": [[14, "asimtools.asimmodules.workflows.sim_array.sim_array"]]}}) \ No newline at end of file diff --git a/_build/usage.html b/_build/usage.html deleted file mode 100644 index 9336ffd..0000000 --- a/_build/usage.html +++ /dev/null @@ -1,601 +0,0 @@ - - - - - - - Running an Existing Asimmodule — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Running an Existing Asimmodule

-

This section will guide you through running an already existing asimmodule -whether it be one of the asimmodules provided in the main repository, from the -asimmodule repository or a custom asimmodule you have written yourself.

-

To run a simulation, all you need to do is run either of the following -commands:

-
asim-execute sim_input.yaml -c calc_input.yaml -e env_input.yaml
-
-
-

Providing calc_input.yaml or env_input.yaml is optional. If not -provided, the globally configured files will be used. See env_input.yaml. This -command will automatically run the specified simulation in the correct -directory and environment.

-

In rare cases, you can use the following command:

-
asim-run sim_input.yaml -c calc_input.yaml
-
-
-

This command will run the simulation in the current directory and environment. -For most cases, you will only ever use asim-execute. The differences -between asim-execute and asim-run are explained in -Usage of asim-execute and asim-run.

-

In summary, the steps you need to take to start using any of the in-built -asimmodules, described in detail below, are the following:

-
    -
  1. Install ASIMTools in you python environment or add it to your -PYTHONPATH.

  2. -
  3. Setup your global env_input.yaml and calc_input.yaml and set the -environment variables pointing to them.

  4. -
  5. Write a sim_input.yaml based on the examples provided in the repository. -Do not hesitate to submit an issue if you are confused as we are still in a -testing phase

  6. -
  7. asim-execute!

  8. -
-
-

Input files

-
-

env_input.yaml

-

One can provide an env_input.yaml file that details the kind -of environments in which asimmodules can be run. This file can be provided with -the asim-execute command using the -e flag or set globally. An example of -an env_input.yaml file is given below

-
# template
-env_id:
-  mode:
-    use_slurm: true
-    interactive: false
-    run_prefix: ...
-    run_suffix: ...
-  slurm:
-    flags: [flag1, flag2, ...]
-    precommands: [precommand1, precommand2, ...]
-    postcommands: [postcommand1, postcommand2, ...]
-
-# Concrete examples below
-inline: # Run the asimmodule directly in the console
-  mode:
-    use_slurm: false
-    interactive: true
-
-batch_job: # Submit a batch job using slurm with 2 tasks
-  mode:
-    use_slurm: true
-    interactive: false
-  slurm:
-    flags:
-        - -n 2
-        - --mem-per-cpu=2G
-    precommands:
-        - source ~/.bashrc
-        - conda activate asimtools
-    postcommands:
-        - conda deactivate asimtools
-# Submit an interactive job using slurm, you can use a dictionary
-# for the flags
-interactive_job:
-  mode:
-    use_slurm: true
-    interactive: true
-  slurm:
-    flags:
-      -n: 2
-      --gres: gpu:2
-    precommands:
-      - module load lammps
-
-
-

The highest level key is the env_id which is the one specified in the -sim_input.yaml. An env_input.yaml can have any number of env_id s. -That way you can specify one global file if you use the same environments -repeatedly. You can configure a global config file by setting -the environment variable.

-
export ASIMTOOLS_ENV_INPUT=/path/to/my/global/env_input.yaml
-
-
-

If you do not provide an env_input.yaml and there is no file called -env_input.yaml in the work directory, ASIMTools will look for the -env_id in the global file.

-

The parameters, required, shown in the template section are described below

-
    -
  • env_id: (str) unique key for identifying the environment, env_id in -sim_input.yaml must match one of the env_id s defined in the -env_input.yaml being used.

  • -
  • env_id.mode.use_slurm: (bool) whether or not to request a slurm -allocation to run the asimmodule

  • -
  • env_id.mode.interactive: (bool) whether or not to run the asimmodule -directly in the terminal (using salloc) or to submit a batch job (using -sbatch).

  • -
  • env_id.mode.run_prefix: (str) string to append before running the -asimmodule e.g. if run_prefix=mpirun the asimmodule will be invoked with -the equivalent of mpirun python my_asimmodule.py. run_prefix in -env_input.yaml is always prepended before the one provided by -calc_input.yaml.

  • -
  • env_id.mode.run_suffix: (str) string to append after running the -asimmodule e.g. if run_suffix: ' &> out.txt' is provided, the asimmodule -will be invoked with the equivalent of python my_asimmodule.py &> -out.txt. run_suffix in env_input.yaml is always appended after the -one provided by calc_input.yaml.

  • -
  • env_id.slurm.flags: (list/dict, optional) The slurm flags for the -allocation as a list of flags e.g. [-n 4, -N 1]. One can also specify a -dictionary e.g. '{-n': 4, '-N': 1, '--mem':2G}

  • -
  • env_id.slurm.precommands: (list, optional) Commands to be run/added to -the job script before running the asimmodule. A common use case is loading -a module or activating an environment.

  • -
  • env_id.slurm.postcommands: (list, optional) Commands to be run/added to -the job asimmodule after running the asimmodule. e.g. for file cleanup or -moving files after the job is complete.

  • -
-
-
-

calc_input.yaml

-

The calc_input.yaml is used to configure an ASE calculator. As -above, a global configuration file can be set using

-
export ASIMTOOLS_CALC_INPUT=/path/to/my/global/calc_input.yaml
-
-
-

or provided to asim-execute at run time. Note that if you launch a chained -workflow with asim-run instead of asim-execute, asimmodules farther -down the chain will use the global calc_input.yaml, so always use -asim-execute

-
# Template
-calc_id:
-  name: ...
-  module: ...
-  precommands: [precommand1, ...]
-  postcommands: [postcommand1, ...]
-  run_prefix: ...
-  run_suffix: ...
-  args:
-    arg1: value_1
-    ...
-
-# Concrete examples
-# Here is a simple LJ potential from ASE
-lj:
-  name: LennardJones
-  module: ase.calculators.lj
-  args:
-    sigma: 3.54
-    epsilon: 0.00802236
-
-# GPAW needs a run_prefix to work in parallel using mpirun
-gpaw:
-  name: GPAW
-  module: gpaw.calculator
-  run_prefix: mpirun
-  args:
-    kpts: [2,2,2]
-    h: 0.1
-    xc: PBE
-    txt: gpaw_output.txt
-
-# You can install a universal potential like MACE and define it as well, see
-# asimtools/calculators.py for implemented external calculators. Submit an
-# issue if you want one to be implemented.
-MACE32-medium:
-  name: MACE
-  args:
-    model: medium
-    use_device: cuda
-
-
-

The parameters for the calculators provided directly in ASE are specified under -the assumption that the calculator will be initiated as follows:

-
from module import name
-calc = name(**args)
-
-
-

This works for all calculators defined in ASE v3.22 and below, for newer -versions of ASE, you might need to use the versions that use profiles e.g. use -name: EspressoProfile not name: Espresso until those become stable in -ASE. For externally defined calculators, you can submit an issue and we will -implement it. For example, calculators for NequIP, Deep Potential, MACE, CHGNet -and M3GNet force fields are implemented.

-
    -
  • calc_id: (str) unique key for identifying the calculator, calc_id in -sim_input.yaml must match one of the calc_id s defined in the -provided calc_input.yaml

  • -
  • calc_id.name: (str) Either the name of the class or the reference to one -of the provided external calculators.

  • -
  • calc_id.module: (str) The module from which the calculator class is -imported. e.g. if name=LennardJones and module=ase.calculators.lj, -then the calculator object is imported as from ase.calculators.lj import -LennardJones. This works if the calculator is available in ASE or follows -ASE format for initialization such as GPAW. Any other ASE calculator will -need to have the instantiation defined in :ref:calculators.py

  • -
  • calc_id.mode.run_prefix: (str) string to append before running the -asimmodule e.g. if run_prefix=mpirun the asimmodule will be invoked with -the equivalent of mpirun python my_asimmodule.py. run_prefix in -env_input.yaml is always prepended before the one provided by -calc_input.yaml.

  • -
  • calc_id.mode.run_suffix: (str) string to append after running the -asimmodule e.g. if run_postfix=' &> out.txt' the asimmodule will be -invoked with the equivalent of python my_asimmodule.py &> out.txt. -run_postfix in env_input.yaml is always appended after the one -provided by calc_input.yaml.

  • -
  • calc_id.precommands: (list, optional) Commands to be run/added to the job -asimmodule before running the asimmodule. A common use case is loading a -module or activating an environment

  • -
  • calc_id.postcommands: (list, optional) Commands to be run/added to the -job asimmodule after running the asimmodule. e.g. cleaning up bulky tmp or -wavefunction files

  • -
  • calc_id.args: (dict) key-value pairs to be passed as arguments for the -initialization of the calculator class. e.g. if the class is LennardJones, -the arguments are passed as calc = LennardJones(**{'sigma':3.2, -'epsilon':3})

  • -
-
-
-

sim_input.yaml

-

The minimal requirement to run an asimmodule is to provide a sim_input.yaml -file. An example of a sim_input.yaml is shown below:

-
asimmodule: singlepoint
-env_id: inline
-overwrite: false
-submit: true
-workdir: results
-precommands:
-    - export MY_ENV_VAR=3
-args:
-    arg1: value_1
-    arg2: value_2
-    ...
-
-
-

The parameters are:

-
    -
  • asimmodule: (str) name of core asimmodule or /path/to/my/asimmodule.py. -Core asimmodules defined in the asimmodules directory can be simply referred -to using Python dot notation. E.g. to specify the -asimtools.asimmodules.workflows.sim_array() asimmodule, you would -specify workflows.sim_array. Any other asimmodule should be specified as -either a full path or a path relative to ASIMTOOLS_ASIMMODULE_DIR -variable to a python file. E.g. my_asimmodules/asim_ple.py

  • -
  • env_id: (str, optional) Environment/context in which to run asimmodule -configured in env_input.yaml, defaults to running in the current console

  • -
  • overwrite: (bool, optional) (bool) whether or not to overwrite work -directories if they exist, defaults to false

  • -
  • submit: (bool, optional) whether to run the asimmodule. If set to false -it will just write the input files which is very useful for testing before -submitting large workflows. You can go in and test one example before -resubmitting with submit=True, defaults to true

  • -
  • workdir: (str, optional) The directory in which the asimmodule will be -run, asim-execute will create the directory whereas asim-run ignores this -parameter entirely, defaults to ‘./results’

  • -
  • precommands: (list, optional) a list of commands to run in the console -before running the asimmodule, defaults to empty list

  • -
  • postcommands: (list, optional) a list of commands to run in the console -after running the asimmodule, defaults to empty list

  • -
  • args: (dict) The arguments of the function being called in the asimmodule -as key-value pairs. These are specific to the asimmodule being run.

  • -
-

All ASIMTools generated files are named sim_input.yaml but you can name -user defined files as whatever you like

-
-
-

Specifying Images/Atoms

-

One of the most useful applications of ASIMTools is the unification of methods -for setting up ASE atoms objects using the same interface. If an asimmodule -requires a single or multiple atoms objects as input, they are provided as -either an image dictionary for a single Atoms object or images for a -list of Atoms objects as part of the args section. Below are the different -ways to get an atoms object. You can also download images from The Materials -Project and for some cases generate them using Pymatgen.

-

For a detailed description of the API and examples, see -asimtools.utils.get_atoms()

-
# Reading a specific image from a structure file using ase.io.read
-image:
-  image_file: /path/to/my/ASE-readable/image/file.xyz
-  # Optional keyword argument passed to ase.io.read
-  index: 3
-
-# Building a bulk crystal using ase.build.bulk
-image:
-  builder: bulk
-  # Optional keyword arguments passed to the builder, must match ASE exactly
-  name: Li
-  crystalstructure: bcc
-  a: 4.3
-  cubic: True
-
-# Building a surface using ase.build.fcc100
-image:
-  builder: fcc100
-  # Optional keyword arguments passed to the builder, must match ASE exactly
-  symbol: Fe
-  vacuum: 8
-  periodic: False
-
-# Building a 3x3x3 supercell of Ar using ase.build.bulk then
-# Atoms.repeat(repeat) and then applying Atoms.rattle(stdev=rattle_stdev)
-image:
-  name: Ar
-  repeat: [3,3,3]
-  rattle_stdev: 0.01
-
-# You can even supply an atoms object directly so that the interface is
-# universal. This is most useful in the asimmodule code itself.
-image:
-  atoms: Atoms
-
-# An example downloading a structure from Materials Project using your own
-# USER_API_KEY
-image:
-  mp_id: 'mp-14'
-  interface: pymatgen
-  user_api_key: "USER_API_KEY"
-  conventional_unit_cell': true
-
-
-

Similarly, if the asimmodule requires multiple image inputs, there exists a -universal interface. The keyword is usually specified as images. This is -especially useful for distributing simulations across multiple structures or -reading structures from multiple previous simulations, even in different -directories.

-

For a detailed description of the API, see asimtools.utils.get_images()

-
# Reading specific images from a structure file using ase.io.read
-images:
-  image_file: /path/to/my/ASE-readable/image/file.xyz
-  # Optional keyword arguments passed to ase.io.read
-  index: '3:8'
-  format: extxyz
-
-# You can read all files matching a certain pattern using a wildcard
-images:
-  pattern: /path/to/my/structure/files/*.cif
-  # Optional keyword argument passed to ase.io.read
-  index: -1
-
-# You can read all files matching certain patterns using a wildcard
-images:
-  patterns:
-  - /path/to/my/structure/files/*.cif
-  - /path/to/my/other/structure/files/*.cfg
-
-# You can even supply a list of atoms objects directly so that the interface
-# is universal. This is most useful in the asimmodule code itself.
-images:
-  images: [Atoms1, Atoms2, ...]
-
-
-
-
-
-

Usage of asim-execute and asim-run

-

The major difference between asim-execute and asim-run is that, -asim-execute takes into account the workdir and the env_id. -asim-run will run the asimmodule in the current directory and in the -current console. In fact, asim-execute will create the workdir and then -run asim-run in the correct environment/batch job. You can always for -example, request a slurm allocation, go to the directory where you want the -asimmodule to be run and call asim-run from there if you would like more -control or to debug. If you want verbose logs for debugging, you can run with -the -d or --debug flag.

-
-
-

Output files

-

A job or asimmodule run through ASIMTools will always produce a standard set of -output files in addition to whatever outputs the asimmodule produces. In -particular the most important outputs are the output.yaml and the -job.log file.

-
    -
  1. ``output.yaml`` contains the status of the job being run in the current -directory which can be one of clean, started, complete, failed, discard. -The statuses are self-explanatory, the discard status is never written -by ASIMTools but a user can edit an output.yaml file and change it’s -status to discard to tell ASIMTools to ignore that job in any workflows. -This is common for example if you launch multiple jobs and one of them fails -irredemably. Deleting the directory for that job is also ok if nothing -depends on it downstream. Importantly, any results returned by the function -defined in the asimmodule are found in output.yaml. Asimmodule functions -should always return a dictionary of only primitive types for this purpose.

    -

    An example of an output.yaml file is shown below.

    -
  2. -
-
# Successful output for singlepoint asimmodule
-end_time: 2023-08-28 21:50:51.368025
-energy: 13.77302319846367  #This was added by the scinglepoint asimmodule
-files:
-  image: image_output.xyz
-job_ids: '372919'
-start_time: 2023-08-28 21:50:46.188300
-status: complete
-
-# Failed output
-start_time: 14:29:55, 10/06/23
-status: failed
-
-
-
    -
  1. job.log captures the logged output of asim-run or asimmodules -that use logging. It is extremely useful for debugging as following the logs -starting from the base directory will usually lead you to the correct -traceback that caused the failure.

  2. -
  3. stderr.txt captures errors and backtraces from running asimmodules. This -is usually the most informative file for debugging. You can be directed to -the correct one by noting errors in job.log files.

  4. -
  5. stdout.txt captures any stdout from running asimmodules. It is mostly a -safety measure for catching anything that prints to stdout and rarely has -useful information unless you write an asimmodule that uses print -statements. In batch jobs, this output this goes to the slurm job output.

  6. -
  7. input_image.xyz and input_images.xyz capture the images input into -the asimmodule. This makes sure there is a concrete artifact for the -structure used by the asimmodule for the purposes of visualization and -debugging. They are always in extxyz format as a flexible standard -format

  8. -
  9. slurm* are slurm job files which can be named according to flags -specified in env_input.yaml otherwise are named -slurm_stdout.id-%a_j%A or slurm_stderr.id-%a_j%A after job and array -IDs

  10. -
-
-
-

Checking job status and Restarting failed jobs

-

To check the status of jobs, even complicated chains and distributed jobs, we -provide the asim-check utility which can be run using:

-
asim-check /path/to/sim_input.yaml
-
-
-

This will print the job tree, including statuses and work directories of the -jobs whose root directory is specified as workdir in sim_input.yaml.

-

In many cases, there may be mistakes in one of your configuration files leading -to a failed workflow. In these cases there are a few ways you could resolve the -issue:

-
    -
  • Delete the work directory and restart the workflow. This is why it is -recommended that the base sim_input.yaml has workdir set to a new -directory that only has the results of the workflow.

  • -
  • Modify the ASIMTools generated sim_input.yaml to fix the problem. If -there are downstream sim_input.yaml files in a chain, they will have to -be deleted or set overwrite=True. Deleting is recommended for safety -purposes.

  • -
  • Simply rerun asim-execute. This will rerun the jobs, skipping any jobs -with a status of complete or discard. Note that error files are not -deleted so you will have to clear those manually. Use this with caution!

  • -
-
-
-

Importing functions from asimmodules and the API

-

Because asimmodules contain what are merely Python functions, you can always -import them and use them in any other code for example, you can import -asimtools.asimmodules.singlepoint() and use it as below.

-
from asimtools.asimmodules.singlepoint import singlepoint
-
-results = singlepoint(image={'name': 'Ar'}, calc_id='lj')
-print(results)
-
-
-

You can also use the utils and tools e.g. to load a calculator using just a -calc_id

-
from asimtools.calculators import load_calc
-
-calc = load_calc('lj')
-
-
-
-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file diff --git a/_build/workflows.html b/_build/workflows.html deleted file mode 100644 index b2cd28a..0000000 --- a/_build/workflows.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - Using built-in workflow tools — asimtools 1.0.0 documentation - - - - - - - - - - - - - - - - - -
- - -
- -
-
-
- -
-
-
-
- -
-

Using built-in workflow tools

-

ASIMTools offers some standard tools for performing common workflows. These -are:

-
    -
  1. asimtools.asimmodules.sim_array.sim_array() - Run the same asimmodule -with one or more specified arguments of the asimmodule iterated over. This -is the most useful asimmodule and can substitute most others except -chained

  2. -
  3. asimtools.asimmodules.image_array.image_array() - Run the same -asimmodule on multiple images, e.g. a repeat calculation on a database

  4. -
  5. asimtools.asimmodules.calc_array.calc_array() - Run the same -asimmodule using different calc_ids or calculator parameters based on a -template. e.g. to converge cutoffs in DFT or benchmark many force fields

  6. -
  7. asimtools.asimmodules.distributed.distributed() - Run multiple -sim_inputs in parallel

  8. -
  9. asimtools.asimmodules.chained.chained() - Run asimmodules one after -the other, e.g. if step 2 results depend on step 1 etc. This allows building -multi-step workflows.

  10. -
  11. asimtools.asimmodules.iterative.iterative() - Run the same asimmodule -over and over until some condition is reached. This asimmodule is still -under active development

  12. -
-

Examples for each type of workflow are given in the examples directory and -documentation can be found in asimtools.asimmodules. They also serve as -templates for you to build your own workflows directly using -asimtools.job.Job() objects as an advanced user.

-
- - -
-
- -
-
-
-
- - - - \ No newline at end of file