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
1.2.6. SInce Qsymm is an optional dependency of Kwant, this
backwards-incompatible change only affects Kwant users who use it.
- 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
import copy
from functools import total_ordering, wraps, update_wrapper
from itertools import islice, chain
import numbers
import inspect
import tinyarray as ta
import numpy as np
......@@ -499,8 +500,27 @@ def herm_conj(value):
"""
if hasattr(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()
return value
......
......@@ -241,11 +241,17 @@ def test_construction_and_indexing():
unknown_hoppings, sym)
def test_hermitian_conjugation():
def f(i, j, arg):
@pytest.mark.parametrize('value', (
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
if j[0] == i[0] + 1:
return arg * ta.array([[1, 2j], [3 + 1j, 4j]])
return value
else:
raise ValueError
......@@ -256,8 +262,13 @@ def test_hermitian_conjugation():
syst[fam(0), fam(1)] = f
assert syst[fam(0), fam(1)] is f
assert isinstance(syst[fam(1), fam(0)], builder.HermConjOfFunc)
assert (syst[fam(1), fam(0)](fam(1), fam(0), 2) ==
syst[fam(0), fam(1)](fam(0), fam(1), 2).conjugate().transpose())
assert np.all(
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)]
assert isinstance(syst[fam(0), fam(1)], builder.HermConjOfFunc)
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