Coverage for ase / constraints / fixed_line.py: 100.00%

17 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-30 08:22 +0000

1from ase.constraints.constraint import ( 

2 IndexedConstraint, 

3 _normalize, 

4 _projection, 

5) 

6 

7 

8class FixedLine(IndexedConstraint): 

9 """ 

10 Constrain an atom index or a list of atom indices to move on a line only. 

11 

12 The line is defined by its vector *direction* 

13 """ 

14 

15 def __init__(self, indices, direction): 

16 """Constrain chosen atoms. 

17 

18 Parameters 

19 ---------- 

20 indices : int or list of int 

21 Index or indices for atoms that should be constrained 

22 direction : list of 3 int 

23 Direction of the vector defining the line 

24 

25 Examples 

26 -------- 

27 Fix all Copper atoms to only move in the x-direction: 

28 

29 >>> from ase.constraints import FixedLine 

30 >>> c = FixedLine( 

31 ... indices=[atom.index for atom in atoms if atom.symbol == 'Cu'], 

32 ... direction=[1, 0, 0], 

33 ... ) 

34 >>> atoms.set_constraint(c) 

35 

36 or constrain a single atom with the index 0 to move in the z-direction: 

37 

38 >>> c = FixedLine(indices=0, direction=[0, 0, 1]) 

39 >>> atoms.set_constraint(c) 

40 """ 

41 super().__init__(indices) 

42 self.dir = _normalize(direction) 

43 

44 def adjust_positions(self, atoms, newpositions): 

45 step = newpositions[self.index] - atoms.positions[self.index] 

46 projection = _projection(step, self.dir) 

47 newpositions[self.index] = atoms.positions[self.index] + projection 

48 

49 def adjust_forces(self, atoms, forces): 

50 forces[self.index] = _projection(forces[self.index], self.dir) 

51 

52 def get_removed_dof(self, atoms): 

53 return 2 * len(self.index) 

54 

55 def __repr__(self): 

56 return f'FixedLine(indices={self.index}, {self.dir.tolist()})' 

57 

58 def todict(self): 

59 return { 

60 'name': 'FixedLine', 

61 'kwargs': { 

62 'indices': self.index.tolist(), 

63 'direction': self.dir.tolist(), 

64 }, 

65 }