Commit e75bf49e authored by Viacheslav Ostroukh's avatar Viacheslav Ostroukh 🚲
Browse files

Merge branch 'stable'

parents 8a6d320b a9fedcf5
Pipeline #74944 passed with stages
in 9 minutes and 1 second
...@@ -346,3 +346,10 @@ Changes in Kwant 1.4.2 ...@@ -346,3 +346,10 @@ Changes in Kwant 1.4.2
1.2.6. SInce Qsymm is an optional dependency of Kwant, this 1.2.6. SInce Qsymm is an optional dependency of Kwant, this
backwards-incompatible change only affects Kwant users who use it. backwards-incompatible change only affects Kwant users who use it.
- Minor bugs were fixed in the KPM module. - Minor bugs were fixed in the KPM module.
Changes after Kwant 1.4.2
-------------------------
- Builder properly handles Hermitian conjugation of array-like values.
Before, if the value was provided not as a true array but, for example, as a
list of lists, it was not conjugated, which could lead to generation of a
non-Hermitian Hamiltonian matrix without emitting any error.
...@@ -174,15 +174,27 @@ def herm_conj(value): ...@@ -174,15 +174,27 @@ def herm_conj(value):
""" """
if hasattr(value, 'conjugate'): if hasattr(value, 'conjugate'):
value = value.conjugate() value = value.conjugate()
if hasattr(value, 'shape'): elif not isinstance(value, numbers.Number):
if len(value.shape) > 2: # Fallback for the case of array-like: see issue 406
is_ta = isinstance(value, ( # https://gitlab.kwant-project.org/kwant/kwant/-/issues/406
ta.ndarray_int, ta.ndarray_float, ta.ndarray_complex)) # If we get a list of lists or another array-like, conjugate()
value = np.swapaxes(value, -1, -2) # attribute won't be present. To be able to conjugate them, we try to
if is_ta: # convert them to tinyarrays
value = ta.array(value) try:
else: value = ta.array(value).conjugate()
value = value.transpose() except Exception:
pass
if hasattr(value, 'shape'):
if len(value.shape) > 2:
is_ta = isinstance(value, (
ta.ndarray_int, ta.ndarray_float, ta.ndarray_complex))
value = np.swapaxes(value, -1, -2)
if is_ta:
value = ta.array(value)
else:
value = value.transpose()
return value return value
......
...@@ -491,6 +491,9 @@ class Monatomic(system.SiteFamily, Polyatomic): ...@@ -491,6 +491,9 @@ class Monatomic(system.SiteFamily, Polyatomic):
sites : numpy array sites : numpy array
An array with sites coordinates. An array with sites coordinates.
""" """
if len(pos) != len(self.offset):
raise ValueError("Incorrect dimensionality of 'pos'.")
# TODO (Anton): transform to tinyarrays, once ta indexing is better. # TODO (Anton): transform to tinyarrays, once ta indexing is better.
return np.dot(lll.cvp(pos - self.offset, self.reduced_vecs, return np.dot(lll.cvp(pos - self.offset, self.reduced_vecs,
n=n, group_by_length=group_by_length, rtol=rtol), n=n, group_by_length=group_by_length, rtol=rtol),
......
...@@ -272,11 +272,17 @@ def test_construction_and_indexing(): ...@@ -272,11 +272,17 @@ def test_construction_and_indexing():
unknown_hoppings, sym) unknown_hoppings, sym)
def test_hermitian_conjugation(): @pytest.mark.parametrize('value', (
def f(i, j, arg): ta.array([[1, 2j], [3 + 1j, 4j]]),
np.array([[1, 2j], [3 + 1j, 4j]]),
[[1, 2j], [3 + 1j, 4j]],
((1, 2j), (3 + 1j, 4j)),
))
def test_hermitian_conjugation(value):
def f(i, j):
i, j = i.tag, j.tag i, j = i.tag, j.tag
if j[0] == i[0] + 1: if j[0] == i[0] + 1:
return arg * ta.array([[1, 2j], [3 + 1j, 4j]]) return value
else: else:
raise ValueError raise ValueError
...@@ -287,8 +293,13 @@ def test_hermitian_conjugation(): ...@@ -287,8 +293,13 @@ def test_hermitian_conjugation():
syst[fam(0), fam(1)] = f syst[fam(0), fam(1)] = f
assert syst[fam(0), fam(1)] is f assert syst[fam(0), fam(1)] is f
assert isinstance(syst[fam(1), fam(0)], builder.HermConjOfFunc) assert isinstance(syst[fam(1), fam(0)], builder.HermConjOfFunc)
assert (syst[fam(1), fam(0)](fam(1), fam(0), 2) == assert np.all(
syst[fam(0), fam(1)](fam(0), fam(1), 2).conjugate().transpose()) np.asarray(
syst[fam(1), fam(0)](fam(1), fam(0))
) == np.asarray(
syst[fam(0), fam(1)](fam(0), fam(1))
).conjugate().transpose()
)
syst[fam(0), fam(1)] = syst[fam(1), fam(0)] syst[fam(0), fam(1)] = syst[fam(1), fam(0)]
assert isinstance(syst[fam(0), fam(1)], builder.HermConjOfFunc) assert isinstance(syst[fam(0), fam(1)], builder.HermConjOfFunc)
assert syst[fam(1), fam(0)] is f assert syst[fam(1), fam(0)] is f
......
...@@ -28,6 +28,9 @@ def test_closest(): ...@@ -28,6 +28,9 @@ def test_closest():
tag = rng.randint(10, size=(3,)) tag = rng.randint(10, size=(3,))
assert lat.closest(lat(*tag).pos) == tag assert lat.closest(lat(*tag).pos) == tag
# Closest should raise if input has a wrong dimensionality
raises(ValueError, lattice.square().closest, [0])
def test_general(): def test_general():
for lat in (lattice.general(((1, 0), (0.5, 0.5)), norbs=1), for lat in (lattice.general(((1, 0), (0.5, 0.5)), norbs=1),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment