Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage and doc updates #88

Merged
merged 18 commits into from
Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Pull Request Template

## Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

- [ ] Test A
- [ ] Test B

**Test Configuration**:
* Python version:
* Operating System:


## Reviewers

@mention individuals who you specifically want to involve in the discussion for this pull request and mention why they are needed in the dicussion/why they are needed to review the pull request.


## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules
- [ ] I have checked my code and corrected any misspellings
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
[![Documentation Status](https://readthedocs.org/projects/smact/badge/?version=latest)](http://smact.readthedocs.org/en/latest/?badge=latest)
[![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Build Status](https://travis-ci.org/WMD-group/SMACT.svg?branch=master)](https://travis-ci.org/WMD-group/SMACT)
[![DOI](http://joss.theoj.org/papers/10.21105/joss.01361/status.svg)](https://doi.org/10.21105/joss.01361)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![PyPi](https://img.shields.io/pypi/v/smact)](https://pypi.org/project/SMACT/)
[![GitHub issues](https://img.shields.io/github/issues-raw/WMD-Group/SMACT)](https://github.com/WMD-group/SMACT/issues)
![dependencies](https://img.shields.io/librariesio/release/pypi/smact)
[![CI Status](https://github.com/WMD-group/SMACT/actions/workflows/ci.yml/badge.svg)](https://github.com/WMD-group/SMACT/actions/workflows/ci.yml)
![python version](https://img.shields.io/pypi/pyversions/smact)


SMACT
=====
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,5 +381,6 @@ def __getattr__(cls, name):
"pymatgen.util",
"pymatgen.util.plotting",
"pymatgen.analysis.structure_prediction",
"pymatgen.transformations.standard_transformations",
]
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
71 changes: 45 additions & 26 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,39 +108,58 @@ We can look for neutral combos.
.. code:: python

import smact.screening
import pprint

elements = ['Ti', 'Al', 'O']
space = smact.element_dictionary(elements)
# We just want the element items from the dictionary
eles = [e[1] for e in space.items()]
# We set a threshold for the stoichiometry of 4
allowed_combinations = smact.screening.smact_filter(eles, threshold=4)
print(allowed_combinations)

[(('Ti', 'Al', 'O'), (1, 3, 3)),
(('Ti', 'Al', 'O'), (2, 3, 4)),
(('Ti', 'Al', 'O'), (3, 1, 4)),
(('Ti', 'Al', 'O'), (1, 4, 4)),
(('Ti', 'Al', 'O'), (3, 1, 2)),
(('Ti', 'Al', 'O'), (3, 2, 4)),
(('Ti', 'Al', 'O'), (1, 2, 3)),
(('Ti', 'Al', 'O'), (1, 3, 4)),
(('Ti', 'Al', 'O'), (2, 4, 3)),
(('Ti', 'Al', 'O'), (2, 1, 3)),
(('Ti', 'Al', 'O'), (4, 2, 3)),
(('Ti', 'Al', 'O'), (1, 3, 2)),
(('Ti', 'Al', 'O'), (1, 2, 4)),
(('Ti', 'Al', 'O'), (1, 1, 2)),
(('Ti', 'Al', 'O'), (1, 2, 2)),
(('Ti', 'Al', 'O'), (1, 1, 4)),
(('Ti', 'Al', 'O'), (3, 1, 3)),
(('Ti', 'Al', 'O'), (2, 1, 4)),
(('Ti', 'Al', 'O'), (1, 1, 1)),
(('Ti', 'Al', 'O'), (2, 2, 3)),
(('Ti', 'Al', 'O'), (4, 1, 3)),
(('Ti', 'Al', 'O'), (1, 1, 3)),
(('Ti', 'Al', 'O'), (1, 4, 3)),
(('Ti', 'Al', 'O'), (2, 1, 2))]
pprint.pprint(allowed_combinations)

[Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -2), stoichiometries=(1, 1, 1)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -2), stoichiometries=(1, 3, 2)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -2), stoichiometries=(2, 4, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -2), stoichiometries=(3, 1, 2)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -2), stoichiometries=(4, 2, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -1), stoichiometries=(1, 1, 2)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -1), stoichiometries=(1, 2, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -1), stoichiometries=(1, 3, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -1), stoichiometries=(2, 1, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 1, -1), stoichiometries=(3, 1, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 2, -2), stoichiometries=(2, 1, 2)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 2, -2), stoichiometries=(2, 2, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 2, -2), stoichiometries=(2, 3, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 2, -2), stoichiometries=(4, 1, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 2, -1), stoichiometries=(1, 1, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 2, -1), stoichiometries=(2, 1, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 3, -2), stoichiometries=(1, 1, 2)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 3, -2), stoichiometries=(3, 1, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(1, 3, -1), stoichiometries=(1, 1, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 1, -2), stoichiometries=(1, 2, 2)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 1, -2), stoichiometries=(1, 4, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 1, -2), stoichiometries=(2, 2, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 1, -2), stoichiometries=(3, 2, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 1, -1), stoichiometries=(1, 1, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 1, -1), stoichiometries=(1, 2, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 2, -2), stoichiometries=(1, 1, 2)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 2, -2), stoichiometries=(1, 2, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 2, -2), stoichiometries=(1, 3, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 2, -2), stoichiometries=(2, 1, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 2, -2), stoichiometries=(3, 1, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 2, -1), stoichiometries=(1, 1, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(2, 3, -2), stoichiometries=(1, 2, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(3, 1, -2), stoichiometries=(1, 1, 2)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(3, 1, -2), stoichiometries=(1, 3, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(3, 1, -1), stoichiometries=(1, 1, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(3, 2, -2), stoichiometries=(2, 1, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(3, 3, -2), stoichiometries=(1, 1, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(4, 1, -2), stoichiometries=(1, 2, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(4, 1, -2), stoichiometries=(1, 4, 4)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(4, 2, -2), stoichiometries=(1, 1, 3)),
Composition(element_symbols=('Ti', 'Al', 'O'), oxidation_states=(4, 2, -2), stoichiometries=(1, 2, 4))]


There is `an example <https://github.com/WMD-group/SMACT/blob/master/examples/Counting/Generate_compositions_lists.ipynb>`_
of how this function can be combined with multiprocessing to rapidly explore large subsets of chemical space.
Expand Down
2 changes: 1 addition & 1 deletion docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Getting Started
Requirements
============

The main language is Python 3 and has been tested using Python 3.6+. Basic requirements are Numpy and Scipy.
The main language is Python 3 and has been tested using Python 3.8+. Basic requirements are Numpy and Scipy.
The `Atomic Simulation Environment <https://wiki.fysik.dtu.dk/ase>`_
(ASE), `spglib <http://atztogo.github.io/spglib>`_,
and `pymatgen <http://pymatgen.org>`_ are also required for many components.
Expand Down
12 changes: 9 additions & 3 deletions examples/Cation_mutation/cation_mutation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,9 @@
"def pretty_print_atoms(atoms, linewrap=15):\n",
" entries = [\n",
" \"{0:5.3f} {1:5.3f} {2:5.3f} {symbol}\".format(*position, symbol=symbol)\n",
" for position, symbol in zip(atoms.get_positions(), atoms.get_chemical_symbols())\n",
" for position, symbol in zip(\n",
" atoms.get_positions(), atoms.get_chemical_symbols()\n",
" )\n",
" ]\n",
"\n",
" for output_i in range(linewrap):\n",
Expand Down Expand Up @@ -196,13 +198,17 @@
"sub_lattice = distort.build_sub_lattice(single_substitution, \"Ba\")\n",
"\n",
"# Enumerate the inequivalent sites\n",
"inequivalent_sites = distort.get_inequivalent_sites(sub_lattice, single_substitution)\n",
"inequivalent_sites = distort.get_inequivalent_sites(\n",
" sub_lattice, single_substitution\n",
")\n",
"\n",
"# Replace Ba at inequivalent sites with Sr\n",
"for i, inequivalent_site in enumerate(inequivalent_sites):\n",
" print(\"-\" * hlinewidth)\n",
" print(f\"Substituted coordinates {i}\")\n",
" distorted = distort.make_substitution(single_substitution, inequivalent_site, \"Sr\")\n",
" distorted = distort.make_substitution(\n",
" single_substitution, inequivalent_site, \"Sr\"\n",
" )\n",
" pretty_print_atoms(distorted)\n",
"\n",
"print(\"=\" * hlinewidth)"
Expand Down
24 changes: 18 additions & 6 deletions examples/Counting/ElementCombinationsParallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ def main():
# neutral_stoichiometries.update({oxidation_states: count})

def n_neutral_ratios(oxidation_states, threshold=8):
return len(smact.neutral_ratios(oxidation_states, threshold=threshold)[1])
return len(
smact.neutral_ratios(oxidation_states, threshold=threshold)[1]
)

neutral_stoichiometries = {
oxidation_states: n_neutral_ratios(
Expand All @@ -158,10 +160,14 @@ def n_neutral_ratios(oxidation_states, threshold=8):
# progress indicator.

combination_count = sum(
count_iter(itertools.combinations(element_list, i)) for i in range(2, n + 1)
count_iter(itertools.combinations(element_list, i))
for i in range(2, n + 1)
)

print("Counting ({} element combinations)" "...".format(combination_count))
print(
"Counting ({} element combinations)"
"...".format(combination_count)
)

# Combinations are counted in chunks set by count_progress_interval.
# In Python 2.7 the // symbol is "integer division" which rounds
Expand Down Expand Up @@ -215,7 +221,9 @@ def n_neutral_ratios(oxidation_states, threshold=8):
# Serial code path -- iteration over element combinations is
# done using the itertools.imap() function.

count = count + sum(map(count_element_combination, imap_arg_generator))
count = count + sum(
map(count_element_combination, imap_arg_generator)
)

# After each chunk, report the % progress, elapsed time and an
# estimate of the remaining time. The smact.pauling_test() calls
Expand All @@ -229,7 +237,8 @@ def n_neutral_ratios(oxidation_states, threshold=8):

time_elapsed = time.time() - start_time
time_remaining = (
combination_count * (time_elapsed / data_pointer) - time_elapsed
combination_count * (time_elapsed / data_pointer)
- time_elapsed
)

print_status(
Expand All @@ -253,7 +262,10 @@ def n_neutral_ratios(oxidation_states, threshold=8):
"Number of charge-neutral stoichiometries for combinations "
"of {} elements".format(n)
)
print("(using known oxidation states, not including zero): " "{}".format(count))
print(
"(using known oxidation states, not including zero): "
"{}".format(count)
)
print("")

print(f"Total time for counting: {total_time:.3f} sec")
Expand Down
4 changes: 3 additions & 1 deletion examples/Counting/Generate_compositions_lists.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@
"# Flatten the list of lists\n",
"flat_list = [item for sublist in result for item in sublist]\n",
"print(f\"Number of compositions: --> {len(flat_list)} <--\")\n",
"print(\"Each list entry looks like this:\\n elements, oxidation states, stoichiometries\")\n",
"print(\n",
" \"Each list entry looks like this:\\n elements, oxidation states, stoichiometries\"\n",
")\n",
"for i in flat_list[:5]:\n",
" print(i)"
]
Expand Down
14 changes: 9 additions & 5 deletions examples/Counting/Raw_combinations.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,12 @@
"\n",
"def main():\n",
"\n",
" compound_names = {2: \"binary\", 3: \"ternary\", 4: \"quaternary\", 5: \"quinternary\"}\n",
" compound_names = {\n",
" 2: \"binary\",\n",
" 3: \"ternary\",\n",
" 4: \"quaternary\",\n",
" 5: \"quinternary\",\n",
" }\n",
"\n",
" print(f\"In a search space of {search_space} elements:\")\n",
" print(\"\")\n",
Expand All @@ -145,9 +150,7 @@
" # (1,2,2), (2,1,1), (2,1,2), (2,1,2)\n",
" def ineq_ratios_with_coeff(n_species, max_coeff):\n",
" print(\n",
" \"Number of inequivalent {} ratios with max coefficient {}: \".format(\n",
" compound_names[n_species], max_coeff\n",
" )\n",
" f\"Number of inequivalent {compound_names[n_species]} ratios with max coefficient {max_coeff}: \"\n",
" ),\n",
" n_ratios = sum_iter(\n",
" filter(\n",
Expand Down Expand Up @@ -188,7 +191,8 @@
" return n_compounds\n",
"\n",
" compounds = {\n",
" n: {x: unique_compounds(n, x) for x in range(4, 9, 2)} for n in range(2, 5)\n",
" n: {x: unique_compounds(n, x) for x in range(4, 9, 2)}\n",
" for n in range(2, 5)\n",
" }\n",
"\n",
"\n",
Expand Down
22 changes: 15 additions & 7 deletions examples/Inverse_perovskites/Inverse_formate_perovskites.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@
" if electroneg_makes_sense:\n",
" pauling_perov.append([A[0], B[0], C[0]])\n",
" # We calculate the Goldschmidt tolerance factor\n",
" tol = (float(A[2]) + C[2]) / (np.sqrt(2) * (float(B[2]) + C[2]))\n",
" tol = (float(A[2]) + C[2]) / (\n",
" np.sqrt(2) * (float(B[2]) + C[2])\n",
" )\n",
" if tol > 1.0:\n",
" a_too_large.append([A[0], B[0], C[0]])\n",
" anion_hex = anion_hex + 1\n",
Expand Down Expand Up @@ -354,7 +356,9 @@
"outputs": [],
"source": [
"# Get list of Element objects\n",
"search = [el for el in smact.ordered_elements(3, 87) if Element(el).oxidation_states]\n",
"search = [\n",
" el for el in smact.ordered_elements(3, 87) if Element(el).oxidation_states\n",
"]\n",
"\n",
"# Covert to list of Species objects\n",
"all_species = []\n",
Expand All @@ -363,8 +367,12 @@
" all_species.append(Species(el, oxi_state, \"6_n\"))\n",
"\n",
"# Define lists of interest\n",
"A_list = [sp for sp in all_species if (sp.oxidation == -1) and (sp.ionic_radius)]\n",
"B_list = [sp for sp in all_species if (4 <= sp.oxidation <= 5) and (sp.ionic_radius)]\n",
"A_list = [\n",
" sp for sp in all_species if (sp.oxidation == -1) and (sp.ionic_radius)\n",
"]\n",
"B_list = [\n",
" sp for sp in all_species if (4 <= sp.oxidation <= 5) and (sp.ionic_radius)\n",
"]\n",
"C_list = [Species(\"F\", -1, 4.47)]"
]
},
Expand All @@ -386,9 +394,9 @@
"for combo in product(A_list, B_list, C_list):\n",
" A, B, C = combo[0], combo[1], combo[2]\n",
" # Check for charge neutrality in 1:1:3 ratio\n",
" if (1, 1, 3) in screening.neutral_ratios([A.oxidation, B.oxidation, C.oxidation])[\n",
" 1\n",
" ]:\n",
" if (1, 1, 3) in screening.neutral_ratios(\n",
" [A.oxidation, B.oxidation, C.oxidation]\n",
" )[1]:\n",
" charge_balanced.append(combo)\n",
" # Check for pauling test\n",
" if screening.pauling_test(\n",
Expand Down
Loading