gridmlip 0.1__tar.gz → 0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gridmlip-0.1/gridmlip.egg-info → gridmlip-0.2}/PKG-INFO +6 -6
- {gridmlip-0.1 → gridmlip-0.2}/README.md +4 -4
- gridmlip-0.2/gridmlip/_mesh.py +139 -0
- gridmlip-0.2/gridmlip/core.py +333 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip/utils.py +1 -1
- {gridmlip-0.1 → gridmlip-0.2/gridmlip.egg-info}/PKG-INFO +6 -6
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip.egg-info/SOURCES.txt +1 -0
- {gridmlip-0.1 → gridmlip-0.2}/setup.cfg +1 -1
- {gridmlip-0.1 → gridmlip-0.2}/setup.py +2 -2
- gridmlip-0.1/gridmlip/core.py +0 -274
- {gridmlip-0.1 → gridmlip-0.2}/LICENSE +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/MANIFEST.in +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip/__init__.py +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip/_neighborhood.py +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip/_percolation_analysis.py +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip/cli.py +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip.egg-info/dependency_links.txt +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip.egg-info/requires.txt +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip.egg-info/top_level.txt +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/gridmlip.egg-info/zip-safe +0 -0
- {gridmlip-0.1 → gridmlip-0.2}/pyproject.toml +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: gridmlip
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2
|
|
4
4
|
Summary: Grid-based method for calculating the percolation barrier of mobile species using machine learning interatomic potentials
|
|
5
5
|
Home-page: https://github.com/dembart/gridmlip
|
|
6
6
|
Author: Artem Dembitskiy
|
|
7
7
|
Author-email: art.dembitskiy@gmail.com
|
|
8
8
|
License: MIT
|
|
9
|
-
Keywords: MLIP,percolation barrier
|
|
9
|
+
Keywords: MLIP,percolation barrier,irreducible mesh
|
|
10
10
|
Platform: UNKNOWN
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -31,7 +31,6 @@ License-File: LICENSE
|
|
|
31
31
|
|
|
32
32
|
**gridmlip** is a library for calculating percolation barriers of mobile species in solids using grid-based method with machine learning interatomic potentials (MLIPs).
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
## Installation
|
|
36
35
|
|
|
37
36
|
```
|
|
@@ -53,7 +52,7 @@ Here we describe the pipeline in general. For a specific example, see [Notebooks
|
|
|
53
52
|
from gridmlip import Grid
|
|
54
53
|
|
|
55
54
|
atomic_types_mapper = {3:0, 31:1, 17:2}
|
|
56
|
-
|
|
55
|
+
grid = Grid.from_file('your.cif', specie = 3, r_min = 1.8,
|
|
57
56
|
atomic_types_mapper=atomic_types_mapper # optional
|
|
58
57
|
)
|
|
59
58
|
cfgs = grid.construct_configurations('data.cfg')
|
|
@@ -72,7 +71,7 @@ from gridmlip import Grid
|
|
|
72
71
|
|
|
73
72
|
grid = Grid.from_file('your.cif', specie = 3, r_min = 1.8)
|
|
74
73
|
grid.read_processed_configurations('processed_data.cfg', format = 'cfg')
|
|
75
|
-
grid.percolation_barriers()
|
|
74
|
+
barriers = grid.percolation_barriers()
|
|
76
75
|
```
|
|
77
76
|
|
|
78
77
|
#### Step #4: Write .grd or .cube file for visualization in VESTA 3.0
|
|
@@ -84,7 +83,8 @@ g.write_grd('test.grd')
|
|
|
84
83
|
## Notebooks
|
|
85
84
|
|
|
86
85
|
|
|
87
|
-
- [Using TensorNet model pre-trained on MatPES](notebooks/TensorNet_MatPES.ipynb)
|
|
86
|
+
- [Using TensorNet model pre-trained on MatPES](notebooks/TensorNet_MatPES.ipynb)
|
|
87
|
+
[](https://colab.research.google.com/drive/14gabZ-u19K-_I_e7-g67N8-xtPIN36Nw#sandboxMode=true&scrollTo=5TySp6C6UBoZ)
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
### How to cite
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
|
|
16
16
|
**gridmlip** is a library for calculating percolation barriers of mobile species in solids using grid-based method with machine learning interatomic potentials (MLIPs).
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
## Installation
|
|
20
19
|
|
|
21
20
|
```
|
|
@@ -37,7 +36,7 @@ Here we describe the pipeline in general. For a specific example, see [Notebooks
|
|
|
37
36
|
from gridmlip import Grid
|
|
38
37
|
|
|
39
38
|
atomic_types_mapper = {3:0, 31:1, 17:2}
|
|
40
|
-
|
|
39
|
+
grid = Grid.from_file('your.cif', specie = 3, r_min = 1.8,
|
|
41
40
|
atomic_types_mapper=atomic_types_mapper # optional
|
|
42
41
|
)
|
|
43
42
|
cfgs = grid.construct_configurations('data.cfg')
|
|
@@ -56,7 +55,7 @@ from gridmlip import Grid
|
|
|
56
55
|
|
|
57
56
|
grid = Grid.from_file('your.cif', specie = 3, r_min = 1.8)
|
|
58
57
|
grid.read_processed_configurations('processed_data.cfg', format = 'cfg')
|
|
59
|
-
grid.percolation_barriers()
|
|
58
|
+
barriers = grid.percolation_barriers()
|
|
60
59
|
```
|
|
61
60
|
|
|
62
61
|
#### Step #4: Write .grd or .cube file for visualization in VESTA 3.0
|
|
@@ -68,7 +67,8 @@ g.write_grd('test.grd')
|
|
|
68
67
|
## Notebooks
|
|
69
68
|
|
|
70
69
|
|
|
71
|
-
- [Using TensorNet model pre-trained on MatPES](notebooks/TensorNet_MatPES.ipynb)
|
|
70
|
+
- [Using TensorNet model pre-trained on MatPES](notebooks/TensorNet_MatPES.ipynb)
|
|
71
|
+
[](https://colab.research.google.com/drive/14gabZ-u19K-_I_e7-g67N8-xtPIN36Nw#sandboxMode=true&scrollTo=5TySp6C6UBoZ)
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
### How to cite
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from spglib import get_symmetry_dataset
|
|
3
|
+
|
|
4
|
+
__author__ = "Artem Dembitskiy"
|
|
5
|
+
|
|
6
|
+
class Mesh:
|
|
7
|
+
"""
|
|
8
|
+
This class implements mesh generation and finding irreducible mesh
|
|
9
|
+
points given the rotations and translations symmetry operations.
|
|
10
|
+
|
|
11
|
+
Example
|
|
12
|
+
-------
|
|
13
|
+
|
|
14
|
+
mesh = Mesh.from_atoms(atoms, resolution = 0.2, symprec = 0.1)
|
|
15
|
+
ir_grid_points, mapping = mesh.get_irreducible_mapping()
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, mesh_shape, rotations, translations, symmetry_dataset=None):
|
|
20
|
+
"""
|
|
21
|
+
Initialization.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
|
|
27
|
+
mesh_shape: tuple of integers, (nx, ny, nz)
|
|
28
|
+
shape of the mesh
|
|
29
|
+
|
|
30
|
+
rotations: list of numpy arrays of shape (3, 3)
|
|
31
|
+
rotation matrices
|
|
32
|
+
|
|
33
|
+
translations: list of numpy arrays of shape (3, 1)
|
|
34
|
+
translation vector
|
|
35
|
+
|
|
36
|
+
symmetry_dataset: dict generated by spglib library, None by default (Optional)
|
|
37
|
+
dataset containing symmetry operations, used for tests
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
self.mesh_shape = mesh_shape
|
|
41
|
+
self.rotations = rotations
|
|
42
|
+
self.translations = translations
|
|
43
|
+
self.symmetry_dataset = symmetry_dataset
|
|
44
|
+
self.mesh = self._generate_mesh()
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def addresses(self):
|
|
48
|
+
return self.mesh
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def from_atoms(cls, atoms, resolution=0.2, symprec=None):
|
|
53
|
+
"""
|
|
54
|
+
Create Mesh object form ASE's Atoms object.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
|
|
60
|
+
atoms: ASE's Atoms object
|
|
61
|
+
atomic structure
|
|
62
|
+
|
|
63
|
+
resolution: float, 0.2 by default
|
|
64
|
+
distance between points of the mesh in angstroms
|
|
65
|
+
symprec: None or float, None by default
|
|
66
|
+
symmetry precision
|
|
67
|
+
used by spglib' get_symmetry_dataset to find symmetry operations
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
rotations = [np.eye(3, dtype=int)]
|
|
71
|
+
translations = [np.zeros(3)]
|
|
72
|
+
symmetry_dataset = None
|
|
73
|
+
a, b, c = np.linalg.norm(atoms.cell, axis = 1)
|
|
74
|
+
nx, ny, nz = int(a // resolution), int(b // resolution), int(c // resolution)
|
|
75
|
+
nx, ny, nz = [n + (n % 2 + 1) % 2 for n in (nx, ny, nz)] # make odd numbers
|
|
76
|
+
mesh_shape = (nx, ny, nz)
|
|
77
|
+
|
|
78
|
+
if symprec:
|
|
79
|
+
spglib_cell = (atoms.cell, atoms.get_scaled_positions(), atoms.numbers)
|
|
80
|
+
symmetry_dataset = get_symmetry_dataset(spglib_cell, symprec=symprec)
|
|
81
|
+
rotations = symmetry_dataset.rotations
|
|
82
|
+
translations = symmetry_dataset.translations
|
|
83
|
+
|
|
84
|
+
return cls(mesh_shape, rotations, translations, symmetry_dataset=symmetry_dataset)
|
|
85
|
+
|
|
86
|
+
def _generate_mesh(self):
|
|
87
|
+
"""Generate integer grid points (i,j,k) for a 3D mesh, including edges and faces."""
|
|
88
|
+
grid = np.mgrid[
|
|
89
|
+
0:self.mesh_shape[0],
|
|
90
|
+
0:self.mesh_shape[1],
|
|
91
|
+
0:self.mesh_shape[2]
|
|
92
|
+
].reshape(3, -1).T
|
|
93
|
+
return grid # shape (N,3), integer
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _index_to_linear(self, indices):
|
|
97
|
+
"""Convert 3D integer indices -> 1D linear indices for fast lookup."""
|
|
98
|
+
return np.ravel_multi_index(indices.T, self.mesh_shape)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _apply_sym_ops(self):
|
|
102
|
+
"""Apply symmetry ops to integer grid points, wrapping by mesh_shape."""
|
|
103
|
+
all_images = []
|
|
104
|
+
mesh_shape = np.array(self.mesh_shape)
|
|
105
|
+
for R, t in zip(self.rotations, self.translations):
|
|
106
|
+
t_mesh = np.rint(t * (mesh_shape - 1)).astype(int)
|
|
107
|
+
transformed = (self.mesh @ R.T + t_mesh) % (mesh_shape - 1)
|
|
108
|
+
all_images.append(transformed)
|
|
109
|
+
return np.stack(all_images, axis=0) # (nsym, npoints, 3)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def get_irreducible_mapping(self):
|
|
113
|
+
"""
|
|
114
|
+
Find symmetry-equivalent points on an integer 3D mesh.
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
indices of the irreducible points of the mesh and
|
|
119
|
+
mapping indices to restore full mesh from irreducible points
|
|
120
|
+
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
npoints = len(self.mesh)
|
|
124
|
+
nsym = len(self.rotations)
|
|
125
|
+
|
|
126
|
+
lin_indices = self._index_to_linear(self.mesh)
|
|
127
|
+
index_map = np.arange(npoints, dtype=int)
|
|
128
|
+
|
|
129
|
+
all_images = self._apply_sym_ops()
|
|
130
|
+
|
|
131
|
+
transformed_lin = self._index_to_linear(all_images.reshape(-1, 3))
|
|
132
|
+
transformed_lin = transformed_lin.reshape(nsym, npoints)
|
|
133
|
+
|
|
134
|
+
eq_ids = index_map[transformed_lin]
|
|
135
|
+
eq_ids = np.concatenate([eq_ids, index_map[None, :]], axis=0)
|
|
136
|
+
irreducible_ids = eq_ids.min(axis=0)
|
|
137
|
+
|
|
138
|
+
unique, inverse = np.unique(irreducible_ids, return_inverse=True)
|
|
139
|
+
return unique, inverse
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from tqdm import tqdm
|
|
3
|
+
from ase.io import read, write, cube
|
|
4
|
+
from pymatgen.io.ase import AseAtomsAdaptor
|
|
5
|
+
from .utils import read_cfg, write_cfg
|
|
6
|
+
from ._neighborhood import nn_list
|
|
7
|
+
from ._percolation_analysis import Percolyze
|
|
8
|
+
from ._mesh import Mesh
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__author__ = "Artem Dembitskiy"
|
|
13
|
+
__version__ = "0.2"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Grid:
|
|
18
|
+
|
|
19
|
+
def __init__(self,
|
|
20
|
+
atoms,
|
|
21
|
+
specie,
|
|
22
|
+
resolution=0.25,
|
|
23
|
+
r_cut=5.0,
|
|
24
|
+
r_min=1.5,
|
|
25
|
+
symprec=0.1,
|
|
26
|
+
atomic_types_mapper= None,
|
|
27
|
+
empty_framework=True,
|
|
28
|
+
verbose=True,
|
|
29
|
+
):
|
|
30
|
+
"""
|
|
31
|
+
Initialization.
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
|
|
36
|
+
atoms: ASE's Atoms object
|
|
37
|
+
atomic structure
|
|
38
|
+
|
|
39
|
+
specie: int
|
|
40
|
+
atomic number of the mobile specie
|
|
41
|
+
|
|
42
|
+
resolution: float, 0.2 by default
|
|
43
|
+
spacing between points (in Angstroms)
|
|
44
|
+
|
|
45
|
+
r_cut: float
|
|
46
|
+
cutoff radius to find the first nearest neighbor for each grid point
|
|
47
|
+
|
|
48
|
+
r_min: float
|
|
49
|
+
blocking sphere radius
|
|
50
|
+
|
|
51
|
+
atomic_types_mapper: dict, optional
|
|
52
|
+
mapper of atomic numbers into species used by MLIP
|
|
53
|
+
|
|
54
|
+
symprec: None or float, 0.1 by default
|
|
55
|
+
symmetry precision
|
|
56
|
+
used to get symmetry operations for finding the irreducible mesh points
|
|
57
|
+
may reduce number of MLIP calculations by factor of ~10-100
|
|
58
|
+
if None, the symmetry will not be used.
|
|
59
|
+
|
|
60
|
+
empty_framework: boolean, True by default
|
|
61
|
+
remove mobile types of interest from the structure
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
self.symprec = symprec
|
|
65
|
+
self.verbose = verbose
|
|
66
|
+
if atomic_types_mapper:
|
|
67
|
+
numbers = self._map_atomic_types(atomic_types_mapper, atoms.numbers)
|
|
68
|
+
atoms = atoms.copy()
|
|
69
|
+
atoms.numbers = numbers
|
|
70
|
+
specie = atomic_types_mapper[specie]
|
|
71
|
+
self.atoms = atoms.copy()
|
|
72
|
+
self.specie = specie
|
|
73
|
+
self.resolution = resolution
|
|
74
|
+
self.cell = self.atoms.cell
|
|
75
|
+
self.r_cut = r_cut
|
|
76
|
+
self.r_min = r_min
|
|
77
|
+
self.base = self.atoms[self.atoms.numbers != self.specie] if empty_framework else atoms.copy()
|
|
78
|
+
|
|
79
|
+
self._mesh = Mesh.from_atoms(self.base,
|
|
80
|
+
resolution = self.resolution,
|
|
81
|
+
symprec = self.symprec)
|
|
82
|
+
self.mesh_shape = self._mesh.mesh_shape
|
|
83
|
+
self.ir_grid_points, self.mapping = self._mesh.get_irreducible_mapping()
|
|
84
|
+
self.mesh_frac = self._mesh.addresses / (np.array(self._mesh.mesh_shape) - 1)
|
|
85
|
+
self.mesh_cart = np.dot(self.mesh_frac, self.base.cell)
|
|
86
|
+
|
|
87
|
+
self.min_dists, _ = nn_list(self.base.positions,
|
|
88
|
+
self.mesh_cart[self.ir_grid_points],
|
|
89
|
+
r_cut,
|
|
90
|
+
self.cell)
|
|
91
|
+
if self.verbose:
|
|
92
|
+
total_points = self.mesh_frac.shape[0]
|
|
93
|
+
irreducible_points = self.ir_grid_points.shape[0]
|
|
94
|
+
passed_filter = (self.min_dists > self.r_min).sum()
|
|
95
|
+
compression = total_points / passed_filter if passed_filter else np.nan
|
|
96
|
+
|
|
97
|
+
print("Mesh Summary")
|
|
98
|
+
print("────────────────────────────────────")
|
|
99
|
+
print(f" Mesh shape: {tuple(self.mesh_shape)}")
|
|
100
|
+
print(f" Symops: {len(self._mesh.rotations)}")
|
|
101
|
+
print(f" Total points: {total_points:,}")
|
|
102
|
+
print(f" Irreducible points: {irreducible_points:,}")
|
|
103
|
+
print(f" Irreducible points (r_min filter): {passed_filter:,}")
|
|
104
|
+
print(f" Compression ratio: {compression:6.2f}×")
|
|
105
|
+
print("────────────────────────────────────\n")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _map_atomic_types(self, atomic_types_mapper, numbers):
|
|
110
|
+
u,inv = np.unique(numbers,return_inverse = True)
|
|
111
|
+
return np.array([atomic_types_mapper[x] for x in u])[inv].reshape(numbers.shape)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@classmethod
|
|
115
|
+
def from_file(cls, file,
|
|
116
|
+
specie,
|
|
117
|
+
resolution = 0.25,
|
|
118
|
+
r_cut = 5.0,
|
|
119
|
+
r_min = 1.5,
|
|
120
|
+
symprec = 0.1,
|
|
121
|
+
atomic_types_mapper = None,
|
|
122
|
+
empty_framework = True,
|
|
123
|
+
):
|
|
124
|
+
"""
|
|
125
|
+
Create Grid object from the file.
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
----------
|
|
129
|
+
|
|
130
|
+
file: string
|
|
131
|
+
.xyz of .cfg file representing atomic structure
|
|
132
|
+
|
|
133
|
+
specie: int
|
|
134
|
+
atomic number of the mobile specie
|
|
135
|
+
|
|
136
|
+
resolution: float, 0.2 by default
|
|
137
|
+
spacing between points (in Angstroms)
|
|
138
|
+
|
|
139
|
+
r_cut: float
|
|
140
|
+
cutoff radius to find the first nearest neighbor for each grid point
|
|
141
|
+
|
|
142
|
+
r_min: float
|
|
143
|
+
blocking sphere radius
|
|
144
|
+
|
|
145
|
+
atomic_types_mapper: dict, optional
|
|
146
|
+
mapper of the species into atomic numbers
|
|
147
|
+
|
|
148
|
+
empty_framework: boolean, True by default
|
|
149
|
+
whether to remove mobile types of interest from the structure
|
|
150
|
+
|
|
151
|
+
symprec: None or float, 0.1 by default
|
|
152
|
+
symmetry precision
|
|
153
|
+
used to get symmetry operations for finding the irreducible mesh points
|
|
154
|
+
may reduce number of MLIP calculations by factor of 10-100
|
|
155
|
+
if None, the symmetry will not be used.
|
|
156
|
+
|
|
157
|
+
Returns
|
|
158
|
+
-------
|
|
159
|
+
Grid object
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
if file.split('.')[-1] == 'cfg':
|
|
163
|
+
atoms = read_cfg(file)[0]
|
|
164
|
+
else:
|
|
165
|
+
atoms = read(file)
|
|
166
|
+
return cls(atoms, specie, resolution=resolution,
|
|
167
|
+
symprec=symprec,
|
|
168
|
+
r_cut=r_cut, r_min=r_min, atomic_types_mapper=atomic_types_mapper,
|
|
169
|
+
empty_framework=empty_framework
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def construct_configurations(self, config_format = 'ase', filename = None):
|
|
175
|
+
"""
|
|
176
|
+
Construct atomic configurations for further calculations.
|
|
177
|
+
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
|
|
181
|
+
filename: string (Optional)
|
|
182
|
+
path to save .xyz of .cfg file with atomic configurations
|
|
183
|
+
|
|
184
|
+
config_format: string, "ase" by default, can be "pymatgen" or "ase"
|
|
185
|
+
data format of the created configurations (pymatgen's Structure of ASE's Atoms)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
Returns
|
|
189
|
+
-------
|
|
190
|
+
configurations: list of ASE's atoms object
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
configurations = []
|
|
194
|
+
if config_format == 'ase':
|
|
195
|
+
ir_mesh_cart = self.mesh_cart[self.ir_grid_points]
|
|
196
|
+
assert len(ir_mesh_cart) == len(self.min_dists)
|
|
197
|
+
for p, d in tqdm(zip(ir_mesh_cart, self.min_dists), desc = 'creating configurations'):
|
|
198
|
+
if d > self.r_min:
|
|
199
|
+
framework = self.base.copy()
|
|
200
|
+
framework.append(self.specie)
|
|
201
|
+
framework.positions[-1] = p
|
|
202
|
+
configurations.append(framework)
|
|
203
|
+
elif config_format == 'pymatgen':
|
|
204
|
+
base = AseAtomsAdaptor.get_structure(self.base)
|
|
205
|
+
ir_mesh_frac = self.mesh_frac[self.ir_grid_points]
|
|
206
|
+
for p, d in tqdm(zip(ir_mesh_frac, self.min_dists), desc = 'creating configurations'):
|
|
207
|
+
if d > self.r_min:
|
|
208
|
+
framework = base.copy()
|
|
209
|
+
framework.append(self.specie, coords = p)
|
|
210
|
+
configurations.append(framework)
|
|
211
|
+
else:
|
|
212
|
+
raise ValueError(f"Wrong config_format {config_format}")
|
|
213
|
+
|
|
214
|
+
if filename:
|
|
215
|
+
if config_format != 'ase':
|
|
216
|
+
raise ValueError('Only "ase" format is allowed for saving files')
|
|
217
|
+
if filename.split('.')[-1] == 'cfg':
|
|
218
|
+
write_cfg(filename, configurations)
|
|
219
|
+
else:
|
|
220
|
+
write(filename, configurations)
|
|
221
|
+
return configurations
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def load_energies(self, energies):
|
|
226
|
+
|
|
227
|
+
"""
|
|
228
|
+
Load energies obtained by any MLIP or structure-to-property model.
|
|
229
|
+
Should match order in created configurations.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
|
|
234
|
+
energies: np.array
|
|
235
|
+
calculated energies for the created configurations
|
|
236
|
+
"""
|
|
237
|
+
|
|
238
|
+
self.energies = energies
|
|
239
|
+
|
|
240
|
+
ir_distribution = np.ones_like(self.min_dists) * np.inf
|
|
241
|
+
ir_distribution[self.min_dists > self.r_min] = self.energies
|
|
242
|
+
|
|
243
|
+
self.distribution = np.nan_to_num(ir_distribution, copy = False, nan = np.inf)[self.mapping]
|
|
244
|
+
self.data = self.distribution.reshape(self.mesh_shape)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def read_processed_configurations(self, filename, file_format = 'xyz'):
|
|
248
|
+
|
|
249
|
+
"""
|
|
250
|
+
Read processed (by any MLIP) atomic configurations
|
|
251
|
+
with calculated energies.
|
|
252
|
+
|
|
253
|
+
Parameters
|
|
254
|
+
----------
|
|
255
|
+
|
|
256
|
+
filename: string
|
|
257
|
+
path to the processed .xyz of .cfg file
|
|
258
|
+
|
|
259
|
+
file_format: string, 'xyz' by default
|
|
260
|
+
format of the file
|
|
261
|
+
if 'cfg' will use custom function read_cfg() to read MLIP 2.0 generated data
|
|
262
|
+
otherwise will use ASE's read()
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
if file_format == 'cfg':
|
|
266
|
+
atoms_list = read_cfg(filename)
|
|
267
|
+
else:
|
|
268
|
+
atoms_list = read(filename, index = ':')
|
|
269
|
+
energies = np.array([atoms.get_potential_energy() for atoms in atoms_list])
|
|
270
|
+
del atoms_list
|
|
271
|
+
self.load_energies(energies)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def write_cube(self, filename):
|
|
276
|
+
|
|
277
|
+
"""
|
|
278
|
+
Write .cube file containing structural and MLIP distribution data.
|
|
279
|
+
|
|
280
|
+
Parameters
|
|
281
|
+
----------
|
|
282
|
+
|
|
283
|
+
filename: str
|
|
284
|
+
file name to write .cube
|
|
285
|
+
"""
|
|
286
|
+
|
|
287
|
+
data = self.data
|
|
288
|
+
nx, ny, nz = data.shape
|
|
289
|
+
with open(f'{filename}.cube', 'w') as f:
|
|
290
|
+
cube.write_cube(f, self.atoms, data = data[:nx-1, :ny-1, :nz-1])
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def write_grd(self, filename):
|
|
295
|
+
|
|
296
|
+
"""
|
|
297
|
+
Write MLIP distribution volumetric file for VESTA 3.0.
|
|
298
|
+
|
|
299
|
+
Parameters
|
|
300
|
+
----------
|
|
301
|
+
|
|
302
|
+
filename: str
|
|
303
|
+
file name to write .grd
|
|
304
|
+
"""
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
data = self.data
|
|
308
|
+
voxels = data.shape[0] - 1, data.shape[1] - 1, data.shape[2] - 1
|
|
309
|
+
cellpars = self.cell.cellpar()
|
|
310
|
+
with open(f'{filename}.grd' , 'w') as report:
|
|
311
|
+
comment = '# MLIP data made with gridmlip package: https://github.com/dembart/gridmlip'
|
|
312
|
+
report.write(comment + '\n')
|
|
313
|
+
report.write(''.join(str(p) + ' ' for p in cellpars).strip() + '\n')
|
|
314
|
+
report.write(''.join(str(v) + ' ' for v in voxels).strip() + '\n')
|
|
315
|
+
for i in range(voxels[0]):
|
|
316
|
+
for j in range(voxels[1]):
|
|
317
|
+
for k in range(voxels[2]):
|
|
318
|
+
val = data[i, j, k]
|
|
319
|
+
report.write(str(val) + '\n')
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def percolation_barriers(self, encut = 10.0):
|
|
324
|
+
"""
|
|
325
|
+
Calculate percolation barriers.
|
|
326
|
+
|
|
327
|
+
Parameters
|
|
328
|
+
----------
|
|
329
|
+
encut: float, 10.0 by default
|
|
330
|
+
upper bound for searching the barrier
|
|
331
|
+
"""
|
|
332
|
+
pl = Percolyze(self.data)
|
|
333
|
+
return pl.percolation_barriers(encut = encut)
|
|
@@ -24,7 +24,7 @@ def read_cfg(filename):
|
|
|
24
24
|
configurations = []
|
|
25
25
|
for i_s, i_e in tqdm(zip(np.where(np.array(text) == 'BEGIN_CFG\n')[0], np.where(np.array(text) == 'END_CFG\n')[0])):
|
|
26
26
|
subtext = text[i_s:i_e]
|
|
27
|
-
grade = None
|
|
27
|
+
grade = None # not used
|
|
28
28
|
results = {}
|
|
29
29
|
for i, line in enumerate(subtext):
|
|
30
30
|
if 'Size' in line:
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: gridmlip
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2
|
|
4
4
|
Summary: Grid-based method for calculating the percolation barrier of mobile species using machine learning interatomic potentials
|
|
5
5
|
Home-page: https://github.com/dembart/gridmlip
|
|
6
6
|
Author: Artem Dembitskiy
|
|
7
7
|
Author-email: art.dembitskiy@gmail.com
|
|
8
8
|
License: MIT
|
|
9
|
-
Keywords: MLIP,percolation barrier
|
|
9
|
+
Keywords: MLIP,percolation barrier,irreducible mesh
|
|
10
10
|
Platform: UNKNOWN
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -31,7 +31,6 @@ License-File: LICENSE
|
|
|
31
31
|
|
|
32
32
|
**gridmlip** is a library for calculating percolation barriers of mobile species in solids using grid-based method with machine learning interatomic potentials (MLIPs).
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
## Installation
|
|
36
35
|
|
|
37
36
|
```
|
|
@@ -53,7 +52,7 @@ Here we describe the pipeline in general. For a specific example, see [Notebooks
|
|
|
53
52
|
from gridmlip import Grid
|
|
54
53
|
|
|
55
54
|
atomic_types_mapper = {3:0, 31:1, 17:2}
|
|
56
|
-
|
|
55
|
+
grid = Grid.from_file('your.cif', specie = 3, r_min = 1.8,
|
|
57
56
|
atomic_types_mapper=atomic_types_mapper # optional
|
|
58
57
|
)
|
|
59
58
|
cfgs = grid.construct_configurations('data.cfg')
|
|
@@ -72,7 +71,7 @@ from gridmlip import Grid
|
|
|
72
71
|
|
|
73
72
|
grid = Grid.from_file('your.cif', specie = 3, r_min = 1.8)
|
|
74
73
|
grid.read_processed_configurations('processed_data.cfg', format = 'cfg')
|
|
75
|
-
grid.percolation_barriers()
|
|
74
|
+
barriers = grid.percolation_barriers()
|
|
76
75
|
```
|
|
77
76
|
|
|
78
77
|
#### Step #4: Write .grd or .cube file for visualization in VESTA 3.0
|
|
@@ -84,7 +83,8 @@ g.write_grd('test.grd')
|
|
|
84
83
|
## Notebooks
|
|
85
84
|
|
|
86
85
|
|
|
87
|
-
- [Using TensorNet model pre-trained on MatPES](notebooks/TensorNet_MatPES.ipynb)
|
|
86
|
+
- [Using TensorNet model pre-trained on MatPES](notebooks/TensorNet_MatPES.ipynb)
|
|
87
|
+
[](https://colab.research.google.com/drive/14gabZ-u19K-_I_e7-g67N8-xtPIN36Nw#sandboxMode=true&scrollTo=5TySp6C6UBoZ)
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
### How to cite
|
|
@@ -7,7 +7,7 @@ url = https://github.com/dembart/gridmlip
|
|
|
7
7
|
description = gridmlip
|
|
8
8
|
long_description = file: README.md
|
|
9
9
|
long_description_content_type = text/markdown
|
|
10
|
-
keywords = MLIP, percolation barrier
|
|
10
|
+
keywords = MLIP, percolation barrier, irreducible mesh
|
|
11
11
|
license = MIT
|
|
12
12
|
classifiers =
|
|
13
13
|
License :: OSI Approved :: BSD License
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name='gridmlip',
|
|
8
|
-
version='0.
|
|
8
|
+
version='0.2',
|
|
9
9
|
py_modules = ["gridmlip"],
|
|
10
10
|
install_requires = [
|
|
11
11
|
"pandas",
|
|
@@ -18,7 +18,7 @@ setuptools.setup(
|
|
|
18
18
|
author="Artem Dembitskiy",
|
|
19
19
|
author_email="art.dembitskiy@gmail.com",
|
|
20
20
|
description="Grid-based method for calculating the percolation barrier of mobile species using machine learning interatomic potentials",
|
|
21
|
-
key_words = ['percolation-barrier', '
|
|
21
|
+
key_words = ['percolation-barrier', 'UMLIP', 'ionic conductivity', 'diffusion'],
|
|
22
22
|
long_description=long_description,
|
|
23
23
|
long_description_content_type="text/markdown",
|
|
24
24
|
url="https://github.com/dembart/gridmlip",
|
gridmlip-0.1/gridmlip/core.py
DELETED
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from tqdm import tqdm
|
|
3
|
-
from ase.io import read, write, cube
|
|
4
|
-
from .utils import read_cfg, write_cfg
|
|
5
|
-
from ._neighborhood import nn_list
|
|
6
|
-
from ._percolation_analysis import Percolyze
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
__version__ = "0.1"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class Grid:
|
|
15
|
-
|
|
16
|
-
def __init__(self, atoms, specie = None, resolution = 0.25,
|
|
17
|
-
r_cut = 5.0, r_min = 1.5, atomic_types_mapper = None):
|
|
18
|
-
|
|
19
|
-
"""
|
|
20
|
-
Initialization.
|
|
21
|
-
|
|
22
|
-
Parameters
|
|
23
|
-
----------
|
|
24
|
-
|
|
25
|
-
atoms: ASE's Atoms object
|
|
26
|
-
atomic structure
|
|
27
|
-
|
|
28
|
-
specie: int
|
|
29
|
-
atomic number of the mobile specie
|
|
30
|
-
|
|
31
|
-
resolution: float, 0.2 by default
|
|
32
|
-
spacing between points (in Angstroms)
|
|
33
|
-
|
|
34
|
-
r_cut: float
|
|
35
|
-
cutoff radius to find the first nearest neighbor for each grid point
|
|
36
|
-
|
|
37
|
-
r_min: float
|
|
38
|
-
blocking sphere radius
|
|
39
|
-
|
|
40
|
-
atomic_types_mapper: dict, optional
|
|
41
|
-
mapper of atomic numbers into species used by MLIP
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
if atomic_types_mapper:
|
|
45
|
-
numbers = self._map_atomic_types(atomic_types_mapper, atoms.numbers)
|
|
46
|
-
atoms = atoms.copy()
|
|
47
|
-
atoms.numbers = numbers
|
|
48
|
-
specie = atomic_types_mapper[specie]
|
|
49
|
-
self.atoms = atoms.copy()
|
|
50
|
-
self.specie = specie
|
|
51
|
-
self.resolution = resolution
|
|
52
|
-
self.cell = self.atoms.cell
|
|
53
|
-
self._mesh(resolution)
|
|
54
|
-
self.base = self.atoms[self.atoms.numbers != self.specie]
|
|
55
|
-
self.min_dists, _ = nn_list(self.base.positions, self.mesh_cart, r_cut, self.cell)
|
|
56
|
-
self.r_cut = r_cut
|
|
57
|
-
self.r_min = r_min
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def _map_atomic_types(self, atomic_types_mapper, numbers):
|
|
62
|
-
u,inv = np.unique(numbers,return_inverse = True)
|
|
63
|
-
return np.array([atomic_types_mapper[x] for x in u])[inv].reshape(numbers.shape)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def _mesh(self, resolution):
|
|
68
|
-
|
|
69
|
-
"""
|
|
70
|
-
This method creates grid of equidistant points in 3D
|
|
71
|
-
with respect to the input resolution.
|
|
72
|
-
|
|
73
|
-
Parameters
|
|
74
|
-
----------
|
|
75
|
-
resolution: float, 0.2 by default
|
|
76
|
-
spacing between points (in Angstroms)
|
|
77
|
-
|
|
78
|
-
Returns
|
|
79
|
-
-------
|
|
80
|
-
mesh_cart: np.array
|
|
81
|
-
cartesian coordinates of meshgrid
|
|
82
|
-
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
a, b, c, _, _, _ = self.cell.cellpar()
|
|
86
|
-
nx, ny, nz = int(a // resolution), int(b // resolution), int(c // resolution)
|
|
87
|
-
x = np.linspace(0, 1, nx)
|
|
88
|
-
y = np.linspace(0, 1, ny)
|
|
89
|
-
z = np.linspace(0, 1, nz)
|
|
90
|
-
self.mesh_frac = np.stack(np.meshgrid(x, y, z, indexing='ij'), axis=-1).reshape(-1, 3)
|
|
91
|
-
self.mesh_cart = self.cell.cartesian_positions(self.mesh_frac)
|
|
92
|
-
self.size = (nx, ny, nz)
|
|
93
|
-
return self.mesh_cart
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
@classmethod
|
|
98
|
-
def from_file(cls, file, specie = None, resolution = 0.25,
|
|
99
|
-
r_cut = 5.0, r_min = 1.5, atomic_types_mapper = None):
|
|
100
|
-
"""
|
|
101
|
-
Create Grid object from the file.
|
|
102
|
-
|
|
103
|
-
Parameters
|
|
104
|
-
----------
|
|
105
|
-
|
|
106
|
-
file: string
|
|
107
|
-
.xyz of .cfg file representing atomic structure
|
|
108
|
-
|
|
109
|
-
specie: int
|
|
110
|
-
atomic number of the mobile specie
|
|
111
|
-
|
|
112
|
-
resolution: float, 0.2 by default
|
|
113
|
-
spacing between points (in Angstroms)
|
|
114
|
-
|
|
115
|
-
r_cut: float
|
|
116
|
-
cutoff radius to find the first nearest neighbor for each grid point
|
|
117
|
-
|
|
118
|
-
r_min: float
|
|
119
|
-
blocking sphere radius
|
|
120
|
-
|
|
121
|
-
atomic_types_mapper: dict, optional
|
|
122
|
-
mapper of the species into atomic numbers
|
|
123
|
-
|
|
124
|
-
Returns
|
|
125
|
-
-------
|
|
126
|
-
Grid object
|
|
127
|
-
"""
|
|
128
|
-
|
|
129
|
-
if file.split('.')[-1] == 'cfg':
|
|
130
|
-
atoms = read_cfg(file)[0]
|
|
131
|
-
else:
|
|
132
|
-
atoms = read(file)
|
|
133
|
-
return cls(atoms, specie, resolution=resolution,
|
|
134
|
-
r_cut = r_cut, r_min = r_min, atomic_types_mapper = atomic_types_mapper)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def construct_configurations(self, filename = None):
|
|
139
|
-
"""
|
|
140
|
-
Construct atomic configurations for further calculations.
|
|
141
|
-
|
|
142
|
-
Parameters
|
|
143
|
-
----------
|
|
144
|
-
|
|
145
|
-
filename: string (Optional)
|
|
146
|
-
path to save .xyz of .cfg file with atomic configurations
|
|
147
|
-
|
|
148
|
-
Returns
|
|
149
|
-
-------
|
|
150
|
-
configurations: list of ASE's atoms object
|
|
151
|
-
"""
|
|
152
|
-
|
|
153
|
-
configurations = []
|
|
154
|
-
for p, d in tqdm(zip(self.mesh_cart, self.min_dists), desc = 'creating configurations'):
|
|
155
|
-
if d > self.r_min:
|
|
156
|
-
framework = self.base.copy()
|
|
157
|
-
framework.append(self.specie)
|
|
158
|
-
framework.positions[-1] = p
|
|
159
|
-
configurations.append(framework)
|
|
160
|
-
|
|
161
|
-
if filename:
|
|
162
|
-
if filename.split('.')[-1] == 'cfg':
|
|
163
|
-
write_cfg(filename, configurations)
|
|
164
|
-
else:
|
|
165
|
-
write(filename, configurations)
|
|
166
|
-
return configurations
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
def load_energies(self, energies):
|
|
171
|
-
|
|
172
|
-
"""
|
|
173
|
-
Load energies obtained by any MLIP or structure-to-property model.
|
|
174
|
-
Should match order in created configurations.
|
|
175
|
-
|
|
176
|
-
Parameters
|
|
177
|
-
----------
|
|
178
|
-
|
|
179
|
-
energies: np.array
|
|
180
|
-
calculated energies for the created configurations
|
|
181
|
-
"""
|
|
182
|
-
|
|
183
|
-
self.energies = energies
|
|
184
|
-
self.distribution = np.ones_like(self.min_dists) * np.inf
|
|
185
|
-
self.distribution[self.min_dists > self.r_min] = self.energies
|
|
186
|
-
self.distribution = np.nan_to_num(self.distribution, copy = False, nan = np.inf)
|
|
187
|
-
self.data = self.distribution.reshape(self.size)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
def read_processed_configurations(self, filename, format = 'xyz'):
|
|
191
|
-
|
|
192
|
-
"""
|
|
193
|
-
Read processed (by any MLIP) atomic configurations
|
|
194
|
-
with calculated energies.
|
|
195
|
-
|
|
196
|
-
Parameters
|
|
197
|
-
----------
|
|
198
|
-
|
|
199
|
-
filename: string
|
|
200
|
-
path to the processed .xyz of .cfg file
|
|
201
|
-
"""
|
|
202
|
-
|
|
203
|
-
if format == 'cfg':
|
|
204
|
-
atoms_list = read_cfg(filename)
|
|
205
|
-
else:
|
|
206
|
-
atoms_list = read(filename, index = ':')
|
|
207
|
-
self.energies = np.array([atoms.get_potential_energy() for atoms in atoms_list])
|
|
208
|
-
del atoms_list
|
|
209
|
-
self.distribution = np.ones_like(self.min_dists) * np.inf
|
|
210
|
-
self.distribution[self.min_dists > self.r_min] = self.energies
|
|
211
|
-
self.distribution = np.nan_to_num(self.distribution, copy = False, nan = np.inf)
|
|
212
|
-
self.data = self.distribution.reshape(self.size)
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
def write_cube(self, filename):
|
|
217
|
-
|
|
218
|
-
"""
|
|
219
|
-
Write .cube file containing structural and MLIP distribution data.
|
|
220
|
-
|
|
221
|
-
Parameters
|
|
222
|
-
----------
|
|
223
|
-
|
|
224
|
-
filename: str
|
|
225
|
-
file name to write .cube
|
|
226
|
-
"""
|
|
227
|
-
|
|
228
|
-
data = self.data
|
|
229
|
-
nx, ny, nz = data.shape
|
|
230
|
-
with open(f'{filename}.cube', 'w') as f:
|
|
231
|
-
cube.write_cube(f, self.atoms, data = data[:nx-1, :ny-1, :nz-1])
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
def write_grd(self, filename):
|
|
236
|
-
|
|
237
|
-
"""
|
|
238
|
-
Write MLIP distribution volumetric file for VESTA 3.0.
|
|
239
|
-
|
|
240
|
-
Parameters
|
|
241
|
-
----------
|
|
242
|
-
|
|
243
|
-
filename: str
|
|
244
|
-
file name to write .grd
|
|
245
|
-
"""
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
data = self.data
|
|
249
|
-
voxels = data.shape[0] - 1, data.shape[1] - 1, data.shape[2] - 1
|
|
250
|
-
cellpars = self.cell.cellpar()
|
|
251
|
-
with open(f'{filename}.grd' , 'w') as report:
|
|
252
|
-
comment = '# MLIP data made with gridmlip package: https://github.com/dembart/gridmlip'
|
|
253
|
-
report.write(comment + '\n')
|
|
254
|
-
report.write(''.join(str(p) + ' ' for p in cellpars).strip() + '\n')
|
|
255
|
-
report.write(''.join(str(v) + ' ' for v in voxels).strip() + '\n')
|
|
256
|
-
for i in range(voxels[0]):
|
|
257
|
-
for j in range(voxels[1]):
|
|
258
|
-
for k in range(voxels[2]):
|
|
259
|
-
val = data[i, j, k]
|
|
260
|
-
report.write(str(val) + '\n')
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
def percolation_barriers(self, encut = 10.0):
|
|
265
|
-
"""
|
|
266
|
-
Calculate percolation barriers.
|
|
267
|
-
|
|
268
|
-
Parameters
|
|
269
|
-
----------
|
|
270
|
-
encut: float, 10.0 by default
|
|
271
|
-
upper bound for searching the barrier
|
|
272
|
-
"""
|
|
273
|
-
pl = Percolyze(self.data)
|
|
274
|
-
return pl.percolation_barriers(encut = encut)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|