0
# Core Classes
1
2
DScribe's core classes provide enhanced functionality for representing atomic systems and lattices beyond the standard ASE (Atomic Simulation Environment) library. These classes form the foundation for efficient descriptor calculations.
3
4
## Capabilities
5
6
### System Class
7
8
The System class extends ASE's Atoms class with caching capabilities for time-consuming calculations that are shared across multiple descriptors. This optimization significantly improves performance when computing multiple descriptors for the same atomic structure.
9
10
```python { .api }
11
class System:
12
def __init__(self, symbols=None, positions=None, numbers=None, tags=None, momenta=None,
13
masses=None, magmoms=None, charges=None, scaled_positions=None,
14
cell=None, pbc=None, celldisp=None, constraint=None, calculator=None,
15
info=None, wyckoff_positions=None, equivalent_atoms=None):
16
"""
17
Initialize System with same parameters as ASE Atoms.
18
19
Parameters:
20
- symbols: Chemical symbols or atomic numbers
21
- positions: Atomic coordinates in Cartesian form
22
- numbers: Atomic numbers
23
- tags: Integer tags for atoms
24
- momenta: Atomic momenta
25
- masses: Atomic masses
26
- magmoms: Magnetic moments
27
- charges: Atomic charges
28
- scaled_positions: Fractional coordinates
29
- cell: Unit cell vectors
30
- pbc: Periodic boundary conditions
31
- celldisp: Cell displacement
32
- constraint: Geometric constraints
33
- calculator: Attached calculator
34
- info: Additional information dictionary
35
- wyckoff_positions: Wyckoff position labels
36
- equivalent_atoms: Equivalent atom groupings
37
"""
38
39
@staticmethod
40
def from_atoms(atoms):
41
"""
42
Create System from ASE Atoms object.
43
44
Parameters:
45
- atoms: ASE Atoms object
46
47
Returns:
48
System: New System object with same properties as input
49
"""
50
51
def get_cell_inverse(self):
52
"""
53
Get inverse of the lattice matrix.
54
55
Returns:
56
numpy.ndarray: 3x3 inverse lattice matrix
57
"""
58
59
def to_scaled(self, positions, wrap=False):
60
"""
61
Transform Cartesian positions to fractional coordinates.
62
63
Parameters:
64
- positions: Cartesian coordinates to transform
65
- wrap (bool): Whether to wrap coordinates to [0,1) range
66
67
Returns:
68
numpy.ndarray: Fractional coordinates
69
"""
70
71
def to_cartesian(self, scaled_positions, wrap=False):
72
"""
73
Transform fractional coordinates to Cartesian positions.
74
75
Parameters:
76
- scaled_positions: Fractional coordinates to transform
77
- wrap (bool): Whether to wrap coordinates before transformation
78
79
Returns:
80
numpy.ndarray: Cartesian coordinates
81
"""
82
83
def get_displacement_tensor(self):
84
"""
85
Get pairwise displacement vectors between all atoms.
86
87
Returns:
88
numpy.ndarray: 3D array with shape (n_atoms, n_atoms, 3) containing
89
displacement vectors from atom i to atom j
90
"""
91
92
def get_distance_matrix(self):
93
"""
94
Get pairwise distance matrix between all atoms.
95
96
Returns:
97
numpy.ndarray: 2D array with shape (n_atoms, n_atoms) containing
98
distances between all atom pairs
99
"""
100
101
def get_distance_matrix_within_radius(self, radius, pos=None, output_type="coo_matrix"):
102
"""
103
Get sparse distance matrix containing only distances within cutoff radius.
104
105
Parameters:
106
- radius (float): Cutoff radius in angstroms
107
- pos: Positions to use (defaults to atomic positions)
108
- output_type (str): Output format ("coo_matrix", "dense")
109
110
Returns:
111
scipy.sparse matrix or numpy.ndarray: Sparse or dense distance matrix
112
"""
113
114
def get_inverse_distance_matrix(self):
115
"""
116
Get inverse distance matrix (1/r_ij) between all atoms.
117
118
Returns:
119
numpy.ndarray: 2D array with shape (n_atoms, n_atoms)
120
"""
121
```
122
123
**Usage Example:**
124
125
```python
126
from dscribe.core import System
127
from ase.build import molecule, bulk
128
129
# Create System from ASE Atoms
130
atoms = molecule("H2O")
131
system = System.from_atoms(atoms)
132
133
# Direct creation with parameters
134
system = System(
135
symbols=["H", "H", "O"],
136
positions=[[0.0, 0.757, 0.587], [0.0, -0.757, 0.587], [0.0, 0.0, -0.074]]
137
)
138
139
# Use enhanced methods
140
distance_matrix = system.get_distance_matrix()
141
sparse_distances = system.get_distance_matrix_within_radius(3.0)
142
displacement_vectors = system.get_displacement_tensor()
143
144
# Work with periodic systems
145
bulk_system = System.from_atoms(bulk("NaCl", "rocksalt", a=5.64))
146
fractional_coords = bulk_system.to_scaled(bulk_system.positions)
147
cartesian_coords = bulk_system.to_cartesian(fractional_coords)
148
```
149
150
### Lattice Class
151
152
The Lattice class represents crystallographic unit cells and provides methods for coordinate transformations between Cartesian and fractional coordinate systems.
153
154
```python { .api }
155
class Lattice:
156
def __init__(self, matrix):
157
"""
158
Initialize Lattice from lattice matrix.
159
160
Parameters:
161
- matrix: 3x3 lattice matrix or 9-element sequence representing lattice vectors
162
"""
163
164
@property
165
def matrix(self):
166
"""
167
Copy of the lattice matrix.
168
169
Returns:
170
numpy.ndarray: 3x3 lattice matrix
171
"""
172
173
@property
174
def inv_matrix(self):
175
"""
176
Inverse of the lattice matrix.
177
178
Returns:
179
numpy.ndarray: 3x3 inverse lattice matrix
180
"""
181
182
@property
183
def lengths(self):
184
"""
185
Lengths of lattice vectors.
186
187
Returns:
188
numpy.ndarray: Array of lattice vector lengths [a, b, c]
189
"""
190
191
@property
192
def abc(self):
193
"""
194
Tuple of lattice lengths.
195
196
Returns:
197
tuple: Lattice lengths (a, b, c)
198
"""
199
200
@property
201
def reciprocal_lattice(self):
202
"""
203
Reciprocal lattice with 2π factor.
204
205
Returns:
206
Lattice: Reciprocal lattice object
207
"""
208
209
@property
210
def reciprocal_lattice_crystallographic(self):
211
"""
212
Crystallographic reciprocal lattice (without 2π factor).
213
214
Returns:
215
Lattice: Crystallographic reciprocal lattice object
216
"""
217
218
def get_cartesian_coords(self, fractional_coords):
219
"""
220
Convert fractional coordinates to Cartesian coordinates.
221
222
Parameters:
223
- fractional_coords: Fractional coordinates to convert
224
225
Returns:
226
numpy.ndarray: Cartesian coordinates
227
"""
228
229
def get_fractional_coords(self, cart_coords):
230
"""
231
Convert Cartesian coordinates to fractional coordinates.
232
233
Parameters:
234
- cart_coords: Cartesian coordinates to convert
235
236
Returns:
237
numpy.ndarray: Fractional coordinates
238
"""
239
240
def get_points_in_sphere(self, frac_points, center, r, zip_results=True):
241
"""
242
Find all points within a sphere considering periodic boundary conditions.
243
244
Parameters:
245
- frac_points: Fractional coordinates of points to search
246
- center: Center point in fractional coordinates
247
- r (float): Search radius in angstroms
248
- zip_results (bool): Whether to zip results together
249
250
Returns:
251
list or tuple: Points within sphere, optionally with distances and indices
252
"""
253
```
254
255
**Usage Example:**
256
257
```python
258
from dscribe.core import Lattice
259
import numpy as np
260
261
# Create lattice from matrix
262
lattice_matrix = np.array([
263
[5.0, 0.0, 0.0],
264
[0.0, 5.0, 0.0],
265
[0.0, 0.0, 5.0]
266
])
267
lattice = Lattice(lattice_matrix)
268
269
# Access properties
270
print(f"Lattice lengths: {lattice.abc}")
271
print(f"Volume: {np.linalg.det(lattice.matrix)}")
272
273
# Coordinate conversions
274
fractional_coords = np.array([[0.5, 0.5, 0.5], [0.0, 0.0, 0.0]])
275
cartesian_coords = lattice.get_cartesian_coords(fractional_coords)
276
back_to_fractional = lattice.get_fractional_coords(cartesian_coords)
277
278
# Find neighbors within sphere
279
center = np.array([0.5, 0.5, 0.5])
280
points_in_sphere = lattice.get_points_in_sphere(
281
fractional_coords, center, radius=2.0
282
)
283
284
# Work with reciprocal lattice
285
reciprocal = lattice.reciprocal_lattice
286
reciprocal_crystallographic = lattice.reciprocal_lattice_crystallographic
287
```
288
289
## Integration with Descriptors
290
291
### System Caching Benefits
292
293
The System class provides significant performance improvements through caching:
294
295
- **Distance matrices**: Computed once and reused across multiple descriptors
296
- **Displacement tensors**: Cached for efficient neighbor finding
297
- **Coordinate transformations**: Fractional/Cartesian conversions are cached
298
- **Inverse matrices**: Cell inverse calculations are cached
299
300
This is especially beneficial when computing multiple descriptors for the same structure:
301
302
```python
303
from dscribe import System
304
from dscribe.descriptors import SOAP, ACSF
305
from ase.build import molecule
306
307
# Create system once
308
water = System.from_atoms(molecule("H2O"))
309
310
# Multiple descriptors benefit from shared caching
311
soap = SOAP(species=["H", "O"], r_cut=5.0, n_max=8, l_max=6)
312
acsf = ACSF(species=["H", "O"], r_cut=6.0, g2_params=[[1, 1], [1, 2]])
313
314
# Distance calculations are shared between descriptors
315
soap_desc = soap.create(water) # Distance matrix computed and cached
316
acsf_desc = acsf.create(water) # Reuses cached distance matrix
317
```
318
319
### Lattice Usage in Descriptors
320
321
The Lattice class is used internally by descriptors for periodic systems:
322
323
- **Coordinate transformations**: Converting between fractional and Cartesian coordinates
324
- **Neighbor finding**: Finding atoms within cutoff radii across periodic boundaries
325
- **Cell extensions**: Creating extended unit cells for local environment calculations
326
327
## Compatibility with ASE
328
329
Both System and Lattice classes maintain full compatibility with ASE:
330
331
- **System**: Can be used anywhere ASE Atoms objects are accepted
332
- **Lattice**: Provides enhanced functionality for unit cell operations
333
- **Conversion**: Easy conversion between DScribe and ASE objects
334
335
This compatibility ensures that DScribe integrates seamlessly with the broader Python materials science ecosystem.