@@ -32,7 +32,6 @@ def __init__(self, dimension: int = 1):
3232 The dimension of the observed data.
3333 """
3434 self ._dimension = dimension
35- self .atoms = None
3635
3736 def __call__ (self , atoms : Atoms , * args , ** kwargs ) -> list [float ]:
3837 """
@@ -53,37 +52,33 @@ def __call__(self, atoms: Atoms, *args, **kwargs) -> list[float]:
5352 The observed value, with dimensions atoms by self.dimension.
5453 """
5554
56- @property
57- def dimension (self ):
55+ def value_count (self , n_atoms : int | None = None ) -> int :
5856 """
59- Dimension of the observable. Commensurate with self.__call__.
57+ Count of values returned by __call__.
58+
59+ Parameters
60+ ----------
61+ n_atoms : int | None
62+ Atom count to expand atoms_slice.
6063
6164 Returns
6265 -------
6366 int
64- Observables dimension .
67+ The number of values returned by __call__ .
6568 """
66- return self ._dimension
69+ return self .dimension
6770
68- def atom_count (self , n_atoms : int ):
71+ @property
72+ def dimension (self ):
6973 """
70- Atom count to average over.
71-
72- Parameters
73- ----------
74- n_atoms : int
75- Total possible atoms.
74+ Dimension of the observable. Commensurate with self.__call__.
7675
7776 Returns
7877 -------
7978 int
80- Atom count averaged over .
79+ Observables dimension .
8180 """
82- if self .atoms :
83- if isinstance (self .atoms , list ):
84- return len (self .atoms )
85- return slicelike_len_for (self .n_atoms )
86- return 0
81+ return self ._dimension
8782
8883
8984class ComponentMixin :
@@ -163,18 +158,28 @@ class Stress(Observable, ComponentMixin):
163158 ----------
164159 components : list[str]
165160 Symbols for correlated tensor components, xx, yy, etc.
161+ atoms_slice : list[int] | SliceLike | None = None
162+ List or slice of atoms to observe velocities from.
166163 include_ideal_gas : bool
167164 Calculate with the ideal gas contribution.
168165 """
169166
170- def __init__ (self , components : list [str ], * , include_ideal_gas : bool = True ):
167+ def __init__ (
168+ self ,
169+ * ,
170+ components : list [str ],
171+ atoms_slice : list [int ] | SliceLike | None = None ,
172+ include_ideal_gas : bool = True ,
173+ ):
171174 """
172175 Initialise the observable from a symbolic str component.
173176
174177 Parameters
175178 ----------
176179 components : list[str]
177180 Symbols for tensor components, xx, yy, etc.
181+ atoms_slice : list[int] | SliceLike | None = None
182+ List or slice of atoms to observe velocities from.
178183 include_ideal_gas : bool
179184 Calculate with the ideal gas contribution.
180185 """
@@ -194,6 +199,11 @@ def __init__(self, components: list[str], *, include_ideal_gas: bool = True):
194199 )
195200 self ._set_components (components )
196201
202+ if atoms_slice :
203+ self .atoms_slice = atoms_slice
204+ else :
205+ self .atoms_slice = slice (0 , None , 1 )
206+
197207 Observable .__init__ (self , len (components ))
198208 self .include_ideal_gas = include_ideal_gas
199209
@@ -215,14 +225,18 @@ def __call__(self, atoms: Atoms, *args, **kwargs) -> list[float]:
215225 list[float]
216226 The stress components in GPa units.
217227 """
228+ sliced_atoms = atoms [self .atoms_slice ]
229+ sliced_atoms .calc = atoms .calc
218230 return (
219- atoms .get_stress (include_ideal_gas = self .include_ideal_gas , voigt = True )
231+ sliced_atoms .get_stress (
232+ include_ideal_gas = self .include_ideal_gas , voigt = True
233+ )
220234 / units .GPa
221235 )[self ._indices ]
222236
223237
224- StressDiagonal = Stress (["xx" , "yy" , "zz" ])
225- ShearStress = Stress (["xy" , "yz" , "zx" ])
238+ StressDiagonal = Stress (components = ["xx" , "yy" , "zz" ])
239+ ShearStress = Stress (components = ["xy" , "yz" , "zx" ])
226240
227241
228242# pylint: disable=too-few-public-methods
@@ -234,14 +248,15 @@ class Velocity(Observable, ComponentMixin):
234248 ----------
235249 components : list[str]
236250 Symbols for velocity components, x, y, z.
237- atoms : Optional[Union[ list[int], SliceLike]]
251+ atoms_slice : list[int] | SliceLike | None = None
238252 List or slice of atoms to observe velocities from.
239253 """
240254
241255 def __init__ (
242256 self ,
257+ * ,
243258 components : list [str ],
244- atoms : list [int ] | SliceLike | None = None ,
259+ atoms_slice : list [int ] | SliceLike | None = None ,
245260 ):
246261 """
247262 Initialise the observable from a symbolic str component and atom index.
@@ -250,17 +265,18 @@ def __init__(
250265 ----------
251266 components : list[str]
252267 Symbols for tensor components, x, y, and z.
253- atoms : Union[list[int], SliceLike]
268+ atoms_slice : Union[list[int], SliceLike]
254269 List or slice of atoms to observe velocities from.
255270 """
256271 ComponentMixin .__init__ (self , components = {"x" : 0 , "y" : 1 , "z" : 2 })
257272 self ._set_components (components )
258273
259274 Observable .__init__ (self , len (components ))
260- if atoms :
261- self .atoms = atoms
275+
276+ if atoms_slice :
277+ self .atoms_slice = atoms_slice
262278 else :
263- atoms = slice (None , None , None )
279+ self . atoms_slice = slice (0 , None , 1 )
264280
265281 def __call__ (self , atoms : Atoms , * args , ** kwargs ) -> list [float ]:
266282 """
@@ -280,4 +296,22 @@ def __call__(self, atoms: Atoms, *args, **kwargs) -> list[float]:
280296 list[float]
281297 The velocity values.
282298 """
283- return atoms .get_velocities ()[self .atoms , :][:, self ._indices ].flatten ()
299+ return atoms .get_velocities ()[self .atoms_slice , :][:, self ._indices ].flatten ()
300+
301+ def value_count (self , n_atoms : int | None = None ) -> int :
302+ """
303+ Count of values returned by __call__.
304+
305+ Parameters
306+ ----------
307+ n_atoms : int | None
308+ Atom count to expand atoms_slice.
309+
310+ Returns
311+ -------
312+ int
313+ The number of values returned by __call__.
314+ """
315+ if isinstance (self .atoms_slice , list ):
316+ return len (self .atoms_slice ) * self .dimension
317+ return slicelike_len_for (self .atoms_slice , self .n_atoms ) * self .dimension
0 commit comments