MaterialsCoord provides an infrastructure for comparing coordination numbers produced by different approaches against a benchmark set of material structures.
Atomic coordination numbers (CNs) are one of the most important descriptors for the local environments in condensed materials, but they have no universal definition. Therefore, researchers have come up with a wide range of algorithms, performance of which are often unknown outside the chemical domain they were particularly designed for. MaterialsCoord aims at providing the necessary infrastructure to host, interface, compare and benchmark different CN algorithms against a selected set of crystal structures. It further allows human interpretations of CN environments to be incorporated into benchmarking (in progress).
1. How do I benchmark Coordination Number algorithms with MaterialsCoord?
2. Which coordination number algorithms are currently available?
3. How do I implement a new Coordination Number algorithm?
4. How can I use MaterialsCoord on my own structures?
5. What is the HumanInterpreter?
6. Installation and requirements
Simply put:
Benchmark
class provides the necessary infrastructure to perform the comparison of CN algorithms. When being initialized, it takes the group of test structures (or your own structures) and a list ofCNBase
methods (CN calculation methods) as arguments.Benchmark.benchmark()
performs the CN calculations on the selected test structuresBenchmark.report()
provides different types of reports that summarizes the results of the benchmarking.
For example, we can compare the Effective Coordination Number (ECoN) and O'Keeffe's Voronoi CN method using a set of unique elemental crystal structures:
from materialscoord.cn_methods import TestECoN, TestVoronoiCoordFinder
from materialscoord.core import Benchmark
bm = Benchmark([TestECoN(), TestVoronoiCoordFinder()], "elemental")
bm.benchmark()
bm.report()
Further details can be found in examples provided in benchmark_examples.ipynb.
##Which coordination number algorithms are currently available? Currently, MaterialsCoord has the following coordination number algorithms implemented in `materialscoord.cn_methods`: - `TestVoronoiCoordFinder`: Weighted Voronoi CNs (O'Keeffe's method). - `TestECoN`: Effective Coordination Numbers, ECoN, (Hoppe's method). - `TestVoronoiCoordFinder_mod`: A modified version of `TestVoronoiCoordFinder`. - `TestVoronoiLegacy`: Basic Voronoi facet counting. - `TestBrunnerReciprocal`: Brunner's method of largest reciprocal gap in interactomic distances. - `TestBrunnerRelative`: Brunner's method of largest relative gap in interactomic distances. - `TestBrunnerReal`: Brunner's method of largest gap in interactomic distances. - `TestDelaunay`: David Mrdjenovich et al.'s Delaunay triangulation based algorithm (under development at LBNL).You can see the details of the available algorithms here. New algorithms are welcome; simply submit a pull request on github.
##How do I implement a new Coordination Number algorithm?This is fairly simple:
- Define a new class that is subclassed from
materialscoord.core.CNBase
. - The class must have a method named
compute
which takes a pymatgen Structure and site-index as input, and returns a dictionary of CNs for that site; e.g.{'O': 4.4, 'F': 2.1}
.
For example:
class MyCoordinationNumberAlgorithm(CNBase):
"""
My new algorithm
"""
def compute(self, structure, n):
params = self._params
# ... here your algorithm finds CNs of site n.
# e.g. cns = my_algorithm(structure, n, **params)
return cns
Any parameters the algorithm needs can be passed to the class when initializing using the params keyword as a dictionary. These can later
be accessed from compute
method as the _params
attribute of the class.
In method compute
you can do whatever is necessary to interface the algorithm with MaterialsCoord. Options include:
- Simplest: Implementing the entire algorithm within the
compute
method. - Recommended: Add the necessary "bulky" code to a relevant module in external_src package and import as you define
compute
. - Not recommended: call or import a library/program outside of MaterialsCoord within the
compute
method. This is not recommended as external dependencies will restrict portability, but maybe unavoidable if the external algorithm is part of another python package, or is written in some other language such as Java. In that casecompute
can simply serve as a wrapper that calls and post processes the output of the external code.
An example can be found in the custom_tests notebook.
Note that in any case, the structures provided can be of any type that pymatgen can automatically interpret (cif, POSCAR, etc.)
##What is the HumanInterpreter? `HumanInterpreter` is a special CN method that provides CNs from the "human" interpreted coordination environments stored in the human_interpreter.yaml file. It can be added as a CN method along with other CN methods. Currently only the `common_binaries` structure group has human interpreted CNs, but more will be added soon.If you interpret the CN environment in a structure and you want to add it to MaterialsCoord to compare against availble CN methods, you can basically add the CN numbers to the human_interpreter.yaml as a dictionary that matches
the name of the structure file in test_structures
or custom_set
you provided (without the file extension, if it has any). For example:
Fe3O4_spinel:
- Fe:
Fe: 0.0
O: 6.0
- Fe:
Fe: 0.0
O: 4.0
- O:
Fe: 4.0
O: 0.0
describes the CN environment in the spinel Fe3O4 spinel structure, where there are two different unique Fe sites, and one O site. Sites are given as a list. And for each site a dictionary of neighboring elements are provided. In this sub-dictionary of surroundings of a given site, we do not differentiate between sites and only list the total CN number for each chemical element (i.e. there is one Fe in each) opposite to the unique sites list (where we had two Fe sites).
Since it is not always easy to interpret the exact coordination number, MaterialsCoord will accept a range. Let's assume hypothetically we aren't sure how many Fe neighbors the O site has, but we guess it's between 3.0 and 5.0, we can write:
Fe3O4_spinel:
- Fe:
Fe: 0.0
O: 6.0
- Fe:
Fe: 0.0
O: 4.0
- O:
Fe:
- 3.0
- 5.0
O: 0.0