Skip to content

Commit 499cb7f

Browse files
committed
Fix argsort_coords
1 parent dba8066 commit 499cb7f

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

pyscf/symm/geom.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def parallel_vectors(v1, v2, tol=TOLERANCE):
5656
cos = numpy.dot(_normalize(v1), _normalize(v2))
5757
return (abs(cos-1) < TOLERANCE) | (abs(cos+1) < TOLERANCE)
5858

59-
def argsort_coords(coords, decimals=None, tol=TOLERANCE):
59+
def argsort_coords(coords, decimals=None, tol=0.05):
6060
# * np.round for decimal places can lead to more errors than the actual
6161
# difference between two numbers. For example,
6262
# np.round([0.1249999999,0.1250000001], 2) => [0.124, 0.125]
@@ -65,19 +65,24 @@ def argsort_coords(coords, decimals=None, tol=TOLERANCE):
6565
# the coordinates might look more different.
6666
# * Using the power of two as the factor can reduce such errors, although not
6767
# faithfully rounding to the required decimals.
68+
# * For normal molecules, tol~=0.1 in coordinates is enough to distinguish
69+
# atoms in molecule. A very tight threshold is not appropriate here. With
70+
# tight threshold, small differences in coordinates may lead to different
71+
# arg orders.
6872
if decimals is None:
69-
fac = 2**int(-numpy.log2(tol) + .5)
73+
fac = 2**int(-numpy.log2(tol))
7074
else:
71-
fac = 2**int(3.3219281 * decimals + .5)
72-
coords = numpy.around(coords*fac)
75+
fac = 2**int(3.3219281 * decimals)
76+
# +.5 for rounding to the nearest integer
77+
coords = (coords*fac + .5).astype(int)
7378
idx = numpy.lexsort((coords[:,2], coords[:,1], coords[:,0]))
7479
return idx
7580

76-
def sort_coords(coords, decimals=None, tol=TOLERANCE):
81+
def sort_coords(coords, decimals=None, tol=0.05):
7782
if decimals is None:
7883
decimals = int(-numpy.log10(tol)) - 1
7984
coords = numpy.asarray(coords)
80-
idx = argsort_coords(coords, decimals=decimals)
85+
idx = argsort_coords(coords, decimals)
8186
return coords[idx]
8287

8388
# ref. http://en.wikipedia.org/wiki/Rotation_matrix
@@ -490,8 +495,8 @@ def symm_identical_atoms(gpname, atoms):
490495
dup_atom_ids = []
491496
for op in ops:
492497
newc = numpy.dot(coords, op)
493-
idx = argsort_coords(newc, tol=TOLERANCE*5)
494-
if not numpy.allclose(coords0, newc[idx], atol=TOLERANCE*5):
498+
idx = argsort_coords(newc)
499+
if not numpy.allclose(coords0, newc[idx], atol=TOLERANCE):
495500
raise PointGroupSymmetryError(
496501
'Symmetry identical atoms not found. This may be due to '
497502
'the strict setting of the threshold symm.geom.TOLERANCE. '

pyscf/symm/test/test_basis.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ def test_symm_orb_c3v_as_cs(self):
163163
['O', ( 0.000000 , 2.572496 , 1.441607 )],
164164
['O', ( 2.227847 , -1.286248 , 1.441607 )],
165165
['O', ( -2.227847 , -1.286248 , 1.441607 )],]
166+
numpy.random.seed(2)
167+
u = numpy.linalg.svd(numpy.random.rand(3,3))[0]
168+
r = numpy.array([a[1] for a in atoms])
169+
atoms = [[a[0], x] for a, x in zip(atoms, r.dot(u))]
166170
basis = {'Fe':gto.basis.load('def2svp', 'C'),
167171
'C': gto.basis.load('def2svp', 'C'),
168172
'H': gto.basis.load('def2svp', 'C'),

0 commit comments

Comments
 (0)