r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import numpy as np

4def distance(s1, s2, permute=True):

5 """Get the distance between two structures s1 and s2.

7 The distance is defined by the Frobenius norm of

8 the spatial distance between all coordinates (see

9 numpy.linalg.norm for the definition).

11 permute: minimise the distance by 'permuting' same elements

12 """

14 s1 = s1.copy()

15 s2 = s2.copy()

16 for s in [s1, s2]:

17 s.translate(-s.get_center_of_mass())

18 s2pos = 1. * s2.get_positions()

20 def align(struct, xaxis='x', yaxis='y'):

21 """Align moments of inertia with the coordinate system."""

22 Is, Vs = struct.get_moments_of_inertia(True)

23 IV = list(zip(Is, Vs))

24 IV.sort(key=lambda x: x[0])

25 struct.rotate(IV[0][1], xaxis)

27 Is, Vs = struct.get_moments_of_inertia(True)

28 IV = list(zip(Is, Vs))

29 IV.sort(key=lambda x: x[0])

30 struct.rotate(IV[1][1], yaxis)

32 align(s1)

34 def dd(s1, s2, permute):

35 if permute:

36 s2 = s2.copy()

37 dist = 0

38 for a in s1:

39 imin = None

40 dmin = np.Inf

41 for i, b in enumerate(s2):

42 if a.symbol == b.symbol:

43 d = np.sum((a.position - b.position)**2)

44 if d < dmin:

45 dmin = d

46 imin = i

47 dist += dmin

48 s2.pop(imin)

49 return np.sqrt(dist)

50 else:

51 return np.linalg.norm(s1.get_positions() - s2.get_positions())

53 dists = []

54 # principles

55 for x, y in zip(['x', '-x', 'x', '-x'], ['y', 'y', '-y', '-y']):

56 s2.set_positions(s2pos)

57 align(s2, x, y)

58 dists.append(dd(s1, s2, permute))

60 return min(dists)