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

Merge branch 'fix/406-conjugate_array_like' into 'stable'

Transpose array-like in herm_conj

See merge request !387
parents 7f5a7dc0 cfe786b1
Pipeline #75212 failed with stages
in 36 minutes and 57 seconds
...@@ -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.
...@@ -13,6 +13,7 @@ import collections ...@@ -13,6 +13,7 @@ import collections
import copy import copy
from functools import total_ordering, wraps, update_wrapper from functools import total_ordering, wraps, update_wrapper
from itertools import islice, chain from itertools import islice, chain
import numbers
import inspect import inspect
import tinyarray as ta import tinyarray as ta
import numpy as np import numpy as np
...@@ -499,8 +500,27 @@ def herm_conj(value): ...@@ -499,8 +500,27 @@ def herm_conj(value):
""" """
if hasattr(value, 'conjugate'): if hasattr(value, 'conjugate'):
value = value.conjugate() value = value.conjugate()
if hasattr(value, 'transpose'): elif not isinstance(value, numbers.Number):
# Fallback for the case of array-like: see issue 406
# https://gitlab.kwant-project.org/kwant/kwant/-/issues/406
# If we get a list of lists or another array-like, conjugate()
# attribute won't be present. To be able to conjugate them, we try to
# convert them to tinyarrays
try:
value = ta.array(value).conjugate()
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() value = value.transpose()
return value return value
......
...@@ -241,11 +241,17 @@ def test_construction_and_indexing(): ...@@ -241,11 +241,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
...@@ -256,8 +262,13 @@ def test_hermitian_conjugation(): ...@@ -256,8 +262,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
......
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