-
-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fixed #633 due to weird combination of boundary lookups #634
Conversation
I have found the issue. In some rare cases the algorithm would search radii just crossing the boundaries which in the end could result in some atoms being part of the first neighbour circle, but its true neighbours would not be part of the 2nd circle. This was a very subtle issue, and would generally only occur for somewhat large structures. |
Maybe moving to #393 would fix it as well ;) |
Damn, not fixed yet... |
I don't know if that will be stable given I have to prepare for the workshop... |
I'll play a bit more tonight... |
I mean replacing the internals, while keeping the same |
I know. I don't think that is smart to do just before a workshop... It's a big change, and it requires handling the supercell indices in a strict manner. I need more time. |
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #634 +/- ##
=======================================
Coverage 87.73% 87.73%
=======================================
Files 362 362
Lines 48348 48308 -40
=======================================
- Hits 42417 42382 -35
+ Misses 5931 5926 -5
☔ View full report in Codecov by Sentry. |
I am afraid this is not a complete fix. Try this: import sisl
import numpy as np
def test(g, runs=100):
x = []
for i in range(runs):
H = sisl.Hamiltonian(g)
H.construct([(0.1, 3), (1, -2.7)])
x.append(H.nnz)
if x[-1] != x[0]:
print(f"Error encountered after {i+1} runs: {x}")
return
print(f"Success after {runs} runs")
np.random.seed(1234)
g1 = sisl.geom.zgnr(10) * (20, 1, 1)
g2 = sisl.geom.sc(1, sisl.Atom('H', R=1))
g = g1.add(g2)
g.set_nsc([1, 1, 1])
test(g)
print(sisl.__version__) which returns:
|
Yeah, I discovered, see my 2nd comment... :( |
@tfrederiksen could you try now... Please do note, that the problem arises because of the way the search is built. It does a batched search space made of 2 radii. One that is an integer number times the For now there is a warning raised when I have tested ~6 geometries with correct input, and they don't fail... :) |
It looks good to me now. Despite several attempts I couldn't design a case with failure :) Would it make sense to have a test with a critical comparison of import sisl
import numpy as np
def test(g):
T = 1 + np.arange(na)
# close call first
H = sisl.Hamiltonian(g)
for ia in g:
idx = g.close(ia, R=R)
for ja, t in zip(idx, T):
H[ia, ja] = t
x = [H.nnz + np.sum(H)]
# now compare with construct calls
for i in range(10):
for method in ['rand', 'sphere', 'cube']:
H = sisl.Hamiltonian(g)
H.construct([R, T], method=method)
x.append(H.nnz + np.sum(H))
if x[-1] != x[0]:
return False # inconsistency detected
return x[0] # no inconsistency detected
np.random.seed(1234)
# build a random geometry with different orbitals
na = 7
R = 1e-4 + np.arange(na)
atoms = [sisl.Atom('HBCNOFPISK'[i], R=R[i]) for i in range(na)]
g = sisl.geom.fcc(2.5, atoms=atoms[0]) * (4, 3, 2)
g.xyz[:] += 10 * np.random.rand(g.na, 3)
for ia in g:
g.atoms[ia] = atoms[ia % na]
g.reduce()
g.set_nsc([1, 1, 1])
assert test(g) == 1224.0
g.set_nsc([1, 1, 9])
assert test(g) == 4518.0
g.set_nsc([3, 3, 3])
assert test(g) == 18286.0
g2 = g.add(g.move(1e-2)) # put atoms almost on top of each other!
g2.set_nsc([1, 1, 1])
assert test(g2) == 4960.0
g2.set_nsc([1, 1, 3])
assert test(g2) == 13038.0
g3 = g.scale(1e3) # separate atoms by a lot!
g3.set_nsc([1, 1, 3])
assert test(g3) == 2 * g3.na
g4 = g.scale(1e-12) # collapse!
g4.set_nsc([1, 1, 3])
assert test(g4) == 6 * g4.na ** 2 Btw, I noticed some debug lines you may want to remove: Lines 974 to 975 in a6344c4
|
The problem of close arose when the searched sphere was just crossing a border of the unit-cell (or supercell). In those cases could the translated to unit-cell indices miss a neighbour. The fix was rather simple; once the atoms closests has been found, only loop over those in the primary unit-cell. There are many other small changes here, but they are more cosmetic and should provide more stability when using orbital distances very close to atomic coordinates. Signed-off-by: Nick Papior <nickpapior@gmail.com>
…ctly When using R distances larger than the internal ranges then the double sphere used in the iter_block_rand may be wrong. This turns out to be important as some connections won't be reached. Currently, this is fixed for direct construct calls, but not for custom self made ones. As long as the user uses a suitable R range, then it should work fine. Signed-off-by: Nick Papior <nickpapior@gmail.com>
Signed-off-by: Nick Papior <nickpapior@gmail.com>
Signed-off-by: Nick Papior <nickpapior@gmail.com>
Signed-off-by: Nick Papior <nickpapior@gmail.com>
@tfrederiksen thanks for the tests!! I'll see if some of that test can be added, currently there is a test that ensures symmetric construct, it is always hard to know when to cut the line here... |
The problem of close arose when the searched sphere was just crossing a border of the unit-cell (or supercell). In those cases could the translated to unit-cell indices miss a neighbour.
The fix was rather simple; once the atoms closests has been found, only loop over those in the primary unit-cell.
There are many other small changes here, but they
are more cosmetic and should provide more stability when using orbital distances very close to atomic coordinates.
construct
? #633isort .
at top--leveldocs/
CHANGELOG.md
@tfrederiksen might you have a 2nd look here, I tested on some geometries, all seems fine, but this would warrant a 2nd look