fastatomstruct 0.7.4__cp313-none-win_amd64.whl
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.
- fastatomstruct/__init__.py +323 -0
- fastatomstruct/__init__.pyi +2196 -0
- fastatomstruct/fastatomstruct.cp313-win_amd64.pyd +0 -0
- fastatomstruct-0.7.4.dist-info/METADATA +93 -0
- fastatomstruct-0.7.4.dist-info/RECORD +7 -0
- fastatomstruct-0.7.4.dist-info/WHEEL +4 -0
- fastatomstruct-0.7.4.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
2
|
+
from time import time
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
from ase import Atoms
|
|
6
|
+
from .fastatomstruct import *
|
|
7
|
+
from tidynamics import msd
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def chunks(indices: List[int], n: int):
|
|
11
|
+
"""Yield successive chunks from list of atoms."""
|
|
12
|
+
for i in range(0, len(indices), n):
|
|
13
|
+
yield indices[i : i + n]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def ipar(
|
|
17
|
+
func: Callable, atoms: List[Atoms], *args: List[Any], **kwargs: Dict[Any, Any]
|
|
18
|
+
) -> List[Any]:
|
|
19
|
+
"""Image-based parallelization.
|
|
20
|
+
|
|
21
|
+
The calculation of many structural quantities is parallelized over atoms.
|
|
22
|
+
However, image-based parallelization (or a mixture of both) can be more efficient
|
|
23
|
+
in some cases. This function makes using this parallelization layer quite easy.
|
|
24
|
+
You can just use it as a simple wrapper around other functions implemented in
|
|
25
|
+
`fastatomstruct` (see example below). **This function needs a working installation
|
|
26
|
+
of the MPI4Py package!** You can set the `RAYON_NUM_THREADS` enviroment variable
|
|
27
|
+
to control the number of threads.
|
|
28
|
+
|
|
29
|
+
Arguments:
|
|
30
|
+
func (Callable): Some function from the `fastatomstruct` package
|
|
31
|
+
atoms (List[Atoms]): List of ASE configurations
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
List of results; type depends on the output of func
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
|
|
38
|
+
The exemplary file "Sb-1.00-300-100.traj" `can be found here <https://zivgitlab.uni-muenster.de/ag-salinga/fastatomstruct/-/raw/master/regressiontesting/Structures/Sb-1.00-300-100.traj>`_.
|
|
39
|
+
The code below needs to be run e.g. with `mpirun -n 2 test.py`. In this case,
|
|
40
|
+
two processes will be used.
|
|
41
|
+
|
|
42
|
+
>>> import fastatomstruct as fs
|
|
43
|
+
>>> from ase import io
|
|
44
|
+
>>> atoms = io.read("Sb-1.00-300-100.traj", index=":2")
|
|
45
|
+
>>> print(fs.ipar(fs.q_tetrahedral, atoms, 3.2, 3))
|
|
46
|
+
[array([6, 3, 4, 2, 4, 3, 3, 2, 3, 5, 3, 3, 3, 3, 4, 4, 4, 5, 4, 3, 3, 3,
|
|
47
|
+
3, 3, 4, 4, 4, 4, 3, 3, 3, 4, 3, 5, 3, 3, 4, 4, 2, 4, 4, 3, 4, 3,
|
|
48
|
+
3, 4, 5, 3, 5, 3, 2, 3, 3, 4, 4, 4, 3, 3, 3, 3, 3, 2, 4, 4, 4, 4,
|
|
49
|
+
4, 4, 4, 3, 3, 5, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3,
|
|
50
|
+
4, 5, 4, 4, 3, 4, 3, 3, 3, 4, 3, 4, 3, 2, 4, 4, 3, 3, 3, 3, 4, 4,
|
|
51
|
+
4, 3, 3, 3, 3, 4, 4, 4, 2, 2, 4, 3, 5, 2, 2, 5, 3, 4, 3, 3, 4, 4,
|
|
52
|
+
4, 4, 4, 4, 5, 3, 5, 5, 3, 3, 3, 4, 3, 4, 3, 5, 3, 4, 3, 3, 4, 4,
|
|
53
|
+
2, 3, 2, 2, 3, 2, 4, 2, 3, 3, 4, 4, 4, 3, 4, 3, 4, 5, 3, 4, 2, 4,
|
|
54
|
+
3, 5, 3, 4, 3, 4, 3, 3, 2, 4, 3, 3, 3, 3, 2, 4, 4, 3, 3, 3, 3, 4,
|
|
55
|
+
3, 3, 5, 4, 3, 3, 4, 3, 2, 4, 3, 2, 3, 3, 3, 4, 4, 3, 3, 3, 4, 4,
|
|
56
|
+
5, 6, 3, 3, 3, 4, 4, 2, 3, 4, 3, 3, 3, 3, 4, 2, 3, 3, 2, 3, 4, 3,
|
|
57
|
+
3, 4, 3, 4, 3, 4, 2, 3, 4, 3, 3, 3, 3, 5, 3, 4, 3, 4, 4, 3, 4, 3,
|
|
58
|
+
4, 4, 4, 3, 4, 5, 3, 3, 4, 5, 4, 4, 3, 2, 3, 3, 3, 5, 3, 4, 3, 3,
|
|
59
|
+
4, 2, 1, 2, 3, 4, 3, 4, 4, 3, 4, 3, 4, 3, 4, 5, 3, 2, 3, 3, 3, 3,
|
|
60
|
+
3, 3, 3, 4, 4, 4, 2, 4, 4, 3, 4, 4, 3, 4, 4, 3, 3, 3, 3, 5, 3, 4,
|
|
61
|
+
3, 4, 3, 3, 5, 3, 3, 2, 5, 3, 4, 3, 3, 4, 3, 4, 5, 3, 5, 4, 2, 4,
|
|
62
|
+
3, 2, 3, 4, 4, 4, 3, 3, 4, 4, 3, 4, 5, 3, 3, 4, 2, 4, 3, 4, 3, 5,
|
|
63
|
+
3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 5, 3, 3, 3, 4, 4, 3, 4, 3, 4, 4, 2,
|
|
64
|
+
4, 4, 2, 3, 3, 3, 3, 4, 4, 4, 3, 3, 4, 5, 4, 3, 3, 4, 4, 4, 2, 4,
|
|
65
|
+
3, 4, 4, 3, 3, 4, 3, 3, 3, 4, 5, 2, 3, 4, 3, 3, 4, 2, 3, 2, 4, 4,
|
|
66
|
+
3, 3, 3, 4, 4, 5, 5, 3, 4, 6, 3, 2, 3, 3, 4, 5, 3, 4, 3, 3, 3, 3,
|
|
67
|
+
5, 3, 4, 3, 2, 4, 4, 3, 3, 4, 3, 4, 3, 3, 3, 2, 5, 4, 4, 3, 3, 2,
|
|
68
|
+
4, 4, 3, 3, 3, 3, 3, 3, 3, 5, 3, 2, 3, 4, 3, 4, 3, 4, 4, 3, 4, 4,
|
|
69
|
+
5, 3, 4, 3, 3, 4, 3, 3, 3, 5, 4, 4, 3, 4, 2, 4, 4, 3, 3, 2, 3, 3,
|
|
70
|
+
3, 4, 3, 4, 3, 3, 4, 4, 3, 3, 3, 4, 3, 3, 4, 4, 2, 3, 3, 4, 3, 4,
|
|
71
|
+
3, 4, 3, 3, 2, 4, 5, 2, 4, 3, 5, 3, 3, 3, 3, 3, 3, 4, 3, 2, 2, 4,
|
|
72
|
+
3, 5, 3, 3, 4, 3, 3, 3, 3, 3, 4, 3, 4, 5, 3, 4, 4, 4, 2, 2, 5, 5,
|
|
73
|
+
5, 3, 1, 2, 3, 2, 4, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3,
|
|
74
|
+
4, 4, 4, 3, 3, 3, 4, 3, 3, 5, 4, 2, 5, 2, 3, 5, 3, 3, 3, 3, 4, 3,
|
|
75
|
+
2, 3, 5, 4, 4, 2, 3, 3, 3, 4, 4, 3, 5, 2, 4, 3, 3, 3, 4, 4, 4, 3,
|
|
76
|
+
2, 4, 3, 3, 3, 3, 6, 3, 4, 4, 3, 4, 3, 3, 4, 3, 2, 4, 3, 3, 3, 2,
|
|
77
|
+
5, 2, 2, 4, 3, 4, 5, 2, 4, 4, 4, 3, 3, 4, 2, 4, 2, 3, 3, 4, 4, 4,
|
|
78
|
+
3, 3, 4, 2, 4, 3, 5, 3, 4, 4, 4, 3, 3, 5, 4, 4, 3, 3, 5, 3, 3, 3,
|
|
79
|
+
3, 3], dtype=uint64), array([5, 3, 4, 3, 3, 2, 4, 4, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 5,
|
|
80
|
+
3, 3, 3, 3, 4, 4, 5, 5, 4, 3, 4, 5, 3, 3, 3, 4, 2, 3, 2, 3, 4, 3,
|
|
81
|
+
3, 4, 4, 3, 4, 3, 3, 3, 3, 3, 4, 4, 3, 2, 3, 2, 3, 4, 4, 3, 4, 3,
|
|
82
|
+
5, 4, 4, 4, 3, 3, 3, 5, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 4, 2, 3,
|
|
83
|
+
4, 3, 3, 2, 3, 3, 3, 3, 4, 4, 4, 4, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3,
|
|
84
|
+
3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 2, 3, 1, 4, 3, 3, 4, 3, 3, 4, 3,
|
|
85
|
+
4, 3, 4, 2, 3, 3, 4, 3, 2, 2, 3, 2, 3, 4, 4, 4, 3, 5, 2, 3, 4, 4,
|
|
86
|
+
4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 4, 1, 3, 5, 2, 4, 4, 4, 4, 3, 3,
|
|
87
|
+
2, 4, 2, 3, 3, 3, 4, 4, 2, 4, 3, 2, 3, 3, 2, 3, 3, 4, 5, 4, 4, 4,
|
|
88
|
+
3, 3, 4, 3, 3, 3, 2, 3, 4, 2, 3, 2, 3, 4, 2, 3, 3, 3, 3, 3, 3, 3,
|
|
89
|
+
5, 3, 3, 4, 3, 4, 3, 2, 3, 3, 3, 4, 3, 4, 5, 3, 5, 5, 3, 3, 4, 4,
|
|
90
|
+
3, 4, 3, 4, 4, 4, 3, 3, 5, 3, 3, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3,
|
|
91
|
+
4, 4, 5, 3, 3, 4, 5, 3, 4, 3, 3, 4, 2, 2, 3, 3, 3, 3, 5, 4, 3, 5,
|
|
92
|
+
4, 3, 3, 3, 4, 4, 4, 2, 3, 3, 4, 2, 3, 3, 2, 2, 2, 2, 3, 2, 3, 4,
|
|
93
|
+
3, 3, 4, 3, 3, 5, 3, 4, 4, 4, 3, 5, 2, 3, 4, 3, 3, 2, 4, 4, 5, 2,
|
|
94
|
+
3, 4, 3, 3, 4, 5, 4, 3, 3, 4, 2, 4, 4, 3, 3, 3, 4, 3, 4, 4, 4, 3,
|
|
95
|
+
3, 2, 3, 3, 3, 5, 2, 4, 4, 4, 4, 3, 4, 2, 3, 3, 3, 4, 3, 3, 5, 5,
|
|
96
|
+
3, 3, 3, 3, 2, 4, 4, 3, 4, 3, 4, 3, 4, 3, 3, 4, 3, 3, 4, 4, 3, 2,
|
|
97
|
+
2, 3, 2, 3, 2, 3, 3, 2, 4, 4, 3, 2, 4, 3, 4, 3, 3, 4, 2, 4, 4, 2,
|
|
98
|
+
3, 5, 3, 2, 3, 4, 3, 4, 4, 4, 3, 4, 3, 2, 3, 3, 2, 4, 3, 4, 2, 4,
|
|
99
|
+
3, 3, 4, 5, 3, 4, 4, 3, 4, 5, 4, 3, 2, 4, 4, 4, 3, 5, 3, 2, 3, 2,
|
|
100
|
+
3, 2, 3, 3, 3, 2, 4, 3, 3, 3, 4, 4, 4, 5, 3, 3, 4, 4, 4, 3, 3, 4,
|
|
101
|
+
3, 5, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 4, 4, 3, 2, 4, 3, 4, 4, 4, 2,
|
|
102
|
+
5, 4, 3, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3,
|
|
103
|
+
2, 1, 3, 3, 3, 3, 4, 4, 3, 2, 2, 4, 4, 2, 4, 4, 3, 2, 4, 4, 3, 4,
|
|
104
|
+
4, 5, 4, 4, 2, 3, 3, 4, 4, 1, 5, 3, 3, 3, 3, 2, 3, 3, 3, 3, 4, 3,
|
|
105
|
+
4, 5, 3, 3, 4, 3, 5, 3, 3, 4, 4, 2, 4, 4, 3, 2, 4, 5, 3, 4, 4, 5,
|
|
106
|
+
1, 3, 4, 3, 3, 3, 4, 4, 4, 3, 3, 2, 4, 3, 3, 4, 4, 3, 4, 3, 5, 3,
|
|
107
|
+
3, 4, 3, 3, 3, 3, 2, 2, 5, 4, 4, 4, 4, 3, 3, 3, 2, 3, 3, 3, 3, 3,
|
|
108
|
+
3, 3, 4, 4, 4, 3, 3, 5, 4, 3, 3, 4, 5, 3, 5, 4, 4, 4, 3, 4, 4, 3,
|
|
109
|
+
4, 4, 3, 4, 4, 4, 5, 2, 3, 3, 5, 4, 3, 3, 3, 3, 4, 2, 3, 3, 4, 3,
|
|
110
|
+
3, 5, 4, 5, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5,
|
|
111
|
+
4, 4, 3, 3, 4, 4, 4, 3, 2, 3, 3, 3, 2, 4, 3, 4, 3, 4, 3, 3, 2, 4,
|
|
112
|
+
4, 3], dtype=uint64)]
|
|
113
|
+
"""
|
|
114
|
+
from mpi4py import MPI
|
|
115
|
+
|
|
116
|
+
comm = MPI.COMM_WORLD
|
|
117
|
+
rank = comm.Get_rank()
|
|
118
|
+
|
|
119
|
+
if rank == 0:
|
|
120
|
+
print("\nImage parallelization report\n" + "----------------------------")
|
|
121
|
+
|
|
122
|
+
if rank == 0:
|
|
123
|
+
res_full, t0_f = [], time()
|
|
124
|
+
|
|
125
|
+
for i, c in enumerate(chunks(list(range(len(atoms))), comm.size)):
|
|
126
|
+
while len(c) < comm.size:
|
|
127
|
+
c.append(None)
|
|
128
|
+
|
|
129
|
+
if rank == 0:
|
|
130
|
+
per = (len(c) - np.count_nonzero([ci is None for ci in c])) / len(c)
|
|
131
|
+
t0 = time()
|
|
132
|
+
if c[rank] is not None:
|
|
133
|
+
a = atoms[c[rank]]
|
|
134
|
+
res = func(a, *args, **kwargs)
|
|
135
|
+
else:
|
|
136
|
+
res = None
|
|
137
|
+
|
|
138
|
+
res = comm.gather(res, root=0)
|
|
139
|
+
if rank == 0:
|
|
140
|
+
t = time() - t0
|
|
141
|
+
print(f"Chunk {i + 1}: {per * 100:03.2f}% | {t:.2f} s")
|
|
142
|
+
res_full.extend(res)
|
|
143
|
+
|
|
144
|
+
if rank == 0:
|
|
145
|
+
for i in range(len(res_full) - 1, -1, -1):
|
|
146
|
+
if res_full[i] is None:
|
|
147
|
+
del res_full[i]
|
|
148
|
+
print("----------------------------")
|
|
149
|
+
print(f"Total: {(time() - t0_f):.2f} s\n")
|
|
150
|
+
else:
|
|
151
|
+
res_full = None
|
|
152
|
+
|
|
153
|
+
return res_full
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def static_structure_factor(
|
|
157
|
+
atoms: List[Atoms],
|
|
158
|
+
q: np.ndarray,
|
|
159
|
+
r_max: float,
|
|
160
|
+
n_bins: int,
|
|
161
|
+
filter: Optional[Filter] = None,
|
|
162
|
+
) -> np.ndarray:
|
|
163
|
+
"""Static structure factor, as calculated from the RDF.
|
|
164
|
+
|
|
165
|
+
For isotropic systems, the static structure factor can be calculated using
|
|
166
|
+
|
|
167
|
+
.. math::
|
|
168
|
+
|
|
169
|
+
S(q) = q + 4 \pi \\rho \int_0^\infty r (g(r) - 1) \\frac{\sin{qr}}{q} dr,
|
|
170
|
+
|
|
171
|
+
with :math:`q` the absolute value of the reciprocal vector and :math:`g(r)`
|
|
172
|
+
the radial distribution function.
|
|
173
|
+
|
|
174
|
+
Arguments:
|
|
175
|
+
atoms (ase.Atoms or List[ase.Atoms]): Atoms object(s) from ASE
|
|
176
|
+
q (np.ndarray): Array with values of :math:`q`
|
|
177
|
+
r_max (float): Cutoff radius for calculating the radial distribution function
|
|
178
|
+
n_bins (int): Number of bins for calculating the radial distribution function
|
|
179
|
+
filter (fastatomstruct.Filter): Filter applied to the atoms
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
np.ndarray of floats with values of :math:`S(q)`
|
|
183
|
+
|
|
184
|
+
Examples
|
|
185
|
+
--------
|
|
186
|
+
|
|
187
|
+
The exemplary file "Sb540.traj" `can be found here <https://zivgitlab.uni-muenster.de/ag-salinga/fastatomstruct/-/raw/master/regressiontesting/Structures/Sb540.traj>`_.
|
|
188
|
+
|
|
189
|
+
>>> import fastatomstruct as fs
|
|
190
|
+
>>> import numpy as np
|
|
191
|
+
>>> from ase import io
|
|
192
|
+
>>> atoms = io.read("Sb540.traj")
|
|
193
|
+
>>> q = np.linspace(0.1, 10, 100)
|
|
194
|
+
>>> fs.static_structure_factor(atoms, q, 10, 100)
|
|
195
|
+
array([ 2.38192150e+00, 1.52370665e+00, 6.46487735e-01, 1.56760937e-01,
|
|
196
|
+
1.20323650e-01, 2.76121498e-01, 2.99045859e-01, 8.31513912e-02,
|
|
197
|
+
-1.90316248e-01, -2.47717736e-01, -2.64701388e-03, 3.32212401e-01,
|
|
198
|
+
4.12935073e-01, 8.23095798e-02, -4.33279251e-01, -6.37901553e-01,
|
|
199
|
+
-1.34285685e-01, 1.02734748e+00, 2.30245828e+00, 2.97459962e+00,
|
|
200
|
+
2.63495154e+00, 1.47795768e+00, 1.95200237e-01, -4.64900582e-01,
|
|
201
|
+
-1.67915414e-01, 8.23636781e-01, 1.86264373e+00, 2.35654147e+00,
|
|
202
|
+
2.12370925e+00, 1.44199006e+00, 7.96081378e-01, 5.32944085e-01,
|
|
203
|
+
6.68269224e-01, 9.48456321e-01, 1.08128433e+00, 9.46956728e-01,
|
|
204
|
+
6.48174186e-01, 3.96442496e-01, 3.47315244e-01, 5.10293291e-01,
|
|
205
|
+
7.78951127e-01, 1.03029307e+00, 1.20441057e+00, 1.31266361e+00,
|
|
206
|
+
1.39040807e+00, 1.44917566e+00, 1.46855988e+00, 1.42365507e+00,
|
|
207
|
+
1.31353477e+00, 1.16335792e+00, 1.00360668e+00, 8.51865026e-01,
|
|
208
|
+
7.15775063e-01, 6.10344434e-01, 5.65892631e-01, 6.11851235e-01,
|
|
209
|
+
7.47484590e-01, 9.27629136e-01, 1.08202234e+00, 1.15793322e+00,
|
|
210
|
+
1.15344778e+00, 1.11384177e+00, 1.09289068e+00, 1.10994910e+00,
|
|
211
|
+
1.13732027e+00, 1.12748028e+00, 1.05705663e+00, 9.51231920e-01,
|
|
212
|
+
8.68843102e-01, 8.60366739e-01, 9.31803892e-01, 1.04118569e+00,
|
|
213
|
+
1.12787974e+00, 1.15066369e+00, 1.10732762e+00, 1.02633983e+00,
|
|
214
|
+
9.43038802e-01, 8.80934999e-01, 8.48915518e-01, 8.48906335e-01,
|
|
215
|
+
8.81116102e-01, 9.40582699e-01, 1.01098283e+00, 1.06655300e+00,
|
|
216
|
+
1.08547102e+00, 1.06556309e+00, 1.02825219e+00, 1.00491362e+00,
|
|
217
|
+
1.01457151e+00, 1.05006526e+00, 1.08377161e+00, 1.08843837e+00,
|
|
218
|
+
1.05674417e+00, 1.00482220e+00, 9.58470246e-01, 9.34461644e-01,
|
|
219
|
+
9.31941120e-01, 9.38971544e-01, 9.46172717e-01, 9.54459745e-01])
|
|
220
|
+
"""
|
|
221
|
+
if isinstance(atoms, list):
|
|
222
|
+
rdf = []
|
|
223
|
+
for a in atoms:
|
|
224
|
+
r, rdf_i = radial_distribution_function(a, r_max, n_bins, filter)
|
|
225
|
+
rdf.append(rdf_i)
|
|
226
|
+
rdf = np.mean(rdf, axis=0)
|
|
227
|
+
rho = len(atoms[0]) / atoms[0].get_volume()
|
|
228
|
+
else:
|
|
229
|
+
r, rdf = radial_distribution_function(atoms, r_max, n_bins)
|
|
230
|
+
rho = len(atoms) / atoms.get_volume()
|
|
231
|
+
|
|
232
|
+
integral = np.zeros(len(q))
|
|
233
|
+
for i, qi in enumerate(q):
|
|
234
|
+
integrand = r[1:] * np.sin(qi * r[1:]) * (rdf[1:] - 1)
|
|
235
|
+
integral[i] = np.trapz(integrand, r[1:])
|
|
236
|
+
return 1 + 4 * np.pi * rho / q * integral
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def __convert_pos(atoms) -> List[np.ndarray]:
|
|
240
|
+
pos = []
|
|
241
|
+
for i in range(len(atoms[0])):
|
|
242
|
+
pos_temp = np.empty((len(atoms), 3))
|
|
243
|
+
for j, a in enumerate(atoms):
|
|
244
|
+
pos_temp[j, :] = a.positions[i, :]
|
|
245
|
+
pos.append(pos_temp)
|
|
246
|
+
return pos
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def mean_squared_displacement(atoms: List[Atoms]) -> np.ndarray:
|
|
250
|
+
"""Mean squared displacment of a trajectory.
|
|
251
|
+
|
|
252
|
+
The MSD is calculated using the `tidynamics` package. It is defined as
|
|
253
|
+
|
|
254
|
+
.. math::
|
|
255
|
+
|
|
256
|
+
\\mathrm{MSD} = \\frac{1}{N} \sum_{i = 1}^N |\\vec{x}_i(t) - \\vec{x}_i(0)|^2,
|
|
257
|
+
|
|
258
|
+
where the :math:`\\vec{x}_i(t)` are the atomic positions at time :math:`t`.
|
|
259
|
+
|
|
260
|
+
Arguments:
|
|
261
|
+
atoms (List[ase.Atoms]): Trajectory, atoms objects from ASE
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
NumPy Array of floats containing the mean squared displacement
|
|
265
|
+
|
|
266
|
+
Examples
|
|
267
|
+
--------
|
|
268
|
+
|
|
269
|
+
The exemplary file "Sb-1.00-300-100.traj" `can be found here <https://zivgitlab.uni-muenster.de/ag-salinga/fastatomstruct/-/raw/master/regressiontesting/Structures/Sb-1.00-300-100.traj>`_.
|
|
270
|
+
|
|
271
|
+
>>> import fastatomstruct as fs
|
|
272
|
+
>>> from ase import io
|
|
273
|
+
>>> atoms = io.read("Sb-1.00-300-100.traj", index=":")
|
|
274
|
+
>>> fs.mean_squared_displacement(atoms)
|
|
275
|
+
array([-1.64608547e-11, 8.99267872e-02, 1.44127662e-01, ...,
|
|
276
|
+
2.02885143e+00, 2.02005773e+00, 2.01818494e+00])
|
|
277
|
+
"""
|
|
278
|
+
return squared_displacement(atoms).mean(axis=0)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def squared_displacement(atoms: List[Atoms]) -> np.ndarray:
|
|
282
|
+
"""Squared displacment of a trajectory.
|
|
283
|
+
|
|
284
|
+
The SD is calculated using the `tidynamics` package. It is defined as
|
|
285
|
+
|
|
286
|
+
.. math::
|
|
287
|
+
|
|
288
|
+
\\mathrm{SD}_i = |\vec{x}_i(t) - \vec{x}_i(0)|^2,
|
|
289
|
+
|
|
290
|
+
where the :math:`\vec{x}_i(t)` are the atomic positions at time :math:`t`.
|
|
291
|
+
|
|
292
|
+
Arguments:
|
|
293
|
+
atoms (List[ase.Atoms]): Trajectory, atoms objects from ASE
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
NumPy Array of floats containing the mean squared displacement
|
|
297
|
+
|
|
298
|
+
Examples
|
|
299
|
+
--------
|
|
300
|
+
|
|
301
|
+
The exemplary file "Sb-1.00-300-100.traj" `can be found here <https://zivgitlab.uni-muenster.de/ag-salinga/fastatomstruct/-/raw/master/regressiontesting/Structures/Sb-1.00-300-100.traj>`_.
|
|
302
|
+
|
|
303
|
+
>>> import fastatomstruct as fs
|
|
304
|
+
>>> from ase import io
|
|
305
|
+
>>> atoms = io.read("Sb-1.00-300-100.traj", index=":")
|
|
306
|
+
>>> fs.mean_squared_displacement(atoms)
|
|
307
|
+
array([[-2.91038305e-11, 8.38161177e-02, 1.25422533e-01, ...,
|
|
308
|
+
6.15651363e-01, 5.27809637e-01, 6.19426924e-01],
|
|
309
|
+
[ 0.00000000e+00, 9.27498088e-02, 1.52887610e-01, ...,
|
|
310
|
+
1.07754904e+00, 1.10512104e+00, 1.46645886e+00],
|
|
311
|
+
[-1.16415322e-10, 8.61089322e-02, 1.37081905e-01, ...,
|
|
312
|
+
1.27085909e+00, 1.18840340e+00, 9.64727558e-01],
|
|
313
|
+
...,
|
|
314
|
+
[-4.65661287e-10, 9.55223907e-02, 1.56593970e-01, ...,
|
|
315
|
+
4.45991428e-01, 2.80684893e-01, 1.91919705e-01],
|
|
316
|
+
[ 0.00000000e+00, 8.69368854e-02, 1.34933834e-01, ...,
|
|
317
|
+
4.86719506e-01, 3.47152810e-01, 5.66086433e-01],
|
|
318
|
+
[-9.31322575e-10, 8.86508557e-02, 1.46782934e-01, ...,
|
|
319
|
+
6.20435820e-01, 7.15149704e-01, 1.23890466e+00]])
|
|
320
|
+
"""
|
|
321
|
+
pos = __convert_pos(atoms)
|
|
322
|
+
m = [msd(p) for p in pos]
|
|
323
|
+
return np.array(m)
|