Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
K
kwant
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Michael Wimmer
kwant
Commits
4d88fdf9
Commit
4d88fdf9
authored
11 years ago
by
Anton Akhmerov
Committed by
Christoph Groth
11 years ago
Browse files
Options
Downloads
Patches
Plain Diff
clean-up of TranslationalSymmetry.add_site_family
parent
560a139d
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
kwant/lattice.py
+53
-29
53 additions, 29 deletions
kwant/lattice.py
kwant/tests/test_lattice.py
+33
-15
33 additions, 15 deletions
kwant/tests/test_lattice.py
with
86 additions
and
44 deletions
kwant/lattice.py
+
53
−
29
View file @
4d88fdf9
...
...
@@ -502,71 +502,95 @@ class TranslationalSymmetry(builder.Symmetry):
self
.
site_family_data
=
{}
self
.
is_reversed
=
False
def
add_site_family
(
self
,
gr
,
other_vectors
=
None
):
def
add_site_family
(
self
,
fam
,
other_vectors
=
None
):
"""
Select a fundamental domain for site family and cache associated data.
Parameters
----------
gr
: `SiteFamily`
fam
: `SiteFamily`
the site family which has to be processed. Be sure to delete the
previously processed site families from `site_family_data` if you
want to modify the cache.
other_vectors : list of lists of integers
Bravais lattice vectors used to complement the periods in forming
a basis. The fundamental domain belongs to the linear space
spanned by these vectors.
a basis. The fundamental domain consists of all the lattice sites
for which the zero coefficients corresponding to the symmetry
periods in the basis formed by the symmetry periods and
`other_vectors`. If an insufficient number of `other_vectors` is
provided to form a basis, the missing ones are selected
automatically.
Raises
------
KeyError
If `
gr
` is already stored in `site_family_data`.
If `
fam
` is already stored in `site_family_data`.
ValueError
If lattice
shape of `gr` cannot have
th
e
given
`
periods
`
.
If lattice
`fam` is incompatible wi
th given periods.
"""
if
gr
in
self
.
site_family_data
:
dim
=
self
.
_periods
.
shape
[
1
]
if
fam
in
self
.
site_family_data
:
raise
KeyError
(
'
Family already processed, delete it from
'
'
site_family_data first.
'
)
inv
=
np
.
linalg
.
pinv
(
gr
.
prim_vecs
)
bravais_periods
=
[
np
.
dot
(
i
,
inv
)
for
i
in
self
.
_periods
]
inv
=
np
.
linalg
.
pinv
(
fam
.
prim_vecs
)
bravais_periods
=
np
.
dot
(
self
.
_periods
,
inv
)
# Absolute tolerance is correct in the following since we want an error
# relative to the closest integer.
if
not
np
.
allclose
(
bravais_periods
,
np
.
round
(
bravais_periods
),
rtol
=
0
,
atol
=
1e-8
)
or
\
not
np
.
allclose
([
gr
.
vec
(
i
)
for
i
in
bravais_periods
],
not
np
.
allclose
([
fam
.
vec
(
i
)
for
i
in
bravais_periods
],
self
.
_periods
):
msg
=
'
Site family {0} does not have commensurate periods with
'
+
\
'
symmetry {1}.
'
raise
ValueError
(
msg
.
format
(
gr
,
self
))
raise
ValueError
(
msg
.
format
(
fam
,
self
))
bravais_periods
=
np
.
array
(
np
.
round
(
bravais_periods
),
dtype
=
'
int
'
)
(
num_dir
,
dim
)
=
bravais_periods
.
shape
(
num_dir
,
lat_
dim
)
=
bravais_periods
.
shape
if
other_vectors
is
None
:
other_vectors
=
[]
for
vec
in
other_vectors
:
for
a
in
vec
:
if
not
isinstance
(
a
,
int
):
raise
ValueError
(
'
Only integer other_vectors are allowed.
'
)
m
=
np
.
zeros
((
dim
,
dim
),
dtype
=
int
)
m
.
T
[:
num_dir
]
=
bravais_periods
other_vectors
=
np
.
zeros
((
0
,
lat_dim
),
dtype
=
int
)
else
:
other_vectors
=
np
.
array
(
other_vectors
)
if
np
.
any
(
np
.
round
(
other_vectors
)
-
other_vectors
):
raise
ValueError
(
'
Only integer other_vectors are allowed.
'
)
other_vectors
=
np
.
array
(
np
.
round
(
other_vectors
),
dtype
=
int
)
m
=
np
.
zeros
((
lat_dim
,
lat_dim
),
dtype
=
int
)
m
.
T
[:
num_dir
]
=
bravais_periods
num_vec
=
num_dir
+
len
(
other_vectors
)
if
len
(
other_vectors
)
!=
0
:
m
.
T
[
num_dir
:
num_vec
]
=
other_vectors
norms
=
np
.
apply_along_axis
(
np
.
linalg
.
norm
,
1
,
m
)
indices
=
np
.
argsort
(
norms
)
for
coord
in
zip
(
indices
,
range
(
num_vec
,
dim
)):
m
[
coord
]
=
1
m
.
T
[
num_dir
:
num_vec
]
=
other_vectors
if
np
.
linalg
.
matrix_rank
(
m
)
<
num_vec
:
raise
ValueError
(
'
other_vectors and symmetry periods are not
'
'
linearly independent.
'
)
# To define the fundamental domain of the new site family we now need to
# choose `lat_dim - num_vec` extra lattice vectors that are not
# linearly dependent on the vectors we already have. To do so we
# continuously add the lattice basis vectors one by one such that they
# are not linearly dependent on the existent vectors
while
num_vec
<
lat_dim
:
vh
=
np
.
linalg
.
svd
(
np
.
dot
(
m
[:,
:
num_vec
].
T
,
fam
.
prim_vecs
),
full_matrices
=
False
)[
2
]
projector
=
np
.
identity
(
dim
)
-
np
.
dot
(
vh
.
T
,
vh
)
residuals
=
np
.
dot
(
fam
.
prim_vecs
,
projector
)
residuals
=
np
.
apply_along_axis
(
np
.
linalg
.
norm
,
1
,
residuals
)
m
[
np
.
argmax
(
residuals
),
num_vec
]
=
1
num_vec
+=
1
det_m
=
int
(
round
(
np
.
linalg
.
det
(
m
)))
if
det_m
==
0
:
raise
RuntimeError
(
'
Adding site group failed.
'
)
print
m
raise
RuntimeError
(
'
Adding site family failed.
'
)
det_x_inv_m
=
\
np
.
array
(
np
.
round
(
det_m
*
np
.
linalg
.
inv
(
m
)),
dtype
=
int
)
assert
(
np
.
dot
(
m
,
det_x_inv_m
)
//
det_m
==
np
.
identity
(
dim
)).
all
()
assert
(
np
.
dot
(
m
,
det_x_inv_m
)
//
det_m
==
np
.
identity
(
lat_
dim
)).
all
()
det_x_inv_m_part
=
det_x_inv_m
[:
num_dir
,
:]
m_part
=
m
[:,
:
num_dir
]
self
.
site_family_data
[
gr
]
=
(
ta
.
array
(
m_part
),
self
.
site_family_data
[
fam
]
=
(
ta
.
array
(
m_part
),
ta
.
array
(
det_x_inv_m_part
),
det_m
)
@property
...
...
This diff is collapsed.
Click to expand it.
kwant/tests/test_lattice.py
+
33
−
15
View file @
4d88fdf9
...
...
@@ -103,35 +103,35 @@ def test_wire():
def
test_translational_symmetry
():
ts
=
lattice
.
TranslationalSymmetry
g
2
=
lattice
.
general
(
np
.
identity
(
2
))
g
3
=
lattice
.
general
(
np
.
identity
(
3
))
f
2
=
lattice
.
general
(
np
.
identity
(
2
))
f
3
=
lattice
.
general
(
np
.
identity
(
3
))
shifted
=
lambda
site
,
delta
:
site
.
family
(
*
ta
.
add
(
site
.
tag
,
delta
))
assert_raises
(
ValueError
,
ts
,
(
0
,
0
,
4
),
(
0
,
5
,
0
),
(
0
,
0
,
2
))
sym
=
ts
((
3.3
,
0
))
assert_raises
(
ValueError
,
sym
.
add_site_family
,
g
2
)
assert_raises
(
ValueError
,
sym
.
add_site_family
,
f
2
)
# Test lattices with dimension smaller than dimension of space.
g
2in3
=
lattice
.
general
([[
4
,
4
,
0
],
[
4
,
-
4
,
0
]])
f
2in3
=
lattice
.
general
([[
4
,
4
,
0
],
[
4
,
-
4
,
0
]])
sym
=
ts
((
8
,
0
,
0
))
sym
.
add_site_family
(
g
2in3
)
sym
.
add_site_family
(
f
2in3
)
sym
=
ts
((
8
,
0
,
1
))
assert_raises
(
ValueError
,
sym
.
add_site_family
,
g
2in3
)
assert_raises
(
ValueError
,
sym
.
add_site_family
,
f
2in3
)
# Test automatic fill-in of transverse vectors.
sym
=
ts
((
1
,
2
))
sym
.
add_site_family
(
g
2
)
assert_not_equal
(
sym
.
site_family_data
[
g
2
][
2
],
0
)
sym
.
add_site_family
(
f
2
)
assert_not_equal
(
sym
.
site_family_data
[
f
2
][
2
],
0
)
sym
=
ts
((
1
,
0
,
2
),
(
3
,
0
,
2
))
sym
.
add_site_family
(
g
3
)
assert_not_equal
(
sym
.
site_family_data
[
g
3
][
2
],
0
)
sym
.
add_site_family
(
f
3
)
assert_not_equal
(
sym
.
site_family_data
[
f
3
][
2
],
0
)
transl_vecs
=
np
.
array
([[
10
,
0
],
[
7
,
7
]],
dtype
=
int
)
sym
=
ts
(
*
transl_vecs
)
assert_equal
(
sym
.
num_directions
,
2
)
sym2
=
ts
(
*
transl_vecs
[:
1
,
:])
sym2
.
add_site_family
(
g
2
,
transl_vecs
[
1
:,
:])
for
site
in
[
g
2
(
0
,
0
),
g
2
(
4
,
0
),
g
2
(
2
,
1
),
g
2
(
5
,
5
),
g
2
(
15
,
6
)]:
sym2
.
add_site_family
(
f
2
,
transl_vecs
[
1
:,
:])
for
site
in
[
f
2
(
0
,
0
),
f
2
(
4
,
0
),
f
2
(
2
,
1
),
f
2
(
5
,
5
),
f
2
(
15
,
6
)]:
assert
sym
.
in_fd
(
site
)
assert
sym2
.
in_fd
(
site
)
assert_equal
(
sym
.
which
(
site
),
(
0
,
0
))
...
...
@@ -150,10 +150,28 @@ def test_translational_symmetry():
(
site
,
shifted
(
site
,
hop
)))
# Test act for hoppings belonging to different lattices.
g
2p
=
lattice
.
general
(
2
*
np
.
identity
(
2
))
f
2p
=
lattice
.
general
(
2
*
np
.
identity
(
2
))
sym
=
ts
(
*
(
2
*
np
.
identity
(
2
)))
assert
sym
.
act
((
1
,
1
),
g2
(
0
,
0
),
g2p
(
0
,
0
))
==
(
g2
(
2
,
2
),
g2p
(
1
,
1
))
assert
sym
.
act
((
1
,
1
),
g2p
(
0
,
0
),
g2
(
0
,
0
))
==
(
g2p
(
1
,
1
),
g2
(
2
,
2
))
assert
sym
.
act
((
1
,
1
),
f2
(
0
,
0
),
f2p
(
0
,
0
))
==
(
f2
(
2
,
2
),
f2p
(
1
,
1
))
assert
sym
.
act
((
1
,
1
),
f2p
(
0
,
0
),
f2
(
0
,
0
))
==
(
f2p
(
1
,
1
),
f2
(
2
,
2
))
# Test add_site_family on random lattices and symmetries by ensuring that
# it's possible to add site groups that are compatible with a randomly
# generated symmetry with proper vectors.
np
.
random
.
seed
(
30
)
vec
=
np
.
random
.
randn
(
3
,
5
)
lat
=
lattice
.
general
(
vec
)
total
=
0
for
k
in
range
(
1
,
4
):
for
i
in
range
(
10
):
sym_vec
=
np
.
random
.
randint
(
-
10
,
10
,
size
=
(
k
,
3
))
if
np
.
linalg
.
matrix_rank
(
sym_vec
)
<
k
:
continue
total
+=
1
sym_vec
=
np
.
dot
(
sym_vec
,
vec
)
sym
=
ts
(
*
sym_vec
)
sym
.
add_site_family
(
lat
)
assert
total
>
20
def
test_translational_symmetry_reversed
():
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment